Handle different application using C++ - c++

Is there any way to control other windows application using c++/qt?
I have: 1000 files of specific image format and an application that can open them. This application can use "Save as..." function to save these files in ".JPEG" format one by one. I want to do this automatically.
Is there any technique to do this? Thank you in advance!

Using QT you have the possibility to run a separate process using a QProcess instance.
Specifically suppose that your external application accepts input parameters (e.g. the filepath to load and the filepath where to store the result.
QProcess shell;
QStringList argv;
//[setup argument-list]
shell.setProcessChannelMode(QProcess::MergedChannels);
shell.start(commandPath, argv);
shell.waitForFinished();
Notice that QProcess can be uses as an IO stream. This is useful to interact with the process (e.g. to retrieve progress information):
shell.start(commandPath, argv);
shell.waitForReadyRead();
while(shell.state() == QProcess::Running || !shell.atEnd()){
auto s = shell.readLine()
//[do something with the current line of the process output]
}
QProcess::ExitStatus es = shell.exitStatus () ;
Of course the external process must accept input parameters and provide feedback through its standard output to solve your problem.

Related

Running a Bash Script with arguments as a Qt resource

Qt newbie here :).
I'm currently executing a bash script in Qt using the popen function to redirect the output to a textBrowser in my application. When I add the script to my project as a resource it does not seem to execute anymore? I use the :/myScript.sh syntax and then try to add my arguments as QStrings.
Any advice will be appreciated!
FILE *in;
char buff[512];
QString args = ":/myScript.sh" + <arguments>;
QByteArray ba = args.toLatin1();
char *temp = ba.data();
if(!(in = popen(temp , "r")))
{
exit(1);
}
while(fgets(buff, sizeof(buff), in)!=NULL)
{
ui->txtConsole->append(buff);
}
ui->progressBar->setValue(50); pclose(in);
Invoking popen with the Qt resource path format will not do what you expect.
You are effectively trying to invoke is this:
popen(":/myScript.sh args", "r");
The popen function doesn't know anything about the Qt resource system nor the :/ syntax. It expects the first parameter to a path on disk that the operating system understands.
Two choices:
Just ship the myScript.sh file as a separate file and execute it directly. (What you observed as working before you tried to make the script a resource). If you aren't using compiled resources, chances are it already is a disk file. Just invoke popen on the absolute path to the file instead of with the :/ syntax.
Write code to extract the myScript.sh text file from the resources and save it locally to disk. Then invoke popen on that saved file.
Its running script file as a qt resource. You add arguments maybe this run.
QStringList arg("-c");
QFile file(":/scriptFile.sh");
arg << file.readAll();
process->start("sh", arg);

Read output of linux command without using temp file

I need to read input of some linux commands to a QString variable. At first, I redirect the stream to a temp file and read from it.
However, I don't like this way. I want to avoid access the hard drive, the less the better.
I try to use the environment variable as the "temp file", then use getenv to get it into a variable.
like this:
QString query="a=$(fdisk -l)";
system(a.toStdString().c_str());
...
char* env;
env= getenv ("a");
however, I get nothing. Add export to the query has the same result.
I manually check the variables by env command. Nothing changed!
So how to fix this? And are there any better way to do this?
Any ideas are appreciated :)
PS: I want to keep the format too, it should keep \t, \n...
If you are using Qt then you should make it in a Qt's fashion, by utilizing QProcess class.
#include <QProcess>
QString command = "/usr/bin/fdisk";
QStringList arguments;
arguments << "-l";
QProcess process;
process.start(command, arguments);
process.waitForFinished(-1);
QByteArray rawOutput = process.readAllStandardOutput();
QStringList output = QString(rawOutput).split("\n");
foreach (QString line, output)
{
// do something with each line from output
}
It cannot work as you wish, because system or popen will start using fork its own shell process, and the a variable is not exported, and even if it was, it will be available only in that shell process and not in the invoking original process.
Remember that changes in child processes cannot affect their parent process in general (except by using some explicit IPC such as pipes between the two).
The only way you could do what your want is to use popen (or some QProcess specific mechanism to read on pipe the stdout of the child command) on fdisk -l then (if you absolutely want to have your getenv later working) use putenv to set your environment variable.
BTW, fdisk is probably using /proc to get its information (which you could get directly, see proc(5) ...).
Read Advanced Linux Programming, and about fork(2) and execve(2)

How to fetch output of command of powershell with C++?

