how to set an event callback for a domain lifecycle - c++

I'm following this document and I'm using qt to implement this event
#include <QCoreApplication>
#include <QDebug>
#include <libvirt/libvirt.h>
void
domainLifecycleCb(virConnectPtr conn,
virDomainPtr dom,
void * opaque)
{
qDebug() << "test";
}
int main(int argc, char *argv[])
{
virEventRegisterDefaultImpl();
QCoreApplication a(argc, argv);
virConnectPtr conn = virConnectOpen("qemu:///session");
virDomainPtr domain = virDomainLookupByName(conn, "Windows");
qDebug() << virConnectDomainEventRegisterAny(conn,
domain,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(domainLifecycleCb),
NULL, NULL);
return a.exec();
}
I tried different methods but the event doesn't work when the domain gets shutdown or started.
By that I mean the callback function should get call when the domain life-cycle changes, And I'm determining that by showing an output in the callback function.

There is a function that needs to be called in a loop to keep the connection alive
#include <QCoreApplication>
#include <QDebug>
#include <libvirt/libvirt.h>
#include <QThread>
void domainLifecycleCb(virConnectPtr conn,
virDomainPtr dom,
void * opaque)
{
qDebug() << "test";
}
int main(int argc, char *argv[])
{
virEventRegisterDefaultImpl();
QCoreApplication a(argc, argv);
virConnectPtr conn = virConnectOpen("qemu:///session");
virDomainPtr domain = virDomainLookupByName(conn, "WindowsECO");
QThread *thread = QThread::create([]{
while (true) {
qDebug() << virEventRunDefaultImpl();
} });
thread->start();
qDebug() << virConnectDomainEventRegisterAny(conn,
domain,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(domainLifecycleCb),
NULL, NULL);
return a.exec();
}

Related

QInputDialog: OK and CANCEL Buttons: Removing button images for OK and Cancel

In QInputDialog how do I get rid of the icons in the OK and Cancel buttons?
Notice the the icons for cancel and ok. I looked through the properties button couldn't figure out how to remove them.
The strategy of the solution is to first obtain the buttons, but these belong to a QDialogButtonBox, so you must use the findChild() method, then reset the icons, there is only one problem, that the buttons are created when necessary, for example when it is visible or when you change the okButtonText or cancelButtonText. For example in the we can force it by making it visible.
#include <QApplication>
#include <QInputDialog>
#include <QDebug>
#include <QAbstractButton>
#include <QDialogButtonBox>
static int getInt(QWidget *parent,
const QString &title,
const QString &label,
int value=0,
int min=-2147483647,
int max=2147483647,
int step=1,
bool *ok=nullptr,
Qt::WindowFlags flags=Qt::Widget)
{
QInputDialog dialog(parent, flags);
dialog.setWindowTitle(title);
dialog.setLabelText(label);
dialog.setIntRange(min, max);
dialog.setIntValue(value);
dialog.setIntStep(step);
dialog.setVisible(true);
for(QAbstractButton *btn: dialog.findChild<QDialogButtonBox*>()->buttons()){
btn->setIcon(QIcon());
}
int ret = dialog.exec();
if (ok)
*ok = !!ret;
if (ret) {
return dialog.intValue();
} else {
return value;
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
bool ok;
int res = getInt(nullptr, "Factorial Calc", "Factorial of:", 5, 0, 100, 1, &ok);
if(ok)
qDebug()<< res;
return 0;
}
But if you use static methods like QInputDialog::getInt() we will not be able to access the QInputDialog directly, we have to do it a moment after showing the QInputDialog with a QTimer, so there are 2 cases:
A parent is passed to the static method:
#include <QApplication>
#include <QInputDialog>
#include <QDebug>
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
bool ok;
QTimer::singleShot(0, [&widget](){
QInputDialog *dialog = widget.findChild<QInputDialog *>();
for(QAbstractButton *btn: dialog->findChild<QDialogButtonBox*>()->buttons()){
btn->setIcon(QIcon());
}
});
int res = QInputDialog::getInt(&widget, "Factorial Calc", "Factorial of:", 5, 0, 100, 1, &ok);
if(ok)
qDebug()<< res;
return 0;
}
A parent is not passed to the static method:
#include <QApplication>
#include <QInputDialog>
#include <QDebug>
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
bool ok;
QTimer::singleShot(0, [](){
for(QWidget *widget: QApplication::topLevelWidgets()){
if(QInputDialog *dialog = qobject_cast<QInputDialog*>(widget)){
for(QAbstractButton *btn: dialog->findChild<QDialogButtonBox*>()->buttons()){
btn->setIcon(QIcon());
}
}
}
});
int res = QInputDialog::getInt(nullptr, "Factorial Calc", "Factorial of:", 5, 0, 100, 1, &ok);
if(ok)
qDebug()<< res;
return 0;
}

