Probleme mit QWizard

Alles rund um die Programmierung mit Qt
Antworten
abenstex
Beiträge: 30
Registriert: 12. September 2006 16:33

Probleme mit QWizard

Beitrag von abenstex »

Ich habe einen Setup-Wizard programmiert mit 5 QWizardPages dazu. Nur das Problem ist, dass der Wizard und auch alles Kostruktoren der QWizardPages aufgerufen werden, aber der Wizard nicht erscheint und ich einfach nicht weiss woran das liegen könnte.
Hier vorsichtshalber die SetupWizard-Klasse:

Code: Alles auswählen


/**
* Own/local headers
*/
#include "SetupWizard.h"

/**
* Qt Headers
*/


/**
* System headers
*/

SetupWizard::SetupWizard(QWidget *parent)
	: QWizard(parent)
{
	setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/icons/NegisWizard.png"));
	setPage(INTRO_PAGE, new IntroPage);
	setPage(XML_DB_PAGE, new XMLDBPage);
	setPage(DB_SETUP_PAGE, new DBSetupPage);
	setPage(XML_SETUP_PAGE, new XMLSetupPage);
	setPage(FINISH_PAGE, new FinishPage);
	setStartId(INTRO_PAGE);
	setWizardStyle(ModernStyle);
	setWindowTitle(tr("NegisSetupWizard"));
	show();
}

SetupWizard::~SetupWizard()
{

}

IntroPage::IntroPage(QWidget *parent)
	: QWizardPage(parent)
{
	cout << "Ctor intropage" << endl;
	setTitle(tr("IntroPageTitle"));
	m_explainLabel = new QLabel(tr("IntroPageExplainLabel"), this);
	m_explainLabel->setWordWrap(true);
}

XMLDBPage::XMLDBPage(QWidget *parent)
: QWizardPage(parent)
{
	cout << "Ctor XMLDBPage" << endl;
	setTitle(tr("XMLDBPageTitle"));
	m_explainLabel = new QLabel(tr("XMLDBPageExplainLabel"));
	m_explainLabel->setWordWrap(true);
	
	m_dbButton = new QRadioButton(tr("XMLDBPageDBButton"));
	m_xmlButton = new QRadioButton(tr("XMLDBPageXMLButton"));
	
	QVBoxLayout *layout = new QVBoxLayout;
	layout->addWidget(m_explainLabel);
	layout->addWidget(m_dbButton);
	layout->addWidget(m_xmlButton);
	setLayout(layout);
}

int XMLDBPage::nextId() const
{
	if(m_dbButton->isChecked())
		return SetupWizard::DB_SETUP_PAGE;
	else
		return SetupWizard::XML_SETUP_PAGE;
}

DBSetupPage::DBSetupPage(QWidget *parent)
: QWizardPage(parent)
{
	cout << "Ctor DBSetupPage" << endl;
	setTitle(tr("DBSetupPageTitle"));
	m_explainLabel = new QLabel(tr("DBSetupExplainLabel"));
	m_explainLabel->setWordWrap(true);
	
	m_hostLabel = new QLabel(tr("DBHost"));
	m_portLabel = new QLabel(tr("DBPort"));
	m_userLabel = new QLabel(tr("DBUser"));
	m_pwdLabel = new QLabel(tr("DBPassword"));
	
	m_hostField = new QLineEdit;
	m_hostLabel->setBuddy(m_hostField);
	
	m_portField = new QLineEdit;
	m_portLabel->setBuddy(m_portField);
	
	m_userField = new QLineEdit;
	m_userLabel->setBuddy(m_userField);
	
	m_pwdField = new QLineEdit;
	m_pwdField->setEchoMode(QLineEdit::Password);
	m_pwdLabel->setBuddy(m_pwdField);
	
	m_testButton = new QPushButton(tr("TestDBConnection"));
	m_savePwdBox = new QCheckBox(tr("SaveDBPassword"));
	
	connect(m_testButton, SIGNAL(clicked()), this,
			SLOT(testConnection()));
			
	QGridLayout *layout = new QGridLayout;
	layout->addWidget(m_explainLabel, 0, 0, 1, 2);
	layout->addWidget(m_hostLabel, 1, 0);
	layout->addWidget(m_hostField, 1, 1);
	layout->addWidget(m_portLabel, 2, 0);
	layout->addWidget(m_portField, 2, 1);
	layout->addWidget(m_userLabel, 3, 0);
	layout->addWidget(m_userField, 3, 1);
	layout->addWidget(m_pwdLabel, 4, 0);
	layout->addWidget(m_pwdField, 4, 1);
	layout->addWidget(m_testButton, 5, 0);
	layout->addWidget(m_savePwdBox, 5, 1);
	setLayout(layout);
	
	registerField("hostField", m_hostField);
	registerField("userField", m_userField);
	registerField("portField", m_portField);
	registerField("pwdField", m_pwdField);
	registerField("savePwdBox", m_savePwdBox);
}

