Qt5 | Function w/ Slot Not Working - qt

I've made an app with two forms.
When I press the save button in the second form, it updates the DB Record, and returns back to the first form. I've connected the two forms via Signal-Slot with this code:
DruckerData.h
signals:
void btnSavePressed(QString printerName);
DruckerData.cpp
UiMainWindow frmMain;
connect(this,SIGNAL(btnSavePressed(QString)),&frmMain,SLOT(refreshSaved( QString )));
emit btnSavePressed(ui->ledit_druckerName->text());
this->hide();
UiMainWindow.h
public slots:
void refreshSaved(QString printerName);
UiMainWindow.cpp
void UiMainWindow::refreshSaved(QString printerName){
qDebug()<<"Updated: "<<printerName;
show_list(); //<<<<<<<<<<<<<<<<<<<<<< this function
}
show_list
void UiMainWindow::show_list (){
QList<DB_Printers_lvs> list;
DB_Printers_lvsTransporter t("LVS");
QString wc;
this->setCursor(Qt::WaitCursor);
wc = QString("where 1=1 order by nam_printer");
if (!t.load_dbPrinters_lvs_wc(&list,wc))
{
log()<< "get printers failed"<< wc << t.getLastError();
this->setCursor(Qt::ArrowCursor);
return;
}
ui.treeWidget->clear();
foreach (DB_Printers_lvs db, list)
{
QTreeWidgetItem *item = new QTreeWidgetItem(0);
printer_to_qtreewidgetitem(item, db);
ui.treeWidget->insertTopLevelItem(ui.treeWidget->topLevelItemCount(), item);
}
ui.treeWidget->header()->resizeSections(QHeaderView::ResizeToContents);
ui.bow_search->apply();
this->setCursor(Qt::ArrowCursor);
}
When I press the button on the second form and the first form shows I see debug writing Updated with printer name but the problem is how can I call or start this funktion show_list()?
Thanks for help.

The problem that you create second instance of UiMainWindow here:
UiMainWindow frmMain;
Then you connect signal with this second instance, call it's slots, but you don't even show this second instance of MainForm. Instead of this, you should connect signal and slot inside the UiMainWindow just after you create DruckerData form. Unfortunatly there is no this code at your question so i can't show exactly place. This should be something like this:
//Inside UiMainWindow
DruckerData *data = new DruckerData(this);
connect(data, SIGNAL(btnSavePressed(QString)),this,SLOT(refreshSaved( QString )));
data->show();

Related

How to link signal and slot when i change the font in the dialog

This is how i am currently choosing the font in my application.
void FontChange()
{
QString filePath = QFileDialog::getOpenFileName(NULL, tr("Open File"),
QStandardPaths::standardLocations(QStandardPaths::FontsLocation)[0],
tr("Fonts (*.ttf);;Everything (*.*)"), nullptr,
QFileDialog::DontUseNativeDialog);
if (filePath.isEmpty())
return;
QlineEditSetFont->setText(filePath);
stdstrLocation = filePath.toStdString();
this->isChanged = true; // this executes the function
}
I want to execute a function whenever i change my selection in the Dialog , currently i have to choose a font and than click on open to execute the function
////////////////////////////////////////////////////////////////////////////
Now i am using a non modal way but how can i determine if cancel has been pressed.
Further Edit
QFileDialog* dialog = new QFileDialog();
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setNameFilter("TTF (*.ttf)");
dialog->setOption(QFileDialog::DontUseNativeDialog);
dialog->setDirectory("C:\\Windows\\Fonts");
QObject::connect(dialog, &QFileDialog::currentChanged, [=](const QString &path) {
qDebug() << path; stdstrLocation = path.toStdString(); this->isChanged = true;
QStringList fileNames = dialog->selectedFiles();
qDebug() << "Selected FIles" << fileNames.size();
});
dialog->show();
You can't use the static convenience method but need to create the QFileDialog instance manually:
auto dialog = new QFileDialog(someParent);
dialog->setWindowTitle(tr("Open File"));
dialog->setDirectory(QStandardPaths::standardLocations(QStandardPaths::FontsLocation)[0]);
dialog->setNameFilter(tr("Fonts (*.ttf);;Everything (*.*)"));
// more setup...
connect(dialog, &QFileDialog::filesSelected, this, [this](const QStringList &selected) {
// handle selection change here
});
if (dialog->exec() == QDialog::Accepted) { // alternatively use open() to avoid blocking exec()
// do something with dialog->selectedFiles()...
}
delete dialog;
Actually, those are two different questions. The one from the title has been already answered. The answer to the second one, namely How can i determine if cancel has been pressed, lies in the documentation of QFileDialog::getOpenFileName itself:
If the user presses Cancel, it returns a null string.
With this in mind, you can do something like:
void FontChange()
{
QString filePath = QFileDialog::getOpenFileName(NULL, tr("Open File"),
QStandardPaths::standardLocations(QStandardPaths::FontsLocation)[0],
tr("Fonts (*.ttf);;Everything (*.*)"), nullptr,
QFileDialog::DontUseNativeDialog);
if (filePath.isNull()) {
// user pressed Cancel
} else if (filePath.isEmpty()) {
return;
} else {
QlineEditSetFont->setText(filePath);
stdstrLocation = filePath.toStdString();
this->isChanged = true; // this executes the function
}
}
You can of course rewrite the if part to be more suitable to your app's logic.
As a side note, QString::isEmpty also implies that it is NULL.