QWebEnginePage does not know its contents size

I have a very simple application using WebEngineView and I just wanted to resize the widget displaying to the contents of the html file. I'm expecting it to be 30 pixels wide. Instead my program prints QSize(0,0) and even worser the widget is not displayed at all.
What I'm doing wrong here?
#include <QWebEngineView>
#include <QApplication>
#include <QDebug>
#include <QWebEnginePage>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto view = new QWebEngineView;
QString html = "<html><body><div width=30px>Text</div></body></html>";
view->setHtml(html);
auto contentsSize=view->page()->contentsSize().toSize();
qDebug() << contentsSize;
view->setFixedSize(contentsSize);
view->show();
return app.exec();
}
Putting my QWebEngineView into a dialog still doesn't work:
#include <QWebEngineView>
#include <QApplication>
#include <QDebug>
#include <QDialog>
#include <QHBoxLayout>
#include <QWebEnginePage>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto dialog = new QDialog;
dialog->setLayout(new QHBoxLayout);
auto view = new QWebEngineView;
dialog->layout()->addWidget(view);
QString html = "<html><body><div width=30px>Text</div></body></html>";
view->setHtml(html);
auto contentsSize=view->page()->contentsSize().toSize();
qDebug() << contentsSize;
view->setFixedSize(contentsSize);
dialog->show();
return app.exec();
}
I also tried to connect to the signal loadFinished, but there is no effect.
#include <QWebEngineView>
#include <QApplication>
#include <QDebug>
#include <QDialog>
#include <QHBoxLayout>
#include <QWebEnginePage>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto dialog = new QDialog;
dialog->setLayout(new QHBoxLayout);
auto view = new QWebEngineView;
dialog->layout()->addWidget(view);
QString html = "<html><body><div width=30px>Text</div></body></html>";
view->setHtml(html);
QObject::connect(view->page(), &QWebEnginePage::loadFinished, [&view](bool b) {
qDebug() << b;
auto contentsSize = view->page()->contentsSize().toSize();
qDebug() << contentsSize;
view->setFixedSize(contentsSize);
});
dialog->show();
return app.exec();
}

gtkmm: Why button only reacts on double click

I want to get a response from the button also if button is only clicked once. The following code only reacts on "double-click". Why does this behavior occur and how can I change that behavior?
#include <iostream>
#include <gtkmm.h>
#include <gtkmm/window.h>
class ExampleWindow: public Gtk::Window
{
Gtk::Button button;
public:
ExampleWindow(): button("Hallo")
{
add(button);
button.signal_button_press_event().connect( [this]( GdkEventButton* ev)->bool{ std::cout << "Press" << std::endl; return true; });
}
};
int main(int argc, char* argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
window.show_all_children();
Gtk::Main::run(window);
return 0;
}

creating QApplication in a different thread

