Why my data can not transfer between forms with SIGNAl/SLOT? - c++

I have main window and 1 dialog in Qt(in Linux OS).I want to send some thing from main window to my dialogs. When the user press menu button, then my button clicked emit a signals. this is my code in main.cpp:
MainWindow w;
MyDialog m;
//------------------------------
//this connection send key button press mood from MainWindow
QObject::connect(&w,SIGNAL(pressMood(QString)),
&m,SLOT(getPressMood(QString)));
w.show();
and this is my mainwindos.h:
signals:
void pressMood(QString mood) ;
mainwindow.cpp:
void MainWindow::on_btnMenu_clicked()
{
if(database->checkEmpty())
{
menu mn;/*=new menu();*/
mn.showFullScreen();
}
else
{
MyDialog *d=new MyDialog(this);
d->show();
d->raise();
d->activateWindow();
emit pressMood("menu");
if(d->Accepted>0)
{
if(loginResult)
{
menu *mn=new menu();
mn->showFullScreen();
}
}
else
QMessageBox::warning(this, tr("Login failed"), "Sorry.Your authenticate is not valid.", QMessageBox::Ok);
}
}
//--------------------------------------------
void MainWindow::on_btnPassword_clicked()
{
//emit sendID2(result);
CardDialog *d=new CardDialog(this);
emit pressMood("pass");
d->show();
d->raise();
if(d->Accepted<=0)
QMessageBox::warning(this, tr("Login failed"), "Sorry.Your authenticate is not valid.", QMessageBox::Ok);
}
I do not use dialog.exec() because I do not need to show modal.
MyDialog.h:
public slots:
void getPressMood(QString mood);
and MyDialog.cpp:
//=================================================
void MyDialog::getPressMood(QString mood)
{
mood=mood;
//ui->lblMood->setText(mood);;
//ui->lblMood->hide();
}
void MyDialog::on_buttonBox_accepted()
{
//QString mood=ui->lblMood->text();
bool st=database->checkPassword(ui->txtID->text(),ui->txtPass->text(),"3");
int id=(ui->txtID->text()).toInt();
//this user is valid to go to menu page
//s/he is admin
if((st)&&
mood=="menu" &&
database->checkAdmin(id))
{
.......
}
when I trace my code line by line. the emit signal is works , it sends the string data to my slot in another form and also the getpressedmood() slot is also worked. But the global var mood become NULL when the dialog show, also I decide to save data in label. In trace mood I see the string is send but when the dialog shows the label becomes to default value.
I can not find the mistake. Could you help me?

It solved.
my mistake is connect the signal and slot in main.cpp. The answer is :
MyDialog *d=new MyDialog(this);
//should connect here not in main.cpp
QObject::connect(this,SIGNAL(pressMood(QString)),
d,SLOT(getPressMood(QString)));
emit pressMood("menu");
d->show();
d->raise();
d->activateWindow();

Related

QMessageBox result as a buttonrole

I wanna get result of QMessagebox as a buttonrole. but result always 16384 or 65536
I dont wantto use standartresults, want to use only buttonrole kind of buttons. what am I doing wrong here ?
(Im very newbie in QT)
void MainWindow::on_pushButton_clicked()
{
QMessageBox msgBox;
QPushButton *a=msgBox.addButton("OK",QMessageBox::ActionRole);
QPushButton *b=msgBox.addButton("CANCEL",QMessageBox::RejectRole);
int result=msgBox.question(this,"Hola","My 1st Msg");
//result always return 16384 or 65536(integer) PROBLEM HERE
if(result==QMessageBox::RejectRole)
this->setWindowTitle("rejected");
else
this->setWindowTitle("accepted");
}
The question method is static. It doesn't use the message box you have above. The first 3 lines of your method essentially don't do anything.
Here's what your method really does:
void MainWindow::on_pushButton_clicked()
{
int result = QMessageBox::question(this,"Hola","My 1st Msg");
[...]
}
Alas, the QMessageBox has a long-standing bug: it ignores (!) the custom button roles when it comes to acceptance or rejection of the dialog. While the role is passed to the underlying QDialogButtonBox, it is not interpreted correctly when the button is clicked.
Although you can get the role back using QMessageBox::buttonRole, the QMessageBoxPrivate::_q_buttonClicked invokes QDialog::done with the index of the button.
Thus, the first button you add will cause the dialog to be rejected, the second one will cause it to be accepted, and further buttons will cause neither. The acceptance/rejection ignores the role completely and is only based on the index of the button, due to the order it was added in.
Thus you should not use the rejected/accepted signals, unless the first two buttons map directly to these roles in this order, and should use the buttonClicked signal and obtain the role of the button directly:
void MainWindow::on_pushButton_clicked()
{
auto box = new QMessageBox{this};
box->setAttribute(Qt::WA_DeleteOnClose);
box->addButton("OK", QMessageBox::ActionRole);
box->addButton("CANCEL", QMessageBox::RejectRole);
box->setIcon(QMessageBox::Question);
box->setWindowTitle("Hola");
box->setText("My 1st message.");
box->show();
connect(box, &QMessageBox::buttonClicked, [=](QAbstractButton *button){
switch (box->buttonRole(button)) {
case QMessageBox::AcceptRole: return setWindowTitle("accept-role");
case QMessageBox::ActionRole: return setWindowTitle("action-role");
case QMessageBox::RejectRole: return setWindowTitle("reject-role");
}
});
}
Alas, there's another problem: the dialog will be also rejected by closing it via the platform's window manager (the close button on the dialog's title bar). So you need to be able to use the rejected signal, but not when it's in error. It's best to factor this functionality out to a MessageBoxAdapter class that will only emit correct accepted and rejected signals:
// https://github.com/KubaO/stackoverflown/tree/master/questions/messagebox-roles-40753898
#include <QtWidgets>
class MessageBoxAdapter : public QObject {
Q_OBJECT
public:
MessageBoxAdapter(QObject *parent = nullptr) : QObject(parent) {
watch(parent);
}
void watch(QObject *obj) {
auto box = qobject_cast<QMessageBox*>(obj);
if (!box) return;
connect(box, &QMessageBox::rejected, [=]{
if (!box->clickedButton()) emit rejected();
});
connect(box, &QMessageBox::buttonClicked, [=](QAbstractButton *button){
auto role = box->buttonRole(button);
if (role == QMessageBox::AcceptRole) emit accepted();
else if (role == QMessageBox::RejectRole) emit rejected();
emit roleClicked(role);
});
}
Q_SIGNAL void accepted();
Q_SIGNAL void rejected();
Q_SIGNAL void roleClicked(QMessageBox::ButtonRole role);
};
And some user interface to try it out:
struct Ui : public QWidget {
QVBoxLayout layout{this};
QTextBrowser browser;
QPushButton button{"Open"};
MessageBoxAdapter adapter{this};
public:
Ui() {
layout.addWidget(&browser);
layout.addWidget(&button);
connect(&button, &QPushButton::clicked, this, &Ui::onClicked);
connect(&adapter, &MessageBoxAdapter::accepted, [=]{ browser.append("accepted"); });
connect(&adapter, &MessageBoxAdapter::rejected, [=]{ browser.append("rejected"); });
connect(&adapter, &MessageBoxAdapter::roleClicked, [=](QMessageBox::ButtonRole role){
browser.append(QStringLiteral("clicked role=%1").arg(role));
});
}
void onClicked() {
auto box = new QMessageBox{this};
adapter.watch(box);
box->setAttribute(Qt::WA_DeleteOnClose);
box->addButton("OK", QMessageBox::AcceptRole);
box->addButton("ACTION", QMessageBox::ActionRole);
box->addButton("CANCEL", QMessageBox::RejectRole);
box->setIcon(QMessageBox::Question);
box->setWindowTitle("Hola");
box->setText("My 1st message.");
box->show();
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
Ui ui;
ui.show();
return app.exec();
}
#include "main.moc"

Qt Dialog X Button Override Reject Not Working As Expected

I have been trying to hide a stand alone dialog application when the user hits the typical close button (The one with the X in the corner usually next to the minimize button) I cam across this post:
Qt: How do I handle the event of the user pressing the 'X' (close) button?
which I thought would have my solution, but I get strange behavior when I implement it.
void MyDialog::reject()
{
this->hide()
}
When I hit the X Button the whole application closes (the process disappears) which is not what I want. Since my gui spawns with a command line, I setup a test system where I can tell my dialog to hide via a text command where I call the same 'this->hide()' instruction, and everything works fine. The dialog hides and then shows back up when I tell it to show.
Any ideas why the reject method is closing my app completely even when I don't explicitly tell it to?
Override the virtual function "virtual void closeEvent(QCloseEvent * e)" in your dialog class. The code comment will explain in detail.
Dialog::Dialog(QWidget *parent) :QDialog(parent), ui(new Ui::Dialog){
ui->setupUi(this);
}
Dialog::~Dialog(){
delete ui;
}
//SLOT
void Dialog::fnShow(){
//Show the dialog
this->show();
}
void Dialog::closeEvent(QCloseEvent *e){
QMessageBox::StandardButton resBtn = QMessageBox::question( this, "APP_NAME",
tr("Are you sure?\n"),
QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
if (resBtn != QMessageBox::Yes){
//Hiding the dialog when the close button clicked
this->hide();
//event ignored
e->ignore();
//Testing. To show the dialog again after 2 seconds
QTimer *qtimer = new QTimer(this);
qtimer->singleShot(2000,this,SLOT(fnShow()));
qtimer->deleteLater();
}
//below code is for understanding
//as by default it is e->accept();
else{
//close forever
e->accept();
}
}

Program crashes on close Event in Qt

I was trying to set the close event to my code but when I set this code my program crashes.
mainwindow.cpp
void MainWindow::closeEvent(QCloseEvent *event)
{
event->ignore();
if (QMessageBox::Yes == QMessageBox::question(this, "Close Confirmation?",
"Are you sure you want to exit?",
QMessageBox::Yes|QMessageBox::No))
{
if(QMessageBox::Yes)
{
if(aboutDialog)
{
aboutDialog->close();
event->accept();
}
event->accept();
}
}
}
void MainWindow::showAboutDialog()
{
aboutDialog = new QDialog;
Ui::About aboutUi;
aboutUi.setupUi(aboutDialog);
connect(aboutUi.Close, SIGNAL(pressed()), aboutDialog, SLOT(close()));
aboutDialog->show();
}
mainwindow.h
private:
QDialog *aboutDialog;
I am confused why this happens. Help me out to solve this!
Don't ignore the event if you're planning to close, try this:
void MainWindow::closeEvent(QCloseEvent *event)
{
if (QMessageBox::Yes != QMessageBox::question(this, "Close Confirmation?",
"Are you sure you want to exit?", QMessageBox::Yes | QMessageBox::No))
{
event->ignore();
}
}
And when creating the aboutDialog-box, you should pass the mainWindow as parent as Nejat's comment suggests: aboutDialog = new QDialog(mainWindow);. This will make sure that the aboutDialog will get closed if the main window closes.

Qt Whenever pressed enter in QTextEdit

Whenever I pressed enter in my QTextEdit it'll perform a click on my login button. Somehow this causes a crash of my QtCreator. How can I change what'll happen If I press enter in my QTextEdit?
You need to subclass QTextEdit and catch the event you're interested in by overriding the appropriate method:
class MyTextEdit : public QTextEdit
{
Q_OBJECT
public:
void MyTextEdit::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Return)
{
login(); // or rather emit submitted() or something along this way
}
else
{
QTextEdit::keyPressEvent(event);
}
}
};
Alternatively, you can install an event filter on the text edit.

Qt Browser stack when dropping link to QMainWindow

I have simple drag and drop functions implemented in QmainWindow the reference taken from here and here
all i want to do is to accept valid url and open QDialog when the url dropped .
but when the url drooped and the QDialog poped up the browser is stocked in the background until i close the QDialog . this is wrong the browser should be free all the time.
here is my code :
void MainWindow::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("text/html"))
{
event->acceptProposedAction();
}
else
{
event->ignore();
}
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
// accept just text/uri-list mime format
if (event->mimeData()->hasFormat("text/html"))
{
event->acceptProposedAction();
}
else
{
event->ignore();
}
}
void MainWindow::dragLeaveEvent(QDragLeaveEvent *event)
{
event->accept();
}
void MainWindow::dropEvent(QDropEvent *event)
{
QList<QUrl> urlList;
QString fName;
QStringList pathList;
QFileInfo info;
QString suffix;
if (event->mimeData()->hasFormat("text/html"))
{
urlList = event->mimeData()->urls(); // returns list of QUrls
// if just text was dropped, urlList is empty (size == 0)
if ( urlList.size() > 0) // if at least one QUrl is present in list
{
QString url = urlList.at(0).toString();
event->acceptProposedAction();
openDialog(url); // THIS IS THE FUNCTION THAT I OPEN THE QDIALOG window
}
}
//event->acceptProposedAction();
}
void MainWindow::openDialog(QString& slink)
{
QHash<QString,QVariant> DataMap;
QString link = slink;
DataMap.insert("m_webpage",link);
PublishToDialog* pPublishToDialog = new PublishToDialog(this);
pPublishToDialog->Init(DataMap);
if(pPublishToDialog->exec() != QDialog::Accepted)
{
}
}
when i remove the call to the QDialog , so every thing is working fine .
and the browser doesn't stuck. i even tryed as suggested using signal/slot put again
when i start the QDialog when drop invoked the browser stucked!
What exactly is PublishToDialog? I would assume that it is a custom dialog implementation of yours that inherits QDialog. And given this line:
pPublishToDialog->exec() != QDialog::Accepted
This opens the dialog as a modal dialog. A modal dialog is blocking and will block the execution of the current thread until some action is performed on the dialog. Instead of using a modal dialog, you should use a non-modal dialog. Since I am still not sure if PublishToDialog inherits QDialog or what else, I am just going to assume it is. Here is what you could do:
PublishToDialog* pPublishToDialog = new PublishToDialog(this);
// Make it a non-modal dialog
pPublishDialog->setModal(false);
// Connect it to a slot to handle whenever the user performs some action on it
QObject::connect(pPublishDialog, SIGNAL(finished()), this, SLOT(handleDialogAction());
pPublishDialog.show();
You will have to implement handleDialogAction in your code. At the same time, you may want to make pPublishDialog a class-member as you will need it to access QDialog::reuslt in handleDialogAction.