bool DBSetupPage::testConnection()
{
	if(m_userField->text().length() == 0)
	{
			QMessageBox::critical(this, tr("Error"), tr("NoUsernameProvided"));
			return false;
	}
	if(m_hostField->text().length() == 0)
	{
		QMessageBox::critical(this, tr("Error"), tr("NoHostProvided"));
		return false;
	}
	if(m_pwdField->text().length() == 0)
	{
		QMessageBox::critical(this, tr("Error"), tr("NoPasswordProvided"));
		return false;
	}
	QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
	db.setHostName(m_hostField->text());
	db.setUserName(m_userField->text());
	db.setDatabaseName("negis");
	db.setPassword(m_pwdField->text());
	if(m_portField->text().length()==0)
		db.setPort(m_portField->text().toInt());
	bool ok = db.open();
	if(!ok)
	{
		SQLException sqle(db.lastError());
		emit sqlExceptionOccurred(sqle);
		return ok;
	}
	db.close();
	return ok;
}

bool DBSetupPage::saveConnection()
{
	if(m_userField->text().length() == 0)
	{
		QMessageBox::critical(this, tr("Error"), tr("NoUsernameProvided"));
		return false;
	}
	if(m_hostField->text().length() == 0)
	{
		QMessageBox::critical(this, tr("Error"), tr("NoHostProvided"));
		return false;
	}
	if(m_pwdField->text().length() == 0)
	{
		QMessageBox::critical(this, tr("Error"), tr("NoPasswordProvided"));
		return false;
	}
	
	
	return true;
}

XMLSetupPage::XMLSetupPage(QWidget *parent)
: QWizardPage(parent)
{
	cout << "Ctor XMLSetupPage" << endl;
	m_explainLabel = new QLabel(tr("ExplanationXMLSetupPage"));
	m_workspaceLabel = new QLabel(tr("Workspace"));
	m_workspaceField = new QLineEdit;
	m_browseButton = new QPushButton(tr("BrowseDir"));
	connect(m_browseButton, SIGNAL(clicked()), this,
			SLOT(browseWorkspaceDir()));
			
	QGridLayout *layout = new QGridLayout;
	layout->addWidget(m_explainLabel, 0, 0, 1, 2);
	layout->addWidget(m_workspaceLabel, 1, 0);
	layout->addWidget(m_workspaceField, 1, 1);
	layout->addWidget(m_browseButton, 1, 2);
	setLayout(layout);
	
	registerField("workspaceField", m_workspaceField);
}

void XMLSetupPage::browseWorkspaceDir()
{
	m_workspaceField->setText(QFileDialog::getExistingDirectory(this, tr("OpenDirectory"),
																QDir::home().path(),
																QFileDialog::ShowDirsOnly
																| QFileDialog::DontResolveSymlinks));
}

FinishPage::FinishPage(QWidget *parent)
: QWizardPage(parent)
{
	cout << "Ctor FinishPage" << endl;
	m_explainLabel = new QLabel(tr("ExplanationFinishPage"));
	setFinalPage(true);
	
	//connect(wizard()->button(QWizard::FinishButton), SIGNAL(clicked()), this,
	//		SLOT(finishWizard()));
}

bool FinishPage::finishWizard()
{
	if(this->wizard()->hasVisitedPage(SetupWizard::DB_SETUP_PAGE))
	{
		QString host = wizard()->field("hostField").toString();
		QString user = wizard()->field("userField").toString();
		QString port = wizard()->field("portField").toString();
		QString pwd="";
		if(wizard()->field("savePwdBox").toBool())
			pwd = wizard()->field("pwdField").toString();
		
		QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, "$HOME/.negis");
		QSettings settings;
		settings.beginGroup("database");
		settings.setValue("host", host);
		settings.setValue("user", user);
		if(pwd.length() > 0)
			settings.setValue("password", pwd);
		if(port.length()!=0)
			settings.setValue("port", port);
		settings.endGroup();
	}
	
	return true;
}

Und hier wird er aufgerufen:

Code: Alles auswählen

if(!QFile::exists("$HOME/.negis"))
	{
		cout << "Before SetupWizard" << endl;
		SetupWizard wiz;
		wiz.show();
		cout << "After SetupWizard" << endl;
	}
	cout << "Dudldu" << endl;
Es erscheint zwar Before SetupWizard, After SetupWizard und Dudldu aber der Wizard selber erscheint nicht. Ach ja in der entsprechenden Header-Datei habe ich nextId() für alle Seiten des Wizards implementiert.

Schon mal vielen Dank!
jd
Beiträge: 130
Registriert: 22. Januar 2008 17:55

