Files
qt6-migration-pipeline/Lts/Common/LtsWidgets/lts_global_wait_dialog.cpp
T

226 lines
4.1 KiB
C++
Executable File

#include "lts_global_wait_dialog.h"
#include "lts_progress_dialog_helper.h"
#include "lts_overlay_loading.h"
#include "lts_dialog.h"
#include "lts_frameless_dialog.h"
#include <QCoreApplication>
#include <QTimer>
#ifdef Q_OS_UNIX
#include <execinfo.h>
#include <dlfcn.h>
#include <cxxabi.h>
#endif
namespace LtsWidgets
{
LtsGlobalWaitDialog::~LtsGlobalWaitDialog()
{
delete m_progressDialog;
}
LtsGlobalWaitDialog::LtsGlobalWaitDialog()
: m_waitingCount(0)
, m_visible(true)
, m_progressDialog(new LtsProgressDialogHelper(nullptr))
, m_hideTimer(new QTimer(this))
{
m_hideTimer->setSingleShot(true);
m_hideTimer->setInterval(500);
connect(m_hideTimer, &QTimer::timeout,
this, &LtsGlobalWaitDialog::hideIt);
}
void LtsGlobalWaitDialog::unarm()
{
m_armed = false;
hideIt();
}
void LtsGlobalWaitDialog::rearm()
{
m_armed = true;
setVisible(true);
}
void LtsGlobalWaitDialog::setVisible(bool visible)
{
if (m_waitingCount > 0 && visible)
showIt();
if (m_waitingCount < 1 && !visible)
hideIt();
}
void LtsGlobalWaitDialog::showIt()
{
if (m_progressDialog->isShown())
return;
m_hideTimer->stop();
if (m_armed)
{
m_progressDialog->slotShowWaitForReplyWindow();
}
}
void LtsGlobalWaitDialog::hideIt()
{
if (!m_progressDialog->isShown())
return;
m_hideTimer->stop();
m_progressDialog->slotStopWaitForReplyWindow();
}
void bt()
{
#ifdef Q_OS_UNIX
void *callstack[128];
const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
int nFrames = backtrace(callstack, nMaxFrames);
char **symbols = backtrace_symbols(callstack, nFrames);
for (int i = 1; i < nFrames; i++)
{
QString address(QStringLiteral("0x%1").arg(QString::number(*(quintptr *)callstack[i], 16)));
QString function;
int offset = -1;
Dl_info info;
if (dladdr(callstack[i], &info) && info.dli_sname)
{
char *demangled = nullptr;
int status = -1;
if (info.dli_sname[0] == '_')
demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status);
function = QString::fromUtf8(status == 0 ? demangled : info.dli_sname == 0 ? symbols[i] : info.dli_sname);
offset = (char *)callstack[i] - (char *)info.dli_saddr;
free(demangled);
}
else
{
function = QString::fromUtf8(symbols[i]);
}
}
free(symbols);
#endif
}
void LtsGlobalWaitDialog::wait(QWidget *parent, const QString &customText)
{
m_progressDialog->setParentWidget(parent);
if (m_waitingCount < 1 && m_visible)
showIt();
setCustomText(customText);
m_waitingCount++;
}
void LtsGlobalWaitDialog::setCustomText(const QString &customText)
{
m_progressDialog->setCustomText(customText);
}
void LtsGlobalWaitDialog::done()
{
if (m_waitingCount == 0)
{
m_hideTimer->start();
return;
}
Q_ASSERT(m_waitingCount > 0);
m_waitingCount--;
if (m_waitingCount == 0)
m_hideTimer->start();
}
static LtsGlobalWaitDialog *s_gwdInstance = nullptr;
void LtsGlobalWaitDialog::cleanupGwdInstance()
{
delete s_gwdInstance;
s_gwdInstance = nullptr;
}
LtsGlobalWaitDialog *LtsGlobalWaitDialog::getInstance()
{
if (!s_gwdInstance)
{
s_gwdInstance = new LtsGlobalWaitDialog;
qAddPostRoutine(&LtsGlobalWaitDialog::cleanupGwdInstance);
}
return s_gwdInstance;
}
}
Waiter::Waiter(const QString &customText)
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(nullptr, customText);
}
Waiter::Waiter(LtsWidgets::LtsDialog *parent, const QString &customText)
: m_parent(parent)
{
m_oldClosableState = m_parent->isClosable();
m_parent->setClosable(false);
m_parent->setCurrentlyBlocking(true);
auto *wait = new LtsWidgets::LtsOverlayLoading;
wait->setText(customText.isEmpty() ? QObject::tr("Waiting for server reply...") : customText);
m_parent->setOverlay(wait);
m_loadingOverlay = wait;
}
Waiter::~Waiter()
{
if (m_loadingOverlay == nullptr)
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
return;
}
m_parent->setClosable(m_oldClosableState);
m_parent->setCurrentlyBlocking(false);
m_loadingOverlay->deleteLater();
}