i implemented program of network statistics with help of powershell scrpit. the program is running successfully and giving me perfact output as well . below is my program.
int main(int argc, char *argv[])
{
string strPath = "C:\\Get-NetworkStatistics.ps1";
char str[50] = "C:\\Get-NetworkStatistics.ps1";
char command[500];
//access function:
//The function returns 0 if the file has the given mode.
//The function returns –1 if the named file does not exist or does not have the given mode
if(access(strPath.c_str(),0) == 0)
{
_snprintf(command, sizeof(command), "Start Powershell.exe -noexit Set -executionpolicy;.'%s';Get-NetworkStatistics",str);
system(command);
}
else
{
system("cls");
cout << "File is not exist";
system("pause");
}
return 0;
}
! here is the output of above program
as you can see the output is in the powershell windows.. i want to fetch all this data of powershell output and want to display it in console. how should it possible?
please help me..
Unless you need to do display the info in realtime as it becomes available, just redirect it to a file, then read that file from C++.
Since netstat was lobotomized in Windows XP SP 2 or thereabouts I can understand using Powershell.
But it may just be that netstat will serve your needs, and then you don't have to deal with any of that complication.
By the way, I recommend using a scripting language for scripting tasks. There is of course the complication that Powershell scripting is disabled by default, otherwise using the Powershell scripting facility would be indicated. But e.g. in this case a [cmd.exe] batch file would be more natural than doing its job from C++.
The Windows Script Host shell objects, available from JScript and VBScript, provide functionality for process execution with output grabbing.
There is a little snag in that you then have to poll the output, but I think it's still easier than doing this at the C/C++ API level.

C++ simple open file dialog in linux

I was wondering if anyone could help me out on implementing a simple file open dialog in C++ in Ubuntu. I am using OpenGL for my GUI, but I would like the user to be able to select a file when the program loads. I have tried gtkmm and wxWidgets but they seem to be too complicated for what I want to do.
If you just need to select a file, then launch a separate program to do that. Like #Dummy00001 said in the comment, you can start zenity --file-selection as a child process and read its stdout.
char filename[1024];
FILE *f = popen("zenity --file-selection", "r");
fgets(filename, 1024, f);
Or you can also write your own program to do the task. That way you can customize the UI as you wish.
I wrote osdialog for this purpose. See osdialog_gtk2.c for an example using GTK+ 2.
This project can help you:
https://github.com/samhocevar/portable-file-dialogs
It uses the same idea described in these answers but it is architecture agnostic and for Unix it wraps zenity, kdialog ...
Here you have more complete code with zenity:
const char zenityP[] = "/usr/bin/zenity";
char Call[2048];
sprintf(Call,"%s --file-selection --modal --title=\"%s\" ", zenityP, "Select file");
FILE *f = popen(Call,"r");
fgets(Bufor, size, f);
int ret=pclose(f);
if(ret<0) perror("file_name_dialog()");
return ret==0;//return true if all is OK

How do you get the icon, MIME type, and application associated with a file in the Linux Desktop?

