QtWidget Convert HTML to PDF - c++

The code below is based on this question.
But I still can't get it to work. From basic debugging I think there is something wrong with passing the filenames to the function. There is no reaction at all when I clicked on the "Print as PDF" button.
The main code is as below. If you would like to see further, feel free to ask them from me. Thanks.
Part of main.cpp
QApplication app(argc, argv);
//Get filename for all documents
QString filename = get_filename(Var_STR);
QString txt = txt_filename(filename);
QString csv = csv_filename(filename);
QString html = html_filename(filename);
//Print report in .txt, .csv and .html accordingly
heading(txt, csv, html, Var_STR, Var_INT[6], Var_INT[16], Var_INT[17]);
pp_prerinse(txt, csv, html, Var_INT[18], Var_INT[19], Var_INT[20], Var_INT[21], Var_INT[22], Var_INT[23], Var_INT[24], Var_INT[25], Var_INT[26], Var_REAL[11], Var_INT[30], Var_INT[31], Var_INT[32]);
pp_wash(txt, csv, html, Var_STR, Var_INT[33], Var_INT[34], Var_INT[35], Var_INT[36], Var_INT[37], Var_INT[38], Var_REAL[23], Var_INT[41], Var_INT[42], Var_INT[43], Var_REAL[28], Var_INT[47], Var_INT[48], Var_INT[49], Var_INT[50], Var_INT[51], Var_INT[52], Var_INT[53], Var_INT[54], Var_INT[55], Var_REAL[40]);
pp_rinse(txt, csv, html, Var_INT[59], Var_INT[60], Var_INT[61], Var_INT[62], Var_INT[63], Var_INT[64], Var_INT[65], Var_INT[66], Var_INT[67], Var_INT[68], Var_INT[69], Var_INT[70], Var_INT[71], Var_INT[72], Var_INT[73], Var_INT[74], Var_INT[75], Var_INT[76], Var_INT[77], Var_REAL[61]);
phase_prerinse(txt, csv, html, Var_STR, Var_REAL[64], Var_REAL[67], Var_REAL[70]);
wash(txt, csv, html, Var_STR, Var_REAL[73], Var_REAL[75], Var_REAL[77], Var_REAL[79], Var_REAL[81], Var_REAL[83], Var_REAL[85], Var_REAL[87], Var_REAL[89], Var_REAL[91], Var_REAL[94], Var_REAL[97]);
rinse(txt, csv, html, Var_INT[129], Var_STR);
basin_flush(txt, csv, html, Var_STR);
alarms_code(txt, csv, html, Var_REAL[100], Var_REAL[103], Var_REAL[106]);
tail(txt, csv, html);
//Report preview UI and convert .html to .pdf
QDir htmlpath = QFileInfo(html).absoluteDir();
MainWindow mainWindow((htmlpath.absolutePath())+"/"+html, filename);
mainWindow.setWindowTitle("Print Preview");
mainWindow.showMaximized();
return app.exec();
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QObject>
#include <QMainWindow>
#include <QWebView>
#include <QUrl>
#include <QPushButton>
#include <QString>
#include "windows.h"
#include <algorithm>
#include "qt_windows.h"
#include "qwindowdefs_win.h"
#include <ShellAPI.h>
namespace Ui
{
class MainWindow;
class QPrinter;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QString previewfile = "", QString file = "", QWidget *parent = 0);
virtual ~MainWindow();
public slots:
void buttonPrint(QString filepath);
void buttonCancel();
private:
QWebView *m_pWebView; //Preview of the report layout
QPushButton *m_button; //Print button
QPushButton *n_button; //Cancel button
QString printfile;
QString filepath;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "stdafx.h"
#include "mainwindow.h"
#include <QPrinter>
#include <QTextDocument>
#include <QTextStream>
#include <QFile>
#include <QDir>
MainWindow::MainWindow(QString previewfile, QString file, QWidget *parent)
: QMainWindow(parent)
{
//Open html version of report
m_pWebView = new QWebView(this);
//Set position and size
m_pWebView->setGeometry(0, 0, 1000, 735);
m_pWebView->load(QUrl::fromLocalFile(previewfile));
//Create "print" button
m_button = new QPushButton("Print as PDF", this);
//Set location of button
m_button->setGeometry(QRect(QPoint(1100, 150), QSize(75, 23)));
//Print button action
connect(m_button, SIGNAL(clicked()), this, SLOT(buttonPrint(file)));
n_button = new QPushButton("Cancel", this);
n_button->setGeometry(QRect(QPoint(1100, 179), QSize(75, 23)));
connect(n_button, SIGNAL(clicked()), this, SLOT(buttonCancel()));
}
void MainWindow::buttonPrint(QString filepath)
{
QFile htmlfile(filepath+".html");
if(htmlfile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QString htmlContent;
QTextStream in(&htmlfile);
htmlContent = in.readAll();
QTextDocument *document = new QTextDocument();
document->setHtml(htmlContent);
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(filepath+".pdf");
document->print(&printer);
delete document;
buttonCancel();
}
}
void MainWindow::buttonCancel()
{
QApplication::quit();
}
MainWindow::~MainWindow()
{
}

