Seite 1 von 1

Probleme mit QWizard

Verfasst: 7. Juni 2008 09:24
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!

Verfasst: 7. Juni 2008 11:53
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

Verfasst: 7. Juni 2008 12:07
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.

Verfasst: 7. Juni 2008 12:15
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...:-)

Verfasst: 7. Juni 2008 12:18
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

Verfasst: 7. Juni 2008 12:33
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.

Verfasst: 7. Juni 2008 12:35
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.

Verfasst: 9. Juni 2008 15:08
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...

Verfasst: 9. Juni 2008 15:12
von jd
Hi, versuch es mal mit

Code: Alles auswählen

QWizard::FinishButton

Verfasst: 9. Juni 2008 15:18
von abenstex
Ja hab ich ja. Habe alle Buttons aus der enum durchprobiert aber ohne Erfolg.

Verfasst: 9. Juni 2008 15:23
von jd
Dann erstelle mal eine Instanz von deinem Wizard mit new.

Code: Alles auswählen

SetupWizard *wiz = new SetupWizard;
wiz->exec();
 

Verfasst: 9. Juni 2008 17:00
von PeterLustig
Wie verbindest du den Button denn?

Verfasst: 9. Juni 2008 17:34
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.