I'm trying to create QApplication in a different thread, but found 2 main problems:
1- I can't interact with GUI
2- some warnings:
WARNING: QApplication was not created in the main() thread.
QObject::startTimer: timers cannot be started from another thread //happens when resizing widget
QObject::killTimer: timers cannot be stopped from another thread
here is the full code: (it may has some memory leaks but for testing purposes it fails)
//main.cpp
#include <QCoreApplication>
#include "cthread.h"
int main(int argc, char *argv[])
{
CThread *MyThread = new CThread;
MyThread->start();
QCoreApplication a(argc, argv);
return a.exec();
}
//CThread.h
#ifndef CTHREAD_H
#define CTHREAD_H
#include <QThread>
#include "theqtworld.h"
class CThread : public QThread
{
Q_OBJECT
public:
CThread();
void run( void );
private:
TheQtWorld *mWorld;
};
#endif // CTHREAD_H
//CThread.cpp
#include "cthread.h"
#include <iostream>
CThread::CThread():mWorld(NULL)
{
}
void CThread::run()
{
std::cout << "thread started" << std::endl;
if(!mWorld)
mWorld = new TheQtWorld();
mWorld->OpenWorld();//now it will init all Qt Stuff inside
// if(mWorld) delete mWorld;
// emit this->exit();
}
//theqtworld.h
#ifndef THEQTWORLD_H
#define THEQTWORLD_H
#include <QObject>
#include "mainwindow.h"
#include <QApplication>
class TheQtWorld : public QObject
{
Q_OBJECT
public:
explicit TheQtWorld(QObject *parent = 0);
int OpenWorld(void);
signals:
public slots:
};
#endif // THEQTWORLD_H
//theqtworld.cpp
#include "theqtworld.h"
TheQtWorld::TheQtWorld(QObject *parent) :
QObject(parent)
{
}
int TheQtWorld::OpenWorld()
{
static int arg = 0;
static char *b[2];
b[0] = "a";
QApplication *a = new QApplication(arg, b);
a->setParent(this);
MainWindow w;
w.show();
return a->exec();
}
I would answer my own question after understanding how to overcome this problem
first the problem was to integrate Qt GUI as a plugin into another Application, so the main issue was the Event loop collision between Qt Events and any other Application Events
my first thoughts was to separate both, so QApplication will stay at a different thread, but this was a totally wrong approach and here is what I have noticed:
1- Qt GUI Must stay in the main() thread so there is no other place for QApplication
2- to avoid the blocking QApplication::exec() , embed QApplication::processEvents() into the other Application Event loop
here is a working code:
//main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication mApp(argc, argv);
MainWindow w;
w.show();
//just for testing and holding the program so it doesn't end
for(int i = 0; i < 100000000; ++i)
{
mApp.processEvents();
}
return 0;
}
edit:thanks to pavel-strakhov for his great suggestion.

how to use QProcess to wrap telenet.exe on Windows?

I'm trying to code a wrapper class using QProcess to drive the CLI applications (e.g. telnet.exe, ftp.exe) on Windows but so far with no luck. Do you know if this is even possible?
Below is the code I used to try with telnet.exe on Windows 7. I was expecting this code will print out the "welcome message" after telnet connected to the server but there is nothing print out (from standard output or error output).
#include <QCoreApplication>
#include <QProcess>
#include <iostream>
class ProcessWrapper :public QObject
{
Q_OBJECT
public:
ProcessWrapper();
~ProcessWrapper();
void start();
public slots:
void readStandardError();
void readStandardOutput();
private:
QProcess *process;
};
ProcessWrapper::ProcessWrapper()
{
process = new QProcess(this);
connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError()));
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
}
void ProcessWrapper::start()
{
if(process) {
process->start("telnet.exe",QStringList() << "135.251.142.36");
process->waitForStarted();
}
}
ProcessWrapper::~ProcessWrapper()
{
if(process) delete process;
}
void ProcessWrapper::readStandardOutput()
{
if(process) {
QByteArray s = process->readAllStandardOutput();
QString str(s);
std::cout << str.toStdString();
}
}
void ProcessWrapper::readStandardError()
{
if(process) {
QByteArray s = process->readAllStandardError();
QString str(s);
std::cout << str.toStdString();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ProcessWrapper p;
p.start();
return a.exec();
}
#include "main.moc"
The function main() exit immediately after you called ProcessWrapper::start().