I recommend you to porting from QTWebKit to QTWebEngine which use Chromium as native browser, faster and newst. Check for details:
http://doc.qt.io/qt-5/qtwebenginewidgets-qtwebkitportingguide.html
With 5.6, Qt WebKit and Qt Quick 1 will no longer be supported and are dropped from the release. Qt 5.7 integrates printsupport for browser so let's try to use Chromium:
First of all, include:
QT += webengine webenginewidgets printsupport
Now, try something like this:
// Create the webview
QWebEngineView *webView = new QWebEngineView(this);
webView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->centralWidget->layout()->addWidget(webView);
// Path to the HTML file
const QString filePath = QFileDialog::getOpenFileName(this, "Import HTML", ".", "HTML Files (*.html)");
// Check if the file exist
QFileInfo fileInfo(filePath);
if (!fileInfo.isFile()) {
qDebug() << "Warning, file not found!";
}
// Preview the HTML file
webView->load(QUrl::fromLocalFile(fileInfo.filePath()));
// How to print the page?
// Get the path to the pdf file
const QString pdfPath = QFileDialog::getSaveFileName(this, "Export to pdf", ".", "PDF Files (*.pdf)");
// Print the page in pdf format
webView->page()->printToPdf(pdfPath);

Related

How do I get the text from a QTableView cell into a QlineEdit on click Qt5 C++