Using C++ on the Linux desktop, what is the best way to get the icon, the document description and the application "associated" with an arbitrary file/file path?
I'd like to use the most "canonical" way to find icons, mime-type/file type descriptions and associated applications on both KDE and gnome and I'd like to avoid any "shelling out" to the command line and "low-level" routines as well as avoiding re-inventing the wheel myself (no parsing the mime-types file and such).
Edits and Notes:
Hey, I originally asked this question about the QT file info object and the answer that "there is no clear answer" seems to be correct as far as it goes. BUT this is such a screwed-up situation that I am opening the question looking for more information.
I don't care about QT in particular any more, I'm just looking for the most cannonical way to find the mime type via C++/c function calls on both KDE and gnome (especially Gnome, since that's where things confuse me most). I want to be able show icons and descriptions matching Nautilus in Gnome and Konquerer/whatever on KDE as well as opening files appropriately, etc.
I suppose it's OK that I get this separately for KDE and Gnome. The big question is what's the most common/best/cannonical way to get all this information for the Linux desktop? Gnome documentation is especially opaque. gnome-vsf has mime routines but it's deprecated and I can't find a mime routine for GIO/GFS, gnome-vsf's replacement. There's a vague implication that one should use the open desktop applications but which one to use is obscure. And where does libmagic and xdg fit in?
Pointers to an essay summarizing the issues gladly accepted. Again, I know the three line answer is "no such animal" but I'm looking for the long answer.
Here is an example of using GLib/GIO to get the information you want.
#include <gio/gio.h>
#include <stdio.h>
int
main (int argc, char **argv)
{
g_thread_init (NULL);
g_type_init ();
if (argc < 2)
return -1;
GError *error;
GFile *file = g_file_new_for_path (argv[1]);
GFileInfo *file_info = g_file_query_info (file,
"standard::*",
0,
NULL,
&error);
const char *content_type = g_file_info_get_content_type (file_info);
char *desc = g_content_type_get_description (content_type);
GAppInfo *app_info = g_app_info_get_default_for_type (
content_type,
FALSE);
/* you'd have to use g_loadable_icon_load to get the actual icon */
GIcon *icon = g_file_info_get_icon (file_info);
printf ("File: %s\nDescription: %s\nDefault Application: %s\n",
argv[1],
desc,
g_app_info_get_executable (app_info));
return 0;
}
You can use the tools available from xdg for that, in particular xdg-mime query.
To find out the filetype of e.g. a file index.html you would
$ xdg-mime query filetype index.html
This will return the mimetype. To query what application is associated with that mimetye use e.g.
$ xdg-mime query default text/html
This returns epiphany.desktop here, i.e. $APPNAME.desktop, so it is easy to get the application name from it. If you would just want to open the file in the default app you could of course just run
$ xdg-open index.html
which would fire up epiphany.
Query functions for icon resources do not seem to be available in xdg-utils, but you could write a small python script using pyxdg that offers tons of additional functionality, too.
For C bindings you will probably need to have a look into the portland code linked on the xdg page.
EDIT:
Concerning libmagic and friends, you will need to decide on your preferences: While libmagic seems to be more complete (and accurate) in terms of coverage for filetypes, it does not care at all about default applications or icons. It also does not provide you with tools to install extra mimetypes.
In Qt >= 4.6, there is a new function for X11 systems
QIcon QIcon::fromTheme ( const QString & name, const QIcon & fallback = QIcon() ) [static]
You can use this function. Documentation here / (Qt 5)
Neither QFileIconProvider nor QFileInfo will do anything with the OS mime database. To access icons associated with different mime types, you will have to use functions of the underlying desktop environment. In Qt there is (yet) no canonical way.
Consider you can have a different icon in Gnome, in KDE and in Windows. So for instance, in KDE you would use KMimeType.
I just found KFileItem. This class gives you everything you for icons, mime types and related things in KDE. I'm sure that there's an equivalent in gnome but this gives access at the same level as a QT application works.
You may want to use the system's "/etc/mime.types" file. It is also a good idea to maintain your program's copy of a MIME type file. That way, you are not dependent on the system, but at the same time you need to keep it fairly exhaustive. Not sure about Icons.
Maybe take a look at this code:
http://ftp.devil-linux.org/pub/devel/sources/1.2/file-4.23.tar.gz
This is the standard file util found on most Linux/Unix distributions. You will get the MIME-type and some more information.
I think both Gnome and KDE have their own ways to determine this and also to set the icon and the standard application for it.
Anyway, that file-tool is probably the best way to get the mime type and the document description. And in some cases even some details about the content.
This will get you the mime-type. That is what you need anyway to know how you can open the file. These are seperated steps. file doesn't say you about the icon nor the application to open the file with.
About 8 years late, but still useful.
To get the associated applications in KDE you can do what Joe suggested (using KFileItem). However, that requires inclusion of a lot of libraries.
The code below requires less.
#include <QCoreApplication>
#include <QMimeDatabase>
#include <QDebug>
#include <KMimeTypeTrader>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
if (argc < 2)
{
qDebug() << "missing argument <filename>";
return 1;
}
QMimeDatabase mimeDb;
QMimeType mimeType = mimeDb.mimeTypeForFile(QString::fromLocal8Bit(argv[1]));
KService::List services = KMimeTypeTrader::self()->query(
mimeType.name(),QStringLiteral("Application"));
foreach(const QExplicitlySharedDataPointer<KService>& svc, services)
{
qDebug() << "service: " << svc->name();
qDebug() << "exec: " << svc->exec();
}
}
To compile the code add QT += KService KCoreAddons to your qmake .pro file.
Links to KMimeTypeTrader & KService documentation:
https://api.kde.org/frameworks/kservice/html/classKService.html
https://api.kde.org/frameworks/kservice/html/classKMimeTypeTrader.html
Copy/Paste of the nice example above (using GLib/Gio) just added proper release of allocated memory as per documentation. I tried to just edit the existing answer but it kept saying the edit queue was full :(
#include <gio/gio.h>
#include <stdio.h>
int
main (int argc, char **argv)
{
g_thread_init (NULL);
g_type_init ();
if (argc < 2)
return -1;
g_autoptr(GError) error;
GFile* file = g_file_new_for_path (argv[1]);
GFileInfo* file_info = g_file_query_info (file,
"standard::*",
G_FILE_QUERY_INFO_NONE,
NULL,
&error);
const char* content_type = g_file_info_get_content_type (file_info);
g_autofree gchar* desc = g_content_type_get_description (content_type);
GAppInfo* app_info = g_app_info_get_default_for_type (
content_type,
FALSE);
/* you'd have to use g_loadable_icon_load to get the actual icon */
GIcon* icon = g_file_info_get_icon (file_info);
printf ("File: %s\nDescription: %s\nDefault Application: %s\n",
argv[1],
desc,
g_app_info_get_executable (app_info));
g_object_unref(file_info);
g_object_unref(file);
return 0;
}