Printing a PDF file from Qt - c++

I have found following code snippet which works as my expectation, but the problem is that, when a PDF file is open and user print the PDF file with some other printer from the PDF reader and not close the PDF reader and again print the PDF file from my application, it will print with printer which is configured on PDF reader not the printer which I set as to print the PDF file.
Example:
On application I set Printer_1 as to print PDF file.
Print the file (it will open the file in PDF reader and print with Printer_1 printer).
On PDF reader I go to CTRL + P to print and there I select Printer_2 and click on print.
I don't close the PDF reader and again on application (printer is selected to Printer_1), I print the PDF file. Now the print command is sent to Printer_2 instead of Printer_1.
Please what is the problem in the following code snippet?
#include <QSettings>
#include <QProcess>
#include <QDebug>
int main(int argc, char *argv[])
{
const QString classesRoot = "HKEY_CLASSES_ROOT";
// get ID of .pdf extension
QSettings pdfSettings(classesRoot + "\\.pdf", QSettings::NativeFormat);
QString pdfId = pdfSettings.value("Default").toString();
// get path to default program that associated with PDF files
QString printPath = QSettings(classesRoot + "\\" + pdfId + "\\shell\\print\\command", QSettings::NativeFormat).value("Default").toString();
QString openPath = QSettings(classesRoot + "\\" + pdfId + "\\shell\\open\\command", QSettings::NativeFormat).value("Default").toString();
qDebug() << "print path" << printPath;
qDebug() << "open path" << openPath;
// open .pdf file
QProcess::startDetached(openPath.arg("full path to pdf file.pdf") );
// print .pdf file
QProcess printProcess;
printProcess.start(printPath.arg("full path to pdf file.pdf") );
printProcess.waitForFinished(-1);
return 0;
}

instead of line
QString printPath = QSettings(classesRoot + "\\" + pdfId + "\\shell\\print\\command", QSettings::NativeFormat).value("Default").toString();
use this and all works as expected:
QString printPath = QSettings(classesRoot + "\\" + pdfId + "\\shell\\printto\\command", QSettings::NativeFormat).value("Default").toString();
And pass "filename", "printer name" ,"printer driver" and "port" [driver name and port are not mandatory]

I'm sorry but I'd said that this seems reasonably to be the expected behaviour: if the application is already open and it is designed not to open separate instances for the same file (as many viewers do and as yours does), then is highly probable that current settings (in your case, the current printer) are preserved too, since, basically, nothing has changed. If you reproduce your steps but replacing your program by your own manual opening of the PDF file, I'm quite confident that you'll see the same results.
An option would be to avoid opening an external viewer and directly load the PDF file (currently using a third-party library, such as Poppler) and print it using Qt's modules. You can check this answer for more information about it.

Related

getenv core dump error in daemon service program

I wrote a daemon service program and I want to open a file in /home/user path while the service is active. But I don't want to open file as root. The first thing I tried for this was to get the user name with the getenv("USER") function, keep it in a string, and then open a txt file with this string path. But after daemonize the program getenv function caused core dump.
int main(){
make_daemon();
const char *userName = "USER";
const char *homePath = "/home/";
const char *env_p = getenv(userName); //Core dump!
std::string m_filePath = homePath;
m_filePath += env_p;
m_filePath += "/test.txt"; // "/home/<user>/test.txt"
//open filePath
//some stuff...
}
I can probably solve this problem by running the service as root and creating a text file somewhere in the /usr/local/ path, but I want to create the text file with the user, not root. Is it possible or is there any other way to do this?

QFileDialog::setNameFilter only show files with no extension

In my project I open a QFileDialog to have the user select a file to open. The file I'm expecting does not have an extension. I would like to set a filter that only shows files that don't have any extension.
Currently, I filter out any files that don't have the exact name:
QString path;
QString desktopPath = QStandardPaths::standardLocations(QStandardPaths::DesktopLocation).at(0);
path = QFileDialog::getOpenFileName(this, tr("Select File"), desktopPath + "\\DATAFILE", tr("DATAFILE file (DATAFILE)"));
However, in the case where the file might be renamed (for example, DATAFILE (2)) that file wouldn't show up because the name doesn't match exactly.
Filtering it to accept all files is not what I want either because that would allow any file type to be selected.
Any suggestions? Thanks for your time.

Giving multiple file names as link to Tkinter GUI in python and opening with default application

