I've been trying to learn c++ and qt framework by doing a point of sale software project.my main window has couple of tabs and with in one tab i have a qpushbutton which open a newpurchase dialog which takes input from user to record a new purchase from supplier.this newpurchase dialog has a lineedit which, when recieves product barcode from a barcode reader ,triggers another quanity dialog which, user can use to enter the quantity of the product. but when i click ok on the button box of the quantity dialog instead of closing just the quantity dialog ,it closes the newpurchase dialog as well.i debugged the qt application and it shows that a qpushbutton (which saves and closes the newpurchase dialog)on the newpuchase dialog gets triggered automatically.additionally this behaviour is only spotted when quantity dialog is triggered through the barcode lineedit,i have another lineedit which accepts description of the product and triggers the same quantity dialog ,but clicking ok button when quantity dialog is triggered through description lineedit does not closes the newpurchase dialog or trigger the qpushbutton which saves and closes the newpurchase dialog.im attaching the screen shots of the dialog and code for the dialogs
on mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
newpurchase mypurchase;
connect(&mypurchase,SIGNAL(purchase_added()),this,SLOT(update_view()));
mypurchase.exec();
}
newpurchase dialog
newpurchase.cpp
#include "newpurchase.h"
#include "ui_newpurchase.h"
#include <QtDebug>
#include <qtablewidget.h>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QCompleter>
#include <QObject>
#include <QWidget>
#include <QDate>
newpurchase::newpurchase(QWidget *parent) :
QDialog(parent),
ui(new Ui::newpurchase)
{
ui->setupUi(this);
QSqlQuery qry;
qry.prepare("select description from product");
if(!qry.exec())
{
qDebug() << "error getting description from product";
}
QStringList items;
while(qry.next())
{
items <<qry.value(0).toString();
}
QCompleter *completer =new QCompleter(items,this);
completer->setCaseSensitivity(Qt::CaseInsensitive);
ui->lineEdit_descripion->setCompleter(completer);
connect(completer,static_cast<void (QCompleter::*)(const QString&)>(&QCompleter::activated),
[&](const QString &text)->void
{
newpurchase::clear(text);
});
QSqlQuery supqry;
supqry.prepare("select supplier_name from supplier");
if(!supqry.exec())
{
qDebug() << "error getting suppliername from supplier";
}
QStringList supitems;
while(supqry.next())
{
supitems <<supqry.value(0).toString();
}
QCompleter *supcompleter =new QCompleter(supitems,this);
supcompleter->setCaseSensitivity(Qt::CaseInsensitive);
ui->lineEdit_sup->setCompleter(supcompleter);
}
newpurchase::~newpurchase()
{
delete ui;
}
void newpurchase::on_lineEdit_barcode_returnPressed()
{
if(!ui->lineEdit_sale->text().isEmpty() && !ui->lineEdit_sup->text().isEmpty() && !ui->lineEdit_inv->text().isEmpty())
{
quantity_dialog quandialog;
connect(&quandialog,SIGNAL(purdetails(QString)),this,SLOT(code(QString)));
quandialog.exec();
}
else
{
Errdialog myerror("please provide supplier and invoice" );
myerror.exec();
}
}
void newpurchase::saveDataIntoTable(QString item,double price,int quantity,QString code,QString date)
{
double rupee =price*quantity*1.00;
//qDebug() <<date;
QString mrp= QString::number(rupee,'f',2);
QString qty= QString::number(quantity);
QString prc= QString::number(price);
// QString kod= QString::number(code);
if (!ui->tableWidget)
return;
const int currentRow = ui->tableWidget->rowCount();
ui->tableWidget->setRowCount(currentRow + 1);
ui->tableWidget->setItem(currentRow, 0, new QTableWidgetItem(item));
ui->tableWidget->setItem(currentRow, 1, new QTableWidgetItem(prc));
ui->tableWidget->setItem(currentRow, 2, new QTableWidgetItem(qty));
ui->tableWidget->setItem(currentRow, 3, new QTableWidgetItem(mrp));
ui->tableWidget->setItem(currentRow, 4, new QTableWidgetItem(code));
ui->tableWidget->setItem(currentRow, 5, new QTableWidgetItem(date));
double total=ui->label_3->text().toDouble();
total = total+rupee;
ui->label_3->setText(QString::number(total,'f',2));
}
void newpurchase::clear(QString item)
{
if(!item.isEmpty())
{
if(!ui->lineEdit_des->text().isEmpty() && !ui->lineEdit_sup->text().isEmpty() && !ui->lineEdit_inv->text().isEmpty())
{
quantity_dialog quandialog;
connect(&quandialog,SIGNAL(purdetails(QString)),this,SLOT(descr(QString)));
quandialog.exec();
}
else
{
Errdialog myerror("please provide supplier and invoice" );
myerror.exec();
}
}
}
void newpurchase::descr(QString q)
{
QStringList elements = q.split(':');
QSqlQuery qry;
qry.prepare("select * from product where description='"+ui->lineEdit_des->text()+"'");
if(!qry.exec())
{
qDebug() << "error getting table product";
}
if (qry.next())
{
QString result=qry.value(1).toString();
double cost= elements[1].toDouble();
QString itemco=qry.value(2).toString();
int quan=elements[0].toInt();
QString mfd=elements[2];
saveDataIntoTable(result,cost,quan,itemco,mfd);
ui->lineEdit_des->clear();
}
}
void newpurchase::on_pushButton_clicked()
{
QItemSelectionModel *select =ui->tableWidget->selectionModel();
int row = select->selectedRows().takeFirst().row();
double rupee=ui->tableWidget->item(row,3)->text().toDouble();
ui->tableWidget->removeRow(row);
double total=ui->label_3->text().toDouble();
total = total-rupee;
ui->label_3->setText(QString::number(total,'f',2));
}
void newpurchase::on_lineEdit_des_returnPressed()
{
}
void newpurchase::code(QString q)
{
QStringList elements = q.split(':');
QSqlQuery qry;
qry.prepare("select * from product where code="+ui->lineEdit_sale->text());
if(!qry.exec())
{
qDebug() << "error getting table product";
}
if (qry.next())
{
QString result=qry.value(1).toString();
double cost= elements[2].toDouble();
QString itemco=qry.value(2).toString();
int quan=elements[0].toInt();
QString mfd=elements[1];
saveDataIntoTable(result,cost,quan,itemco,mfd);
}
ui->lineEdit_sale->clear();
}
void newpurchase::on_pushButton_2_clicked()
{
QString datetime= QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
QString supplier=ui->lineEdit_sup->text();
QString invoice=ui->lineEdit_inv->text();
int numrow=ui->tableWidget->rowCount();
// qDebug() << numrow;
for (int i = 0; i < numrow; i++)
{
QSqlQuery query;
query.prepare("SELECT MAX(Id) FROM stock_transaction");
if(!query.exec())
{
qDebug() << "error getting id";
}
int id=0 ;
if (query.next())
{
id=query.value(0).toInt()+1;
}
QString coder=ui->tableWidget->item(i,4)->text();
QString qua=ui->tableWidget->item(i,2)->text();
double rate=ui->tableWidget->item(i,1)->text().toDouble();
QString date= ui->tableWidget->item(i,5)->text();
QString d=QString::number(id);
QString batch=supplier+"_"+invoice+"_"+d;
QSqlQuery querysale;
querysale.prepare("INSERT INTO stock_transaction(id,code,stock,mfd,supplier,invoice,cost,date_time) VALUES(:id,:code,:stock,:mfd,:supplier,:invoice,:cost,:date_time)");
querysale.bindValue(":id", id);
querysale.bindValue(":code",coder);
querysale.bindValue(":stock", qua.toInt());
querysale.bindValue(":mfd",date);
querysale.bindValue(":supplier", supplier);
querysale.bindValue(":invoice", invoice);
querysale.bindValue(":cost", rate*1.00);
querysale.bindValue(":date_time", datetime);
if(!querysale.exec())
{
qDebug() << "error recording sale";
}
}
emit this->purchase_added();
close();
}
quantity dialog
quantity.cpp
#include "quantity_dialog.h"
#include "ui_quantity_dialog.h"
quantity_dialog::quantity_dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::quantity_dialog)
{
ui->setupUi(this);
ui->lineEdit_quan->setFocus();
ui->buttonBox->setEnabled(false);
connect(ui->lineEdit_quan, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
connect(ui->dateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(checkLineEdits()));
connect(ui->lineEdit_3, SIGNAL(textChanged(QString)), this, SLOT(checkLineEdits()));
}
quantity_dialog::~quantity_dialog()
{
delete ui;
}
void quantity_dialog::on_buttonBox_accepted()
{
emit purdetails(ui->lineEdit_quan->text()+":"+ui->dateEdit->text()+":"+ui->lineEdit_3->text());
ui->lineEdit_quan->clear();
}
Please let me know if i can provide any other details
the auto default property of the autoclicking qpushbutton was set.changing this property solved my issue
Related
I'm a beginner at Qt and I'm struggling to populate a QStandardItemModel from an XML file.
I've tried the following and the entire project runs successfully but the QtableView does not display the data.
Here is my main.cpp:
void readXml(const QString& fileName) {
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text)) {
qDebug() << "Cannot read file" << file.errorString();
return;
}
StockItems* stockitems = new StockItems;
XmlStockItemsReader xmlReader(stockitems);
if(!xmlReader.read(&file))
qDebug() << "Parse error in file " << xmlReader.errorString();
else {
stockitems->print();
stockitems->populateStockModel();
}
}
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
StockItems si;
//! Change this to match the path of your project
QString path = "C:\\unisa\\cos3711\\FIConcession";
readXml(path + "\\stockitems.xml");
si.show();
return app.exec();
}
In stockitems.cpp I have the following function:
void StockItems::populateStockModel() {
foreach(Item* item, m_items) {
QList<QStandardItem*> newRow;
QStandardItem *stockID = new QStandardItem(QString("%1").arg(item->stockID()));
QStandardItem *desc = new QStandardItem(QString("%2").arg(item->desc()));
QStandardItem *price = new QStandardItem(QString("%3").arg(item->price()));
newRow.append(stockID);
newRow.append(desc);
newRow.append(price);
stockModel->appendRow(newRow);
}
}
If I do some debugging I can see that the stockID, desc and prices are correctly read, so the problem must lie somewhere with updating the stockModel.
My main StockItems Constructor is as follows:
StockItems::StockItems(QWidget *parent) :
QDialog(parent),
ui(new Ui::StockItems)
{
ui->setupUi(this);
stockModel = new QStandardItemModel(0, 3);
// Set Model Headers
stockModel->setHeaderData(0, Qt::Horizontal, "Stock ID", Qt::DisplayRole);
stockModel->setHeaderData(1, Qt::Horizontal, "Description", Qt::DisplayRole);
stockModel->setHeaderData(2, Qt::Horizontal, "Price", Qt::DisplayRole);
// Link Model to Table View
ui->tvStock->setModel(stockModel);
}
I have an add button which contains the following onclick code which works as expected so I'm just not sure if I'm referencing the stockModel correctly.
QList<QStandardItem*> newRow;
QStandardItem* stockID = new QStandardItem(QString("%1").arg(ui->tbStockId->text()));
QStandardItem* desc = new QStandardItem(QString("%2").arg(ui->tbDesc->text()));
QStandardItem* price = new QStandardItem(QString("%3").arg(ui->sbPrice->text()));
newRow.append(stockID);
newRow.append(desc);
newRow.append(price);
stockModel->appendRow(newRow);
Finally I think this might help, my stockitems.h file:
class StockItems : public QDialog
{
Q_OBJECT
public:
explicit StockItems(QWidget *parent = 0);
~StockItems();
void populateStockModel();
void addItem(Item* item);
void print() const;
private slots:
void on_btnAdd_clicked();
void on_btnDelete_clicked();
private:
Ui::StockItems *ui;
QStandardItemModel *stockModel;
QList<Item*> m_items;
};
This is a lot and please let me know if I should provide anything else but I'm really lost as to how to populate this model correctly.
Thanks for any guidance!
Your readXml function does not populate the StockItems instance that you create in your main function, but a completely new StockItems instance that isn't used anywhere.
For example, instead of
StockItems* stockitems = new StockItems;
in your readXml function, let readXml take another StockItems argument, and use that:
void readXml(const QString& fileName, StockItems *stockItems) {
// do everything here as before, except for the
// StockItems* stockitems = new StockItems;
...
}
int main(int argc, char* argv[]) {
...
readXml(path + "\\stockitems.xml", &si);
si.show();
...
}
I'm trying to create a simple app which allows user to enter a word and the app will output the definition. I have compiled words and definitions by making mysql database file. I thought using MySQL would be a faster way make my app. My database looks like this:
rowed | Column1(word) | Column2(definition)
1 DNA A double-stranded,helical...
The pseudocode for this program definitely should be like this:
if(lineEdit == wordInput)
{
ui->label->setText("Display definition)
}
I just can't figure out how to do it. So far I have tried following code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>
#include <QPalette>
#define Path_to_DB "/Users/makkhay/Desktop/nep_eng-2.sqlite"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Set background picture
QPixmap bkgnd("/Users/makkhay/Desktop/background.jpg");
bkgnd = bkgnd.scaled(this->size(), Qt::IgnoreAspectRatio);
QPalette palette;
palette.setBrush(QPalette::Background, bkgnd);
this->setPalette(palette);
myDB = QSqlDatabase::addDatabase("QSQLITE");
myDB.setDatabaseName(Path_to_DB);
QFileInfo checkFile(Path_to_DB);
if(checkFile.isFile())
{
if(myDB.open())
{
ui->label->setText("The database is connected");
}
}else{
ui->label->setText("No file found!");
}
}
MainWindow::~MainWindow()
{
delete ui;
myDB.close();
}
void MainWindow::on_pushButton_clicked()
{
// QMessageBox::StandardButton reply= QMessageBox::question(this,
// "My Title", " Word not found, quit app?",
// QMessageBox::Yes | QMessageBox::No);
// if(reply == QMessageBox::Yes){
// QApplication::quit();
//}
if(!myDB.isOpen()){
qDebug() << " No connection to db";
return;
}
QString wordInput, definition;
wordInput = ui->lineEdit->text();
QSqlQuery qry;
qry.prepare("SELECT Column1,Column2 FROM Nepali WHERE Column1 = :input");
qry.bindValue(":input",wordInput);
// int fieldNo = query.record().indexof("Column1");
if(qry.exec())
{
ui->debug->setText(" Checking output!"); // output is visible
while (qry.next())
{
ui->output->setText("Checing output!"); // output is not visible
QString inputWord = qry.value(0).toString();
QString wordDefinition = qry.value(1).toString();
ui->output->setText(wordDefinition);
}
}
}
OK, the following code works for me. Try commenting out your existing code and pasting this code in. This code is basically the exact same code you posted, I just commented out some of the code to set the background and removed some excess lines.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>
#include <QPalette>
#include <QSqlQuery>
#include <QFileInfo>
#define Path_to_DB "/Users/makkhay/Desktop/nep_eng-2.sqlite"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Set background picture
//QPixmap bkgnd("/Users/makkhay/Desktop/background.jpg");
//bkgnd = bkgnd.scaled(this->size(), Qt::IgnoreAspectRatio);
//QPalette palette;
//palette.setBrush(QPalette::Background, bkgnd);
//this->setPalette(palette);
myDB = QSqlDatabase::addDatabase("QSQLITE");
myDB.setDatabaseName(Path_to_DB);
QFileInfo checkFile(Path_to_DB);
if(checkFile.isFile())
{
if(myDB.open())
{
ui->label->setText("The database is connected");
}
}else{
ui->label->setText("No file found!");
}
}
MainWindow::~MainWindow()
{
delete ui;
myDB.close();
}
void MainWindow::on_pushButton_clicked()
{
if(!myDB.isOpen()){
qDebug() << " No connection to db";
return;
}
QString wordInput;
wordInput = ui->lineEdit->text();
QSqlQuery qry;
qry.prepare("SELECT Column1,Column2 FROM Nepali WHERE Column1 = :input");
qry.bindValue(":input",wordInput);
if(qry.exec())
{
ui->debug->setText(" Checking output!");
while (qry.next())
{
// Retrieve Values from select statement
QString inputWord = qry.value(0).toString();
QString wordDefinition = qry.value(1).toString();
// Display values
ui->output->setText(wordDefinition);
}
} else {
qDebug() << "query failed to execute";
}
}
After declaring the qry variable the code should look like this:
qry.prepare("SELECT Column1,Column2 FROM tableName WHERE Column1 = :input");
qry.bindValue(":input",wordInput);
if(qry.exec())
{
if (qry.next())
{
// Extract the results from the SELECT statement
QString inputWord = qry.value(0).toString();
QString wordDefinition = qry.value(1).toString();
// Then use the values for whatever you wish.
}
}
You don't need comma before WHERE. Also, I guess that you are comparing Column1 with wordInput, not Column2.
if(qry.exec("SELECT Column1,Column2 FROM some_table WHERE Column1='"+ wordInput+"'"))
Edit: you don't mention a table you are selecting from.
I'm trying to toggle QAction's icon. It depends on context of a specific table. Actually, it's working whenever I start message.cpp, but it wouldn't change when I'm on message.cpp. I expect updateIcon() will change my icon if I click on m_action4, but it doesn't. Could I repaint QAction?
Firstly, I set variable on header:
message.h:
private:
QAction *m_action4;
Here is my code on source:
message.cpp:
QSqlQuery query0;
m_action4 = new QAction(QIcon(":/images/silent1.png"), tr("Mute"), this);
m_muteActive = false;
query0.prepare("SELECT state FROM mute_state WHERE p_id=?");
query0.addBindValue(m_pid);
query0.exec();
if (query0.next() && query0.value(0) == "1" )
{
{
m_muteActive = true;
m_action4->setIcon(QIcon(":/images/speaker.png"));
}
}
m_actionBar->addButton(m_action4);
connect(m_action4, SIGNAL(triggered()), this, SLOT(muteMessages()));
muteMessages()
{
QSqlQuery query;
query.prepare("UPDATE mute_state SET state=? , duration= ? , type=? WHERE p_id=?");
if (m_muteActive)
{
query.addBindValue("0");
query.addBindValue("0");
m_muteActive = false;
}
else
{
query.addBindValue("1");
query.addBindValue("525949");
m_muteActive = true;
}
query.addBindValue("private");
query.addBindValue(m_id);
if (query.exec())
qDebug()<<"query was executed";
}
QTimer::singleShot(100 , this, SLOT(updateIcon()));
}
updateIcon()
{
if (m_muteActive)
m_action4->setIcon(QIcon(":/images/silent1.png"));
else
m_action4->setIcon(QIcon(":/images/speaker.png"));
}
The code you've posted works fine. Here it is, after removing the SQL queries that are not necessary to demonstrate it:
#include <QApplication>
#include <QAction>
#include <QToolBar>
#include <QGridLayout>
#include <QPainter>
class Ui : public QWidget {
QGridLayout m_grid;
QToolBar m_actionBar;
QIcon m_silent, m_speaker;
QAction m_action4;
bool m_muteActive;
QPixmap drawText(const char * text, int size = 64) {
QPixmap pix(size, size);
QPainter p(&pix);
p.setFont(QFont("helvetica", size*0.8));
p.fillRect(pix.rect(), Qt::white);
p.drawText(pix.rect(), QString::fromUtf8(text));
return pix;
}
public:
Ui() :
m_grid(this),
m_silent(drawText("🔇")),
m_speaker(drawText("🔊")),
m_action4(tr("Mute"), this),
m_muteActive(false)
{
m_grid.addWidget(&m_actionBar, 0, 0);
m_actionBar.addAction(&m_action4);
connect(&m_action4, &QAction::triggered, this, &Ui::muteMessages);
updateIcon();
}
Q_SLOT void muteMessages() {
m_muteActive = !m_muteActive;
updateIcon();
}
Q_SLOT void updateIcon() {
m_action4.setIcon(m_muteActive ? m_silent : m_speaker);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Ui ui;
ui.show();
return a.exec();
}
I am new in Qt and I need to do a program who export html page to PDF
So, the main idea is use QWebPage for interpret html and export itself to pdf with QPrinter.
I have two class webview who use QWebPage and Print who use QPrinter.
In main.cpp I have connect LoadFinished to PrintPDF slot:
Print *pdf = new Print(args);
webview *nav = new webview();
nav->setPrinter(pdf->getPrinter());
if(nav->load(args) == false) {
qDebug() << "can't load page";
return 0;
}
//when the page page is ready, we will print it
QObject::connect(nav->getFrame(), SIGNAL(loadFinished(bool)), nav, SLOT(printPDF(bool)));
My webview.cpp class:
#include "webview.h"
webview::webview()
{
page = new QWebPage;
printer = 0;
}
webview::~webview()
{
delete page;
}
bool webview::load(Arguments *args)
{
QRegularExpression url("^(file|http)://");
QRegularExpression fullPath("^/");
QRegularExpressionMatch pathMatch = fullPath.match(args->getSource());
QRegularExpressionMatch urlMatch = url.match(args->getSource());
// see http://qt-project.org/doc/qt-4.8/qwebsettings.html#WebAttribute-enum for more informations
page->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
page->settings()->setAttribute(QWebSettings::AutoLoadImages, true);
page->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
page->settings()->setAttribute(QWebSettings::PrintElementBackgrounds, true);
page->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
if(pathMatch.hasMatch()) {
page->mainFrame()->load(QUrl::fromLocalFile(args->getSource()));
} else {
if (urlMatch.hasMatch()) {
page->mainFrame()->load(QUrl(args->getSource()));
} else {
fprintf(stderr, "%s\n", qPrintable(QApplication::translate("main", "Error: Invalide source file")));
return false;
}
}
return true;
}
void webview::printPDF(bool ok)
{
if(ok == true) {
qDebug() << "okay";
} else
qDebug() << "non okay";
if(printer != 0)
page->mainFrame()->print(printer);
}
This is what my console display:
non okay
QPainter::begin: A paint device can only be painted by one painter at a time.
I have no idea where the error might be due. The whole project is here
The arguments are:
./htmltopdf http://stackoverflow.com destinationFolder
(destinationFolder is not yet implemented, you must directly modify the source code)
You have more than one Painter in your Code. Search for it.
I thing the Problem is in your "Printer Class". With a Local Printer in the printPDF Method it works. Try it:
void webview::printPDF(bool ok)
{
QPrinter printer(QPrinter::HighResolution);
QString fileName = QFileDialog::getSaveFileName(this, "Export PDF",
QString(), "*.pdf");
printer.setPageSize(QPrinter::A4);
printer.setOrientation(QPrinter::Portrait);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(fileName);
page()->mainFrame()->print(&printer);
}
UPDATE: Here a small working Example:
testview.cpp
#include "testview.h"
#include <QWebFrame>
#include "webview.h"
#include <QWebPage>
#include <QGridLayout>
testview::testview(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QGridLayout* Layout = new QGridLayout(this);
webview* w = new webview(this);
w->setMinimumSize(500, 500);
centralWidget()->setLayout(Layout);
bool a = connect(w->page()->mainFrame(), SIGNAL(loadFinished(bool)), w, SLOT(printPDF(bool)));
w->page()->mainFrame()->load(QUrl("http://stackoverflow.com"));
}
testview::~testview()
{
}
webview.cpp
#include "webview.h"
#include <QPrinter>
#include <QWebFrame>
#include <QFileDialog>
webview::webview(QWidget *parent)
: QWebView(parent)
{
}
webview::~webview()
{
}
void webview::printPDF(bool ok)
{
QPrinter printer(QPrinter::HighResolution);
QString fileName = QFileDialog::getSaveFileName(this, "Export PDF",
QString(), "*.pdf");
printer.setPageSize(QPrinter::A4);
printer.setOrientation(QPrinter::Portrait);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(fileName);
page()->mainFrame()->print(&printer);
}
The problem was elsewhere :
In my main.cpp I had this :
QObject::connect(nav->getFrame(), SIGNAL(loadFinished(bool)), nav, SLOT(printPDF(bool)));
[...]
delete args;
delete pdf;
delete nav;
return app.exec();
app.exec() is a kind of infinit loop who thaht handles Qt events and thus allows the program does not close.
If I proceed to delete before calling this function,then I will have freshly deallocated pointers that will be used
If I Do :
bool result = app.exec();
delete args;
delete pdf;
delete nav;
return result;
It's work fine !
I would like to get a set of four values from four input labels in Qt. I would like to use QInputDialog but it contains only one inputbox as a default one. So, how can I add four labels and four line-edits and get the value from it?
You don't. The documentation is pretty clear:
The QInputDialog class provides a simple convenience dialog to get a
single value from the user.
If you want multiple values, create a QDialog derived class from scratch with 4 input fields.
For example:
QDialog dialog(this);
// Use a layout allowing to have a label next to each field
QFormLayout form(&dialog);
// Add some text above the fields
form.addRow(new QLabel("The question ?"));
// Add the lineEdits with their respective labels
QList<QLineEdit *> fields;
for(int i = 0; i < 4; ++i) {
QLineEdit *lineEdit = new QLineEdit(&dialog);
QString label = QString("Value %1").arg(i + 1);
form.addRow(label, lineEdit);
fields << lineEdit;
}
// Add some standard buttons (Cancel/Ok) at the bottom of the dialog
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, &dialog);
form.addRow(&buttonBox);
QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
// Show the dialog as modal
if (dialog.exec() == QDialog::Accepted) {
// If the user didn't dismiss the dialog, do something with the fields
foreach(QLineEdit * lineEdit, fields) {
qDebug() << lineEdit->text();
}
}
Following alexisdm's answer, here is one way to implement custom QInputDialog.
"inputdialog.h":
#ifndef INPUTDIALOG_H
#define INPUTDIALOG_H
#include <QDialog>
class QLineEdit;
class QLabel;
class InputDialog : public QDialog
{
Q_OBJECT
public:
explicit InputDialog(QWidget *parent = nullptr);
static QStringList getStrings(QWidget *parent, bool *ok = nullptr);
private:
QList<QLineEdit*> fields;
};
#endif // INPUTDIALOG_H
"inputdialog.cpp":
#include "inputdialog.h"
#include <QLabel>
#include <QLineEdit>
#include <QDialogButtonBox>
#include <QFormLayout>
InputDialog::InputDialog(QWidget *parent) : QDialog(parent)
{
QFormLayout *lytMain = new QFormLayout(this);
for (int i = 0; i < 4; ++i)
{
QLabel *tLabel = new QLabel(QString("Text_%1:").arg(i), this);
QLineEdit *tLine = new QLineEdit(this);
lytMain->addRow(tLabel, tLine);
fields << tLine;
}
QDialogButtonBox *buttonBox = new QDialogButtonBox
( QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this );
lytMain->addWidget(buttonBox);
bool conn = connect(buttonBox, &QDialogButtonBox::accepted,
this, &InputDialog::accept);
Q_ASSERT(conn);
conn = connect(buttonBox, &QDialogButtonBox::rejected,
this, &InputDialog::reject);
Q_ASSERT(conn);
setLayout(lytMain);
}
QStringList InputDialog::getStrings(QWidget *parent, bool *ok)
{
InputDialog *dialog = new InputDialog(parent);
QStringList list;
const int ret = dialog->exec();
if (ok)
*ok = !!ret;
if (ret) {
foreach (auto field, dialog->fields) {
list << field->text();
}
}
dialog->deleteLater();
return list;
}
Now you can use getStrings() method similar to QInputDialog::getText():
QStringList list = InputDialog::getStrings(this);
if (!list.isEmpty()) {
// use list
}
Or
bool ok;
QStringList list = InputDialog::getStrings(this, &ok);
if (ok) {
// use list
}