Beitrag von jd »

Hallo, in deinem ersten Konstruktor rufst du show(); auf. Warum? Du startest den Wizard doch deiner main-Funktion.

Ich weiß nicht ob das der Fehler ist, aber ich würde das mal Debuggen auf old-school art, kommentiere alles aus, außer die WizardPages. Dann kannst du schonmal sehen ob dein Hirachie passt. Alternativ: http://doc.trolltech.com/4.4/dialogs-classwizard.html

so long
jd
PeterLustig
Beiträge: 386
Registriert: 21. November 2007 20:07

Beitrag von PeterLustig »

Benutz exec, nicht show. Das blockiert den Code mit einer eigenen Schleife bis der Wizard fertig ist. Ansonsten wird mit deinem Code der Wizard auf dem Stack erstellt, angezeigt, er geht sofort aus dem Scope raus und der Wizard wird zerstört.
abenstex
Beiträge: 30
Registriert: 12. September 2006 16:33

Beitrag von abenstex »

Ich habe mich zwar an das Beispiel der Trolle gehalten inkl. show() in der main.cpp, aber das exec hats gebracht. Klingt komisch ist aber so...:-)
PeterLustig
Beiträge: 386
Registriert: 21. November 2007 20:07

Beitrag von PeterLustig »

Klingt nicht komisch, klingt genau nach dem was ich gesagt habe. Oo
Objekt wird erstellt, Objekt wird angezeigt, Code läuft weiter, Objekt ist aus dem Scope, Anzeige wird beendet, Objekt wird gelöscht. Das alles innerhalb einer Sekunde. Exec blockiert mit einer eigenen Ereignisschleife.

Code: Alles auswählen

{
  int a; // a wird auf dem Stack erstellt
  // ...
  if (a == 9)
  {
    int b; // b wird auf dem Stack erstellt
  }
  // b existiert hier nicht mehr
  // a existiert aber noch
}
// a existiert hier nicht mehr
jd
Beiträge: 130
Registriert: 22. Januar 2008 17:55

Beitrag von jd »

Dazu mal eine kleine Gegenfrage wann benutzt man show(); und wann exec();

Ich habe exec() bis jetzt immer dann benutze, wenn ich abfragen will, wann das Widget geschlossen wurde, oder ein accept(); ausgelöst wurde.
PeterLustig
Beiträge: 386
Registriert: 21. November 2007 20:07

Beitrag von PeterLustig »

Exec benutzt man, wenn das Aufrufen des Widgets die Ereignisschleife der Applikation blockieren soll.
Show benutzt man, wenn die Ereignisschleife des Widgets sich in die Ereignisschleife der Applikation einklinken soll, sodass nichts blockiert wird.

Bei show muss man eben beachten, dass das Objekt nicht gelöscht wird (wenn es z. B. aus dem Scope geht). Also erstellt man das Objekt dann eher auf dem Heap.
abenstex
Beiträge: 30
Registriert: 12. September 2006 16:33

Beitrag von abenstex »

So, noch ein kleines Problem mit dem Wizard. Und zwar wollte ich in meiner FinishPage den FinishButton mit einem SLOT verbinden aber jedesmal wenn ich versuche über

Code: Alles auswählen

QAbstractButton * QWizard::button ( WizardButton which ) const
auf einen Button zuzugreifen stürzt das Program ab. Das passiert auch bei allen anderen Methoden in QWizard, die auf einen Button zugreifen und mit allen Buttons...kann mir das einer erklären und sagen was ich da falsch mache? Falls es irgendwie hilft ich benutze Qt 4.3.4 auf Mac OS X 10.5.2...
jd
Beiträge: 130
Registriert: 22. Januar 2008 17:55

Beitrag von jd »

Hi, versuch es mal mit

Code: Alles auswählen

QWizard::FinishButton
abenstex
Beiträge: 30
Registriert: 12. September 2006 16:33

Beitrag von abenstex »

Ja hab ich ja. Habe alle Buttons aus der enum durchprobiert aber ohne Erfolg.
jd
Beiträge: 130
Registriert: 22. Januar 2008 17:55

Beitrag von jd »

Dann erstelle mal eine Instanz von deinem Wizard mit new.

Code: Alles auswählen

SetupWizard *wiz = new SetupWizard;
wiz->exec();
 
PeterLustig
Beiträge: 386
Registriert: 21. November 2007 20:07

Beitrag von PeterLustig »

Wie verbindest du den Button denn?
abenstex
Beiträge: 30
Registriert: 12. September 2006 16:33

Beitrag von abenstex »

Habs mittlerweile gelöst. Das Problem war, dass ich den Button im ctor verbinden wollte, den ctor aber in setPage in QWizard aufgerufen habe und zu dem Zeitpunkt wizard() anscheinend 0 zurückgibt.
Antworten