So I have been trying all day to find a working example of how to retrieve the data from a QtableView into a lineEdit as a QString. I think I have tried every example code online and have had zero success, I can not even figure out how to pull the row and column numbers from the tableView. Everything I have tried fails and I get the error that index is a unused parameter. This has got to be something simple that I am missing but I have not used QT or done any C++ programing since version 3 and am completely baffled. mainWindow.cpp is below. Thanks in advance for any help you can give me. BTW everything works fine except for the clicked slot.
#include <QDebug>
#include <QAbstractTableModel>
#include <QModelIndex>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->setupUi(this);
// Create a data model for the mapping table from a CSV file
csvModel = new QStandardItemModel(this);
csvModel->setColumnCount(2);
//csvModel->setHorizontalHeaderLabels(QStringList() << "Name" << "Number");
ui->tableView->setModel(csvModel);
// Open the file
QFile file("/home/foo.csv");
if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
qDebug() << "File not exists";
} else {
// Create a thread to retrieve data from a file
QTextStream in(&file);
//Read to end
while (!in.atEnd())
{
QString line = in.readLine();
QList<QStandardItem *> standardItemsList;
for (QString item : line.split(",")) {
standardItemsList.append(new QStandardItem(item));
}
csvModel->insertRow(csvModel->rowCount(), standardItemsList);
}
file.close();
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
qDebug() << "test";
}
Header code below
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_tableView_clicked(const QModelIndex &index);
private:
Ui::MainWindow *ui;
QStandardItemModel *csvModel;
};
#endif // MAINWINDOW_H
I think this is just a basic misunderstanding with regard to how signals/slots operate. Unless you're using the auto connect feature you need to manually connect a signal to a slot using one of the QObject::connect overloads. So in your constructor you need something like...
connect(ui->tableView, &QTableView::clicked, this, &MainWindow::[on_tableView_clicked);

How can QAction ask for input when triggered?

I am trying to have a little OpenGL drawing application which needs files. I need to open a file using the menu bar. What I want is, when a user triggers the action, there is a little popup window that allows the user to enter the input.
Is is possible to do so using Qt? If yes, how?
glmainwindow.cpp
#include "glmainwindow.h"
#include <QGroupBox>
#include <QMenuBar>
glMainWindow::glMainWindow(fileReader reader, QWidget *parent) : QMainWindow(parent)
{
// initialization(reader);
QGroupBox *box = new QGroupBox(this);
mainLayout = new QGridLayout();
glWidget = new mainWidget(reader.p1, reader.p2);
mainLayout->addWidget(glWidget, 0, 0); //glWindow, 0, 0); //instance, 0, 0); //glWindow, 0, 0); //game, 1, 0); //simpleTex, 0, 0); //cubeTextureWindow, 0, 0);
/* Above FOR simpleGame */
userInput = new QLineEdit;
mainLayout->addWidget(userInput, 1, 0);
box->setLayout(mainLayout);
setCentralWidget(box);
setGeometry(150, 200, 720, 740);
createActions();
createMenus();
}
void glMainWindow::createMenus()
{
glMenuBar = menuBar();
fileMenu = new QMenu("File", this);
fileMenu->addAction(openFileAction);
fileMenu->addAction(closeAction);
glMenuBar->addMenu(fileMenu);
}
void glMainWindow::createActions()
{
openFileAction = new QAction(tr("Open file"), this);
// connect(openFileAction, &QAction::triggered)
closeAction = new QAction("Exit", this);
connect(closeAction, &QAction::triggered, glWidget, &QWidget::close);
}
glMainWindow.h
#ifndef GLMAINWINDOW_H
#define GLMAINWINDOW_H
#include <QPushButton>
#include <QLabel>
#include <QMainWindow>
#include <QGridLayout>
#include <QSlider>
#include <QLineEdit>
#include <QAction>
#include "../roadsFileRead/filereader.h"
#include "mainwidget.h"
class glMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit glMainWindow(fileReader reader, QWidget *parent = nullptr);
private:
void createMenus();
void createActions();
private:
QGridLayout *mainLayout;
mainWidget *glWidget{nullptr};
QSlider* xSlider;
QSlider* ySlider;
QSlider* zSlider;
QLineEdit *userInput;
QMenuBar *glMenuBar;
QMenu *fileMenu;
QAction *closeAction{nullptr};
QAction *openFileAction{nullptr};
};
#endif // GLMAINWINDOW_H
I have tried searching online and similar stackoverflow questions, but to no avail. However, I have seen some applications do this. I found similar tutorials, but they didn't have anything that's like what I want. How can I connect this to the triggering of the action? Also, I am not using Qt Designer.
you are almost there... just add a QfileDialog as suggested in the comments..
void glMainWindow::createActions()
{
//define the object for the file name:
QString fileName = "";
openFileAction = new QAction(tr("Open file"), this);
connect(openFileAction, &QAction::triggered, []()
{
fileName = QFileDialog::getOpenFileName(this,
tr("Open the file"), "/home/user/path", tr("my Files (*.txt *.csv)"));
});
....
}
So I got my own way. I used QInputDialog NOT QFileDialog, as QFileDialog doesn't help and is confusing. I added this to glmainwindow.h:
void openFileAct()
{
QString filePath = QInputDialog::getText(0, "File path",
"FIle path", QLineEdit::Normal,
"");
openFile(filePath.toStdString());
}
where openFile is the function that opens the file. I connected the action to openFileAct.

How to get file name in Qt?

