Xin hat geschrieben:nufan hat geschrieben:Xin hat geschrieben:und ich bin mir nicht 100%ig sicher, was Du willst.
In meinem Programm brauche ich einige externe Tools (apt, mount, rsync, chmod...). Es wäre ziemlich aufwändig immer die entsprechenden Bibliotheken zu verwenden. Das würde ewig dauern mich darin einzuarbeiten. Deshalb setze ich diese Programme voraus und installiere sie falls sie nicht vorhanden sind.
Dann installiere Dich, setz Dich ins richtige Verzeichnis und starte Dich selbst neu, stelle damit fest, dass Du alles installiert hast und tu, was Du eigentlich tun wolltest.
Hmm... ich glaube ich verstehe was du meinst, das mit dem Verzeichnis wechseln kann ich mir aber sparen:
Code: Alles auswählen
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <iostream>
using namespace std;
int main (int argc, char *argv[])
{
if (argc == 1) // keine extra Parameter
{
// -> zweiten Prozess starten
char *path = new char [strlen (argv[0]) + strlen (" -copy") + 1]; // Speicher für Pfad und Parameter reservieren
char c; // Hilfsvariable zum Einlesen
strcpy (path, argv[0]); // Pfad des Programms kopieren
strcat (path, " -copy"); // Parameter dranhängen
FILE *copy = popen (path, "r"); // Programm nochmal mit Parameter zum Lesen starten
sleep (1); // ein bisschen drauf warten (nicht schön gelöst...)
while (feof (copy) == 0) // solange was da ist lesen und ausgeben
{
c = fgetc (copy);
if (isprint (c) != 0 || isspace (c) != 0)
cout << c;
}
cout << endl;
pclose (copy); // anderen Prozess beenden
delete[] path; // Speicher wieder freigeben
}
else if (strcmp (argv[1], "-copy") == 0) // Programm wurde mit Parametern aufgerufen -> zweiter Prozess
{
FILE *shell = popen ("sh", "w"); // sh zum Schreiben starten
fprintf (shell, "ls"); // irgendein Programm ausführen
pclose (shell); // sh beenden
}
return 0;
}
Das ist sicher schön gelöst, aber ich kann nun mit dem ersten Programm keinen Einfluss mehr auf das zweite nehmen.
Nach etwas herumprobieren hab ich eine für mich perfekte Lösung gefunden:
main.cpp:
Code: Alles auswählen
#include <QApplication>
#include "ShellDialog.h"
int main (int argc, char *argv[])
{
QApplication app (argc, argv);
ShellDialog dialog;
dialog.show ();
return app.exec ();
}
CommandLine.h:
Code: Alles auswählen
#ifndef COMMANDLINE_H
#define COMMANDLINE_H
#include <QLineEdit>
// Widget to enter single line of text
class CommandLine : public QLineEdit
{
Q_OBJECT
public:
CommandLine ();
private slots:
// emits the signal "comamndEntered ()" with the widget's text and clears the widget when enter is pressed
void emitCommandSignal ();
signals:
// current text of the widget is passed; is used to pass a command to the shell
void commandEntered (QString command);
};
#endif
CommandLine.cpp:
Code: Alles auswählen
#include "CommandLine.h"
CommandLine::CommandLine ()
{
connect (this, SIGNAL (returnPressed()), this, SLOT (emitCommandSignal())); // call slot when enter is pressed
}
void CommandLine::emitCommandSignal ()
{
emit commandEntered (text ()); // emit signal with current text
clear (); // clear the widget's text
}
Shell.h:
Code: Alles auswählen
#ifndef SHELL_H
#define SHELL_H
#include <QProcess>
#include <QString>
// creates a shell as new process
class Shell : public QProcess
{
Q_OBJECT
public:
Shell (); // starts and sets up the process
~Shell (); // stops the process
public slots:
void exec (const QString& command); // executes the passed command in the shell
private slots:
void showOutput (); // emits signal to show output of process in a widget
signals:
void newText (QString text); // output of the process is passed
};
#endif
Shell.cpp:
Code: Alles auswählen
#include "Shell.h"
Shell::Shell ()
{
// signal with text is emitted when output is available
connect (this, SIGNAL (readyReadStandardOutput()), this, SLOT (showOutput()));
setProcessChannelMode (QProcess::MergedChannels); // merge stdout and stderr
start ("sh"); // start shell
waitForStarted (); // give it time to start up
}
Shell::~Shell ()
{
close (); // stop the process
}
void Shell::exec (const QString& command)
{
write ((command + '\n').toStdString ().c_str ()); // write command to the shell
emit newText ("<b>$ " + command + "</b>"); // emit highlighted command to be appended to a widget
}
void Shell::showOutput ()
{
emit newText (readAllStandardOutput()); // emit all available output of the process
}
ShellDialog.h:
Code: Alles auswählen
#ifndef SHELLDIALOG_H
#define SHELLDIALOG_H
#include "Shell.h"
#include "CommandLine.h"
#include <QWidget>
#include <QTextEdit>
#include <QVBoxLayout>
// dialog that has a commandline and a widget for output
class ShellDialog : public QWidget
{
Q_OBJECT
public:
ShellDialog (); // creates widgets and sets up connections
~ShellDialog ();
private:
QVBoxLayout *layout; // layout for commandline and output widget
QTextEdit *outputwidget; // widget to show the output of the process
CommandLine *commandline; // single line widget that emits signal when enter is pressed
Shell sh; // shell started in a separate process
};
#endif
ShellDialog.cpp:
Code: Alles auswählen
#include "ShellDialog.h"
ShellDialog::ShellDialog ()
{
// create widgets
layout = new QVBoxLayout;
commandline = new CommandLine;
outputwidget = new QTextEdit;
// user can select text, but not change it
outputwidget -> setTextInteractionFlags (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
// add widgets to the layout
layout -> addWidget (commandline);
layout -> addWidget (outputwidget);
setLayout (layout); // apply layout to the widget
setWindowTitle ("sh");
// execute command entered in commandline in shell
connect (commandline, SIGNAL (commandEntered (QString)), &sh, SLOT (exec (QString)));
// append output of the shell-process to the output widget
connect (&sh, SIGNAL (newText (QString)), outputwidget, SLOT (append(QString)));
}
ShellDialog::~ShellDialog ()
{
delete outputwidget;
delete commandline;
delete layout;
}
And that's the Qt way to do it
Hier noch ein Bild von dem Programm in Aktion:
So... Problem endlich gelöst. Danke für die Hilfe, aber das war leider von mir der falsch Ansatz