Qt -how to get variable value from another function in same file

New to Qt. Still learning it. I have clone.ui, clone.h and clone.cpp. clone ui has 2 buttons.
Browse button-> to Selection a destination path
Add button -> Clone(copy) a file
Clone.h
QString destination_path;
QFileDialog *fdialog;
Clone.cpp has
QFileInfo finfo; // Declare outside function to increase scope
QString destination_name;
void Clone:: on_pushButton__Browse_clicked()
{
/*get the destination path in QString using QFileDialog
Got destination_path */
QString destinatino_path = QFileDialog::getExistingDirectory(....);
QFile finfo(destination_path);
// QFileDialog finfo(destionation_path)
}`
In the same file Clone.cpp
void Clone:: on_btn_Add_clicked()
{
// how to get the same destination_path value here...
//using QFile or some other way?
}
I struck here, Am i missing anything? Any thoughts/suggestion highly useful.
You've create a class (Clone) which has a data member QString destination_path.
Since it is a member variable it has class scope (as in you can access the same variable in any Clone:: member function for the same Clone object).
The problem is that you've hidden it by declaring another QString destination_path in Clone::on_pushButton__Browse_clicked().
void Clone::on_pushButton__Browse_clicked()
{
...
// this *hides* the class member with the same name
QString destination_path = QFileDialog::getExistingDirectory(....);
...
}
The solution is to remove QString from the beginning of the line, which means you are now assigning to the class object's data member.
void Clone::on_pushButton__Browse_clicked()
{
...
// now you're assigning to your object's data member
destination_path = QFileDialog::getExistingDirectory(....);
...
}
Later, in Clone::on_btn_Add_clicked() you can access destination_path, and it will have the value assigned to it in Clone::on_pushButton__Browse_clicked

How can I get access to a QMessageBox by QTest

I am creating some automated GUI tests in my application using QTest.
I can access the widgets from my application using the command:
savePushButton = mainWindow->findChild<QPushButton *>("savePushButton");
It is working fine, but now I have to click on the OK button of a QMessageBox.
I created the QMessageBox in my application like this:
if( something_wrong )
{
QMessageBox::warning(new Widget(), "Title", "Something wrong!");
}
How can I have access to this QMessageBox, and its buttons?
I found a solution on the following link: http://www.qtcentre.org/threads/31239-Testing-modal-dialogs-with-QTestLib .
It uses the command QApplication::topLevelWidgets(); to get a widget list. Then it searches for the message box widget and simulates a key enter (QTest::keyClick(mb, Qt::Key_Enter);) which closes the message box.
Example:
void MyTest::testDialog()
{
QTimer::singleShot(500, this, SLOT(timeOut()));
QVERIFY(functionThatProducesMessageBox());
}
void MyTest::timeOut()
{
QWidgetList allToplevelWidgets = QApplication::topLevelWidgets();
foreach (QWidget *w, allToplevelWidgets) {
if (w->inherits("QMessageBox")) {
QMessageBox *mb = qobject_cast<QMessageBox *>(w);
QTest::keyClick(mb, Qt::Key_Enter);
}
}
}
The header file must contain the Q_OBJECT macro to use the signals and slots mechanism.
Example:
class MyClass: public QWidget
{
Q_OBJECT
public:
...
It worked well for me since the UI (thread) is blocked when the message box appears.
Note: remember to rebuild the project when you add the Q_OBJECT macro.
It often helps to look to Qt's auto tests:
void ExecCloseHelper::timerEvent(QTimerEvent *te)
{
if (te->timerId() != m_timerId)
return;
QWidget *modalWidget = QApplication::activeModalWidget();
if (!m_testCandidate && modalWidget)
m_testCandidate = modalWidget;
if (m_testCandidate && m_testCandidate == modalWidget) {
if (m_key == CloseWindow) {
m_testCandidate->close();
} else {
QKeyEvent *ke = new QKeyEvent(QEvent::KeyPress, m_key, Qt::NoModifier);
QCoreApplication::postEvent(m_testCandidate, ke);
}
m_testCandidate = Q_NULLPTR;
killTimer(m_timerId);
m_timerId = m_key = 0;
}
}
Judging from that code, you can get the message box via QApplication::activeModalWidget(). Testing native (I'm assuming they're native) widgets is difficult, which is likely why they chose to send key events, as you don't need to know e.g. the location of the buttons for those, as you would with a mouse click.

How to draw dash instead of null in QSpinBox?

I need to draw dash instead of null in QSpinBox. Also I need to make dash key pressing equalling null key pressing.
How can I do this?
You can use setSpecialValueText();
QSpinBox spinBox;
spinBox->setSpecialValueText(tr("-"));
You can then check if the special value is selected by connecting valueChanged(QString) function. Note that this is different from valueChanged(int) You can then check the value of the passed string in a slot, and if it is equal to special text, you can do something.
main()
{
connect(spinBox, SIGNAL(valueChanged(QString)), this, SLOT(doSomething(QString)));
}
void doSomething(QString valueStr)
{
if(valueStr == spinBox->specialValueText())
// Do something
else
//Convert valueStr to int and do other stuff
}
Or you could do something like this:
main()
{
connect(spinBox, SIGNAL(valueChanged()), this, SLOT(doSomething()));
}
void doSomething()
{
if(spinBox->value() == 0)
// Do something with dash
else
//Do something with the value
}
For your other question, you need to create a keyPressEvent and check if pressed key is dash or not. If it's dash you can call another function to do something. Edit: BTW, the index of specialValueText() is 0.
Edit: Or you can create a QShortcut in your main function.
new QShortcut(QKeySequence(Qt::Key_Minus), this, SLOT(doSomething()));
Edit continued: doSomething() is a slot function. Put, for example void doSomething(); in the private slots: section of your header file. And in the cpp file define a function similar to this:
void MainWindow::doSomething()
{
ui->spinBox->setValue(0);
//This is the slot called when you press dash.
}
Edit still continued:
You need to declare a protected: function in the header like this:
virtual void keyPressEvent(QKeyEvent *event);
Then you need to define this function in your cpp file. Like this:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Minus)
ui->spinBox->setValue(0);
}
You don't have to connect any signals or slots for this function. It's an event.
That means when dash is pressed ui->spinBox->setValue(0);
Because of that, you need to create a spinBox with a range starting from 0.
spinBox->setRange(0, 100);
That means,
if(spinBox->value() == 0)
//Then specialValueText is selected.

Can't update view in StackedWidget

I am using stackedwidget and for some reason i cannot be able to update a view.I used this to get to my first view
(manage_employee_data).
connect(ui.actionManage_Employees_Data, SIGNAL(triggered()), this, SLOT(manage_employee_data()));
Here is the code i am using to update the view.
void employed::manage_employee_data()
{
tablesModel = new QSqlTableModel(ui.empds_tableview);
tablesModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
tablesModel->setTable("employee_datastores");
ui.empds_tableview->setModel(tablesModel);
ui.empds_tableview->setColumnHidden(tablesModel->fieldIndex("id"), true);
ui.empds_tableview->setColumnHidden(tablesModel->fieldIndex("employee_datastore_description"), true);
ui.empds_tableview->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui.empds_tableview->setSelectionMode(QAbstractItemView::SingleSelection);
ui.empds_tableview->setSortingEnabled(true);
ui.empds_tableview->setSelectionBehavior(QAbstractItemView::SelectRows);
ui.empds_tableview->horizontalHeader()->setStretchLastSection(true);
tablesModel->select();
//Localized Header Captions
tablesModel->setHeaderData(1, Qt::Horizontal, tr("Employee DataStore Name"));
connect(ui.empds_tableview->selectionModel(),
SIGNAL(currentRowChanged(const QModelIndex&,
const QModelIndex&)),
this, SLOT(updateView()));
ui.stackedWidget->setCurrentWidget(ui.page_10);
}
void employed::updateView()
{
QMessageBox msgBox;
msgBox.setText("Manage Employee Data Sent Me.");
msgBox.exec();
}
I just added ui.stackedWidget->setCurrentWidget(ui.page_10); to my update function.
void employed::updateView()
{
QMessageBox msgBox;
msgBox.setText("Manage Employee Data Sent Me.");
msgBox.exec();
ui.stackedWidget->setCurrentWidget(ui.page_10);
}

Resources