I have modified the Text Finder example which I got from a Qt Tutorial and made a Text Viewer. In this program, the user types in the address of the file and clicks the Search button. The program then displays the content of the text file. Below is my code.
text_finder.cpp:
#include "text_finder.h"
#include "ui_text_finder.h"
#include <QHBoxLayout>
#include <QFile>
#include <QTextStream>
#include <QFileDialog>
Text_Finder::Text_Finder(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Text_Finder)
{
ui->setupUi(this);
}
Text_Finder::~Text_Finder()
{
delete ui;
}
void Text_Finder::loadFile(QFile file){ // I have to pass the file name as parameter.
QFile inputFile(file);
inputFile.open(QIODevice::ReadOnly);
QTextStream in(&inputFile);
QString line = in.readAll();
inputFile.close();
ui->read->setText(line);
QTextCursor cursor = ui->read->textCursor();
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1);
}
void Text_Finder::on_search_clicked()
{
// Code that gets the path from the text box.
loadFile();//Parameters not passed yet.
}
I have not yet entered the code which gets the name of the file from the address of the text box. I will have to pass the file to the loadFile() function which will enter the contents into the Text Edit in the center of the program. I want a solution to get the name of the file of which the user enters. For example, the user might enter, "/home/user/input.txt". The program should get the contents of that file and forward it to loadFile(). An solution with an explanation on how the various parts work is needed. I am using Qt Creator on Ubuntu 15.04 (Beta).
If i understand you correctly, the user types the full path or address of the file in the text box and you want to get just the name of the file out of the full path the user entered.
EDIT: I realized using 'QFileDialog' was the ideal way to get the file name. So this
is how i redesigned the whole code;
text_finder.h
#ifndef TEXT_FINDER_H
#define TEXT_FINDER_H
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
#include <QFileDialog>
class Text_Finder : public QWidget{
Q_OBJECT
public:
Text_Finder(QWidget *parent = 0);
~Text_Finder();
public slots:
void on_search_clicked();
void open();
//void loadFile(QString const &filename);
private:
void loadFile(QString const &filename);
QLineEdit *txtFileName;
QTextEdit *txtFileContents;
QString fileName;
QPushButton *search;
QPushButton *openFile;
};
#endif
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
text_finder.cpp
#include "text_finder.h"
Text_Finder::Text_Finder(QWidget *parent) : QWidget(parent) {
openFile = new QPushButton("Open File");
connect(openFile, SIGNAL(clicked()), this, SLOT(open()));
txtFileName = new QLineEdit;
search = new QPushButton("&Search");
txtFileContents = new QTextEdit;
QHBoxLayout *dialogAndViewLayout = new QHBoxLayout;
dialogAndViewLayout->addWidget(openFile);
dialogAndViewLayout->addWidget(txtFileName);
dialogAndViewLayout->addStretch();
dialogAndViewLayout->addWidget(search);
QVBoxLayout *layout = new QVBoxLayout;
layout->addLayout(dialogAndViewLayout);
layout->addWidget(txtFileContents);
connect(search, SIGNAL(clicked()), this, SLOT(on_search_clicked()));
setLayout(layout);
}
Text_Finder::~Text_Finder(){
delete txtFileName;
delete txtFileContents;
delete search;
delete openFile;
}
void Text_Finder::loadFile(QString const &filename){
QFile inputFile(filename);
inputFile.open(QIODevice::ReadWrite | QIODevice::Text);
QTextStream textStream(&inputFile);
QString contents = textStream.readAll();
inputFile.close();
txtFileContents->setPlainText(contents);
}
void Text_Finder::on_search_clicked() {
loadFile(fileName);
}
/*this slot opens a file dialog. After the file has been selected, it sets
the file to the text text edit box*/
void Text_Finder::open() {
fileName = QFileDialog::getOpenFileName(this, "Open text", "/home/",
"");
txtFileName->setText(fileName);
}
mainwindow.cpp
#include "mainwindow.h"
#include "text_finder.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
Text_Finder *textFinder = new Text_Finder;
setCentralWidget(textFinder);
}
MainWindow::~MainWindow() {
}
Finally
main.cpp
#include "text_finder.h"
#include <QApplication>
int main(int argc, char **argv){
QApplication app(argc, argv);
Text_Finder *window = new Text_Finder;
window->show();
return app.exec();
}
Unless you're going to do some programmatic editing, you do not need to use QTextCursor at all.
I suggest you have a browse through the reference manual before trying to carry on since it's clear that you are not familiar with the bare-basics of the graphical widgets you're using.
If you're only reading in a file name and then displaying the contents in plain text format, this is all you need to do. (I'm assuming your filename is entered into a QLineEdit widget and ui->read is a QTextEdit widget)
void Text_Finder::loadFile(QString const &filename){ // I have to pass the file name as parameter.
QFile inputFile(filename);
inputFile.open(QIODevice::ReadOnly);
QTextStream in(&inputFile);
QString contents = in.readAll();
inputFile.close();
ui->read->setPlainText(contents);
}
void Text_Finder::on_search_clicked()
{
QString filename = ui->filename->text();
loadFile(filename);
}
EDIT:
I've created a fully-functional remake of your code, incorporating the changes I suggested. I have compiled and tested it and it is working as per your description.
Note: In the absence of your UI file, I've created the user interface manually.
text_finder.h
#ifndef TEXT_FINDER_H
#define TEXT_FINDER_H
#include <QMainWindow>
class QLineEdit;
class QTextEdit;
class Text_Finder : public QMainWindow{
Q_OBJECT
public:
Text_Finder(QWidget *parent = 0);
~Text_Finder();
public slots:
void on_search_clicked();
private:
void loadFile(QString const &filename);
QLineEdit *txtFileName;
QTextEdit *txtFileContents;
};
#endif // TEXT_FINDER_H
main.cpp
#include "text_finder.h"
#include <QApplication>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
Text_Finder::Text_Finder(QWidget *parent) :
QMainWindow(parent)
{
QWidget *ui = new QWidget(this);
QHBoxLayout *hLayout = new QHBoxLayout;
txtFileName = new QLineEdit(this);
QPushButton *loadButton = new QPushButton("Load File", this);
connect(loadButton, &QPushButton::clicked, this, &Text_Finder::on_search_clicked);
hLayout->addWidget(txtFileName);
hLayout->addWidget(loadButton);
QVBoxLayout *vLayout = new QVBoxLayout(this);
vLayout->addLayout(hLayout);
txtFileContents = new QTextEdit(this);
vLayout->addWidget(txtFileContents);
ui->setLayout(vLayout);
setCentralWidget(ui);
}
Text_Finder::~Text_Finder(){
// It's not necessary to explicitly delete any widgets.
// QObject implements the Composite Pattern, which takes care of all this automatically
}
void Text_Finder::loadFile(QString const &filename){
QFile inputFile(filename);
inputFile.open(QIODevice::ReadOnly);
QTextStream in(&inputFile);
QString contents = in.readAll();
inputFile.close();
txtFileContents->setPlainText(contents);
}
void Text_Finder::on_search_clicked()
{
QString filename = txtFileName->text();
loadFile(filename);
}
int main(int argc, char **argv){
QApplication app(argc, argv);
Text_Finder w;
w.show();
return app.exec();
}
HINT for future questions: You will get better answers quicker if you include an SSCCE in your question. What I've included in this edit is a suitable example.