#python version 2.7.11
import os
from Tkinter import *
fileName = "Nothing" #fileName is required so that the callback function can link the current file name with button click
def callback(event):
#os.startfile() works only on windows machine
os.startfile(fileName) #opens the fileName with its default application (in my case a pdf viewer)
def makeLink(file):
global fileName
fileName = file
link = Label(textbox, text=fileName, fg="blue", cursor="hand2")
link.pack()
link.bind("<Button-1>", callback)
oldDir = os.getcwd()
newDir = os.chdir("pdf folder") #pdf folder contains some pdf files
root = Tk()
textbox = Text(root)
textbox.pack()
allFiles = os.listdir(os.getcwd()) #makes a list of files present in current directory
for file in allFiles:
makeLink(file)
root.mainloop()
os.chdir(oldDir)
I want to select the files of a folder (in above code it's pdf folder) containing some pdf files and display them as a link in GUI window. When pressed on the link, the file should open with it's default application (so the pdf file should open with default pdf viewer). My code is displaying the file names of every file in the "pdf folder" as link. But on clicking on every link, the last file of the folder is opening. Can someone correct the code so that every link opens it's own file. I searched everywhere but found nothing on this topic.
This is exactly what you have coded so far. You're making fileName global and then setting fileName = file where the last assignment will be the last item in your loop. So, this is why it is opening the last file. If you want a user to be able to select options from these I'd suggest a combobox or some other widget that takes the list of filenames as the options. You can then bind on <<ComboboxSelected>> to call your makeLink function.
you should really also rename file. file is a built in.
This problem can surely be done by combobox but when i have many pdf files then every file is placed in a combobox which is not a good way to interact.
Here I have taken two count variables ---- one is global count and one localCount. The localCount is required to remember the count of which file is to be opened.
from Tkinter import *
import os
def callback(count):
os.system("open "+fileNames[count])
def makeLink(files):
localCount = count
link = Button(frame1, text=(count , files), bg="light blue", cursor="hand2", command=lambda: callback(localCount))
link.pack()
oldDir = os.getcwd()
newDir = os.chdir("pdf folder")
fileNames = os.listdir(os.getcwd())
root = Tk()
frame1 = Frame(root)
frame1.pack()
count = 0
for files in fileNames:
makeLink(files)
count += 1
root.mainloop()
os.chdir(oldDir)

Qfile open returns false

I have kept the Content.xml in the same folder where my app.exe exists.
But open call returns false ?
What should be the exact path for the file ?
I do not want to give the complete path for the file but want my code to be path independent "means file which i want to read should be in same folder where my exe is lying"
#define FILE_NAME "Content.xml"
QString xmlFileName(FILE_NAME);
xmlFile.setFileName(xmlFileName);
if ( ! xmlFile.open(QIODevice::ReadOnly|QIODevice::Text) )
{
QMessageBox* msgBox = new QMessageBox();
msgBox->setText("File Not Found !!");
msgBox->setWindowFlags(Qt::WindowStaysOnTopHint);
msgBox->exec();
}
Try to open file with full path like:
xmlFile.setFileName(QCoreApplication::applicationDirPath() + QLatin1Char('/') + xmlFileName);
If you run your code with the run button from Qt Creator, the Content.xml needs to be in the same folder as your code is.

QFileDialog: adding extension automatically when saving file?

When using a QFileDialog to save a file and to specify the extension (like *.pdf) and the user types in a name without this extension, also the saved file hasn't this extension.
Example-Code:
QFileDialog fileDialog(this, "Choose file to save");
fileDialog.setNameFilter("PDF-Files (*.pdf)");
fileDialog.exec();
QFile pdfFile(fileDialog.selectedFiles().first());
now when the user enters "foo" as the name, the file will be saved as "foo", not as "foo.pdf". So the QFileDialog doesn't add the extension automatically. My question: How can I change this?
You could use QFileDialog::setDefaultSuffix():
This property holds suffix added to the filename if no other suffix was specified.
This property specifies a string that will be added to the filename if it has no suffix already. The suffix is typically used to indicate the file type (e.g. "txt" indicates a text file).
For multiple file filters, the following can be done.
import re
import os
def saveFile(self):
path, fileFilter = QFileDialog().getSaveFileName(self, "Save file",
"", "Gnuplot Files (*.plt)"
+ ";;" + "Gnuplot Files (*.gp)"
+ ";;" + "Gnuplot Files (*.gpt)"
+ ";;" + "Text Files (*.txt)")
selectedExt = re.search('\((.+?)\)',fileFilter).group(1).replace('*','')
# Attach extension as per selected filter,
# if file does not have extension.
if not os.path.splitext(path)[1]:
path = path + selectedExt
print(path)