#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 #include #ifdef Q_OS_UNIX #include #include #include #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(); }