Read text file in textedit Qt C++

I have this text file:
Name 1 Email 1
Name 2 Email 2
Name 3 Email 3
Name 4 Email 4
Name 5 Email 5
This is a list of employees with their emails. I want to make a list in a dialog window with their names displayed there. I thought this was a good way to print out the text file on the dialog window but it isn't working.
employees_dialog.cpp
#include "employees_dialog.h"
#include "ui_employees_dialog.h"
#include <QtCore/QFile>
#include <QtCore/QTextStream>
employees_dialog::employees_dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::employees_dialog)
{
ui->setupUi(this);
getTextFile();
}
employees_dialog::~employees_dialog()
{
delete ui;
}
void employees_dialog::getTextFile()
{
QFile myFile(":/employees.txt");
myFile.open(QIODevice::ReadOnly);
QTextStream textStream(&myFile);
QString line = textStream.readAll();
myFile.close();
ui->textEdit->setPlainText(line);
}
This is the header file.
#ifndef EMPLOYEES_DIALOG_H
#define EMPLOYEES_DIALOG_H
#include <QDialog>
namespace Ui {
class employees_dialog;
}
class employees_dialog : public QDialog
{
Q_OBJECT
public:
explicit employees_dialog(QWidget *parent = 0);
~employees_dialog();
private slots:
private:
Ui::employees_dialog *ui;
void getTextFile();
};
#endif // EMPLOYEES_DIALOG_H
So the textEdit in the UI should display the text file. But it's just blank white. I have the file in Qt Resources File. The debugger doesn't give any errors the application itself is just working fine but the text won't appear in the textEdit.
By the way, I'm new to Qt.
use this:
QFile file( "myfile.txt" );
if ( !file.exists() )
{
qDebug()<<"doesn't exist the file";
}

How to print text in Qt when a button is clicked

I have been reading the Qt documentation for QPrinter and QPrintDialog but I cannot figure how to print the contents in a textEdit field.
Here is the code I have been try and which of course doesn't work.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>
#include <QPainter>
void MainWindow::on_pushButton_clicked()
{
QString textFromField = ui->textEdit->toPlainText();
QPrinter printer;
QPrintDialog *printDialog = new QPrintDialog(&printer, this);
printDialog->setWindowTitle("Print Document");
if(printDialog->exec() != QDialog::Accepted)
{
}
QPainter painter;
painter.begin(&printer);
painter.drawText(100, 100, 500, 500,Qt::AlignLeft | Qt::AlignTop, textFromField);
painter.end();
}
This is the output I get when I run it.
:-1: warning: directory not found for option
'-F/Applications/Qt5.1.0//5.1.0/clang_64/qtbase/lib' :-1: error:
symbol(s) not found for architecture x86_64
Any idea what am I doing wrong? Again all I want is to print the contents in a textEdit field.
The QTextEdit is just an editor for a QTextDocument, which is a powerful class that knows how to print it's content.
QTextDocument *doc = ui->textEdit->document();
doc->print(&printer);