libui/qt5/main.cpp

139 lines
2.9 KiB
C++

#include "uipriv_qt5.hpp"
#include <QApplication>
#include <QTimer>
#include <QWidget>
#include <QThread>
#include <functional>
const char *styleSheet = R"qcss(
QGroupBox {
font: bold;
color: #333;
/*border: none;*/
}
)qcss";
const char *uiInit(uiInitOptions *o)
{
Q_UNUSED(o); // don't care about something that isn't used
if (QCoreApplication::instance() != nullptr) {
return "another QApplication instance already exists";
}
static int argc = 0;
static const char *argv[] = {"libui"};
auto app = new QApplication(argc,(char **)argv);
if (app == nullptr) {
return "failed to allocate new QApplication";
}
qSetMessagePattern("%{file}:%{line} %{function}(): %{message}");
// few consistency things
app->setQuitOnLastWindowClosed(false);
app->setStyleSheet(styleSheet);
initAlloc();
return NULL;
}
void uiUninit(void)
{
auto app = static_cast<QApplication*>(QCoreApplication::instance());
// not strictly necessary, just so we don't get needless nag from uninitAlloc()
// becasue of cascading it's not possible to iterate over the list (copy)
while (app->topLevelWidgets().count()) {
delete app->topLevelWidgets().first();
}
uninitAlloc();
delete app;
}
void uiFreeInitError(const char *err)
{
Q_UNUSED(err); // we only return static constants for errors
}
void uiMain(void)
{
if (QApplication::instance()) {
QApplication::instance()->exec();
}
}
int uiMainStep(int wait)
{
if (QApplication::instance()) {
if (wait) {
// processEvents will always return immediately if there are no
// immediate events to process
// we would have to install a event listener and run in while loop
// that seems very questionable.. don't understand the use case
qWarning("TODO: wait - no equivalent?");
}
QApplication::instance()->processEvents();
}
return 0;
}
void uiQuit(void)
{
QTimer::singleShot(0,QApplication::instance(), &QApplication::quit);
}
void uiQueueMain(void (*f)(void *data), void *data)
{
if (!QCoreApplication::instance()) {
// no instance...?
return;
}
if (QThread::currentThread()->eventDispatcher()) {
// the simple way to queue something to run on main thread
QTimer::singleShot(0,QCoreApplication::instance(), [f,data]{
f(data);
});
} else {
// very dirty workaround, spawn a new thread.. with event dispatcher to deliver this
// this could be done with custom signal, but since I decided to do
// this without using moc this is the simplest solution I could think of.
// sort of works, but not very light weight and will block to ensure resource cleanup
class Thread : public QThread
{
std::function<void ()> taskForMain_;
void run()
{
QTimer::singleShot(0,QCoreApplication::instance(), taskForMain_);
exec(); // start event loop
}
public:
Thread(std::function<void ()> taskForMain)
: taskForMain_(taskForMain)
{
start();
}
~Thread()
{
quit();
wait();
}
};
Thread([f,data]{
f(data);
});
}
}