I have tried to write some code to print a pdf file using Qt but somehow it's not working.
If anybody has any idea to solve this problem, please provide your tips.
void ChartViewer::onprintBtnClicked(){
String filename = QFileDialog::getOpenFileName(this,"Open File",QString(),"Pdf File(*.pdf)");
qDebug()<<"Print file name is "<<filename;
if(!filename.isEmpty()) {
if(QFileInfo(filename).suffix().isEmpty())
filename.append(".pdf");
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(filename);
QPrintDialog*dlg = new QPrintDialog(&printer,this);
if(textedit->textCursor().hasSelection())
dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
dlg->setWindowTitle(tr("Print Document"));
if(dlg->exec() == QDialog::Accepted) {
textedit->print(&printer);
}
delete dlg;
}
}
I didn't understand your question, but now I get it. You want to print PDF file using Qt, you don't want to print into PDF, right?
Qt does not have support for loading and display PDF.
For PDF support in Qt you need external library poppler. Check this article.
Poppler allows you to render PDF files into QImage and you can easily print QImage
like this.
Here is how do you print text into PDF file.
I tried to edit your code so that I can test it a bit and it works for me, can you check?
Maybe try to check if QPrinter::isValid() returns true in your environment.
#include <QtGui>
#include <QtCore>
int main(int argc, char **argv) {
QApplication app(argc, argv);
QTextEdit parent;
parent.setText("We are the world!");
parent.show();
QString filename = QFileDialog::getOpenFileName(&parent,"Open File",QString(),"Pdf File(*.pdf)");
qDebug()<<"Print file name is "<<filename;
if(!filename.isEmpty()) {
if(QFileInfo(filename).suffix().isEmpty()) {
filename.append(".pdf");
}
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(filename);
QPrintDialog*dlg = new QPrintDialog(&printer,&parent);
dlg->setWindowTitle(QObject::tr("Print Document"));
if(dlg->exec() == QDialog::Accepted) {
parent.print(&printer);
}
delete dlg;
}
return app.exec();
}
Related
I am working on a Save dialog for my qt app. Everything works, but if no file extension is added behind the filename, it won't automatically be saved with the file extension although the filter is selected.
I know i need to set a defaultsuffix option, but even if i do, then it still won't add the extension automatically if its not given.
I found several other similar questions, where i read it works in windows but it could fail on linux distro's. If so, is there a simple workaround? Because right now, i don't have a working solution...
void MainWindow::on_actionSave_Chart_As_triggered()
{
QFileDialog *fileDialog = new QFileDialog;
fileDialog->setDefaultSuffix("files (*);;AstroQt aqt (*.aqt)");
QString fileName = fileDialog->getSaveFileName(this, "Save Radix", ui->label_2->text() +".aqt", "AstroQT(*.aqt)");
qDebug() << " save file name " << fileName << endl;
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
return;
}
setWindowTitle(fileName);
QTextStream out(&file);
QString text = "text that will be saved...";
out << text;
file.close();
}
Edit: After trying multiple solutions, none seemed to work. But it should have, i guess. Why else is there a aftersuffix function...? For now i solved it doing it manually. But i'm not happy with it, there should be a better solution/explanation.
// add extension if none is found.
if(!fileName.endsWith(".aqt"))
fileName.append(".aqt");
If you use the static method getSaveFileName things seems to work correctly:
#include <QFileDialog>
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QString fileName = QFileDialog::getSaveFileName(
nullptr, QObject::tr("Save File"),
"teste.aqt",
QObject::tr("AstroQt (*.aqt)"));
qDebug() << " save file name " << fileName << endl;
return app.exec();
}
I get the correct file name with the extension, if I type something without the extension.
If you take a look at QFileDialog documentation, you will see that getSaveFileName() is an static function. Because of this, there is no way for this method to access a member of the instance of the class that makes use of setDefaultSuffix(). So whatever you set in fileDialog->setDefaultSuffix(...) has nothing to do with what the getSaveFileName() function does.
In ordertTo make it work, you have to run the dialog directly from the instance. You should do something like this:
QFileDialog fileDialog(this, "Choose file to save");
fileDialog.setDefaultSuffix("json");
fileDialog.setNameFilter("json-files (*.json)");
fileDialog.exec();
QFile f(fileDialog.selectedFiles().first());
QFileInfo fileInfo(f);
QString FILE_NAME(fileInfo.fileName());
I am using Qt 5.12 and trying to write test (using QTest) for opening of project stored in some xml format.
In test I use QTimer::singleShot to wait QFileDialog to appear as proposed in QT close window by QTest in locked thread.
The problem is that QFileDialog::selectFile doesn't select anything. This means that OK button is not active, so I can't click on it in my test.
I assume in the following example that full path to file is /tmp/project.xml. Notice that QFileDialog::setDirectory works great: when the following example starts, you are in /tmp dir instead of /.
#include <QApplication>
#include <QFileDialog>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTimer::singleShot(300, []() {
QWidget* window = nullptr;
while (!window) {
window = qApp->activeModalWidget();
}
QFileDialog* fd = qobject_cast<QFileDialog*>(window);
fd->setDirectory("/tmp");
fd->selectFile("project.xml");
});
QString path = QFileDialog::getOpenFileName(nullptr, "Open Project",
"/", QString(),
nullptr, QFileDialog::DontUseNativeDialog);
}
The function selectFile didn't work because of the file name text box (lineEdit) is focused. This behavior comes from the implementation of QFileDialog::selectFile() :
void QFileDialog::selectFile(const QString &filename)
{
// ... function body
//Put the filename into the lineEdit when :
//1. The dialog is not visible or
//2. The lineEdit is not focused.
if (!isVisible() || !d->lineEdit()->hasFocus())
d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
}
To make the program works, there are two ways :
Put the file name directly in the text box
Give the focus away then call selectFile
fd->setDirectory("/tmp");
QLineEdit * lineEdit = qobject_cast<QLineEdit*>(fd->focusWidget());
if( lineEdit ){
//Method 1
lineEdit->setText("project.xml");
//Method 2
lineEdit->nextInFocusChain()->setFocus();
fd->selectFile("project.xml");
}else { //no lineEdit focus found
fd->selectFile("project.xml");
}
In my program, my users can copy a string of text from anywhere and paste it into my program. I use the simple QApplication::clipboard()->text(); function and everything works as expected. However, several of my users are having problems when trying to copy and paste on Windows 8.1
Here is how I access the clipboard text from my paste function:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(QApplication::clipboard()->text().isEmpty())
return;
//do something with clipboard
But if the text was copied from Notepad or Chrome, the text is ALWAYS empty. Windows 7 users have not had any problems. Not ALL Windows 8 users have this issue, it's only a handful but the issue it consistent. When copied from some other random places or within my program itself, the clipboard works fine.
I've tried using mimeData. When using the function formats(), only plain text is an available format, but the text is always empty.
The text being copied from Notepad/Chrome shows up fine in clipboard viewers and stuff and can be pasted elsewhere in other programs.
Copying and pasting is a very important feature in my program and its frustrating that my users can't copy and paste from Notepad or Chrome.
Any ideas? Thanks for your time. :)
EDIT: I tried using the "windows" style technique. There was no change. Here is my current, still unworking code:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(clipboard.isEmpty())
{
//might not actually be empty. Check using the other technique
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL))
{
HGLOBAL hGlobal = GetClipboardData(CF_TEXT) ;//hGlobal is NULL
if (hGlobal != NULL)//This never gets called because it is NULL
{
LPTSTR lpszData = (LPTSTR) GlobalLock(hGlobal) ;
if (lpszData != NULL)
{
clipboard.fromLocal8Bit((const char *)lpszData);
GlobalUnlock(hGlobal) ;
}
}
CloseClipboard() ;
}
if(clipboard.isEmpty())
return;
}
The copied text shows up fine in a clipboard viewer, but my program can't get to it no matter what:
How come GetClipboardData() isn't picking anything up? Again, the copied text CAN be pasted in any other program I've tried... just not mine. But if copied from somewhere else, it works no problem.
EDIT: With this version, When the user copies text and text gets to clipboard, a function copies the text this time to an internal text file not directly to your program, using QFile. Another function copies the text from the internal text file to your program. By this way, i think your program wouldn't have to directly deal with text in the clipboard
clipboard.h
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include <QDialog>
#include <QClipboard>
#include <QLabel>
#include <QHBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QFile>
#include <QTextStream>
class ClipBoard : public QDialog {
Q_OBJECT
public:
explicit ClipBoard(QWidget *parent = 0);
~ClipBoard();
private slots:
//the functions that will copy and paste text from the text file
void copyToTextFile();
void paste();
private:
QPushButton *button;
QTextEdit *edit;
QString textFromClipBoard;
QClipboard *clipBoardText;
QString clipboard;
};
#endif // CLIPBOARD_H
clipboard.cpp
#include "clipboard.h"
#include "ui_clipboard.h"
ClipBoard::ClipBoard(QWidget *parent) : QDialog(parent) {
button = new QPushButton("&Paste Copied Text");
edit = new QTextEdit;
/*when user copies text and text gets to clipboard, the text is copied
from clipboard to a text file then copied from the text file to the
program*/
connect(button, SIGNAL(clicked()), this, SLOT(copyToNotepad()));
connect(button, SIGNAL(clicked()), this, SLOT(paste()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button);
layout->addWidget(edit);
setLayout(layout);
}
/*This function copies text from the clipboard to an internal text file
created by the program*/
void ClipBoard::copyToTextFile() {
clipboard = QApplication::clipboard()->text();
QFile output("out.txt");
if (output.open(QIODevice::ReadWrite | QFile::Truncate |
QIODevice::Text)) {
QTextStream out(&output);
out << clipboard;
}
}
/*This function then copies the text from the internal text file and pastes
it to the text edit. So the program doesn't have to deal directly with the
clipboard*/
void ClipBoard::paste() {
QFile input("out.txt");
if (input.exists()) {
if (input.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&input);
clipboard = in.readAll();
}
}
edit->setText(clipboard);
}
ClipBoard::~ClipBoard() {
}
main.cpp
#include "clipboard.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
ClipBoard w;
w.show();
return a.exec();
}
Look through and compare with your part of the code to see if there's something you did wrong. But as to how you claim it works on some Windows 8.1 systems and don't on others baffles me.
I had similar issue,
the solution for me is sleep.
void MainWindow::on_clipboard_change(){
QThread::msleep(1); //without this line I get allways empty clipboard
QString text = QGuiApplication::clipboard()->text();
qDebug() << "clipboard change event triggered ( " << text << " )";
}
I have a list of textfiles in a treeview (with QFileSystemModel). If a textfile is selected and a print button is pressed. It should show a print dialog and the file should be printed out. I thought (after reading documentations and examples) it should look like this:
void berichtenhistorie::on_printButton_released()
{
QModelIndex index = ui->treeView->currentIndex();
QFileSystemModel *model = (QFileSystemModel*)ui->treeView->model();
QString path = model->filePath(index);
QString name = model->fileName(index);
QString dir = path;
dir.remove(dir.size() - name.size(), name.size());
QFile file(path);
if(file.open(QIODevice::WriteOnly | QIODevice::Text))
{
file.close();
if(file.rename(QString("%1geprint %2").arg(dir, name)))
qDebug() << "renamed";
}
//all above works correctly
QPrinter printer(QPrinter::HighResolution);
printer.setPageSize(QPrinter::A4);
printer.setOrientation(QPrinter::Portrait);
printer.setPageMargins (15,15,15,15,QPrinter::Millimeter);
printer.setFullPage(false);
printer.setOutputFileName(path);
printer.setOutputFormat(QPrinter::NativeFormat);
QPainter painter(&printer);
painter.end();
}
The renaming part (so above all the printing stuff) works as it should, no errors or anything. But I get abunch of errors at the printing error. I thought it was because of the libraries, because im using Qt5.
#include <QDirModel>
#include <QDebug>
#include <QMessageBox>
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrinter>
#include <QPainter>
#include <QFile>
Here are the errors:
Apparently you are using Qt5, where printing functionality has been placed in separate add on (in Qt4 it is part of QtGui module), see documentation. So you have to add to pro file this line:
QT += printsupport
This will fix your build error, but your code doesn't print yet. You have to use painter.
If you are planing to support Qt4 it should be like this
greaterThan(QT_MAJOR_VERSION, 4) {
QT += printsupport
}
EDIT: I managed to get a compiling and non crashing version. The only thing left is to get the desired output, however this particular question (why it crashes) has been answered so I am closing the question. I will post the working code before the broken one.
Good day! I am trying to create a small example that will simply create a pdf document. Everything compiles, however when the program starts it simply crashes. I am using Qt version 5.0.0
---New working code---
int main( int argc, char **argv )
{
QApplication app( argc, argv );
QTextDocument doc;
doc.setHtml( "<p>A QTextDocument can be used to present formatted text "
"in a nice way.</p>"
"<p align=center>It can be <b>formatted</b> "
"<font size=+2>in</font> <i>different</i> ways.</p>"
"<p>The text can be really long and contain many "
"paragraphs. It is properly wrapped and such...</p>" );
QPrinter printer;
printer.setOutputFileName("C:\\Users\\SameTime\\Desktop\\Cutie\\PDFPrintMaybe");
printer.setOutputFormat(QPrinter::PdfFormat);
doc.print(&printer);
printer.newPage();
return 0;
}
Here is the project code:
#-------------------------------------------------
#
# Project created by QtCreator 2013-06-08T10:07:11
#
#-------------------------------------------------
QT += core
QT -= gui
QT += printsupport
TARGET = PDFPrintMaybe
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
----Old code with error---
And here is the main cpp:
#include <QCoreApplication>
#include <QTextDocument>
#include <QPrinter>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextDocument doc;
doc.setHtml("<h1>Testing, testing, is this thing on?!</h1>");
QPrinter printer;
printer.setOutputFileName("C:\\Users\\SameTime\\Desktop\\Cutie\\PDFPrintMaybe");
printer.setOutputFormat(QPrinter::PdfFormat);
doc.print(&printer);
printer.newPage();
return a.exec();
}
I am a bit at a loss since it is compiling but crashing (almost) instantly when ran.
Try to create the objects on the heap otherwise they get automatically deleted when they ran out of scope, then the framework probably tries to delete them again and crashes.
QTextDocument *doc = new QTextDocument();
doc->setHtml("<h1>Testing, testing, is this thing on?!</h1>");
QPrinter* printer = new QPrinter();
printer->setOutputFileName("C:\\Users\\SameTime\\Desktop\\Cutie\\PDFPrintMaybe");
printer->setOutputFormat(QPrinter::PdfFormat);
doc->print(printer);
printer->newPage();