226 lines
4.1 KiB
C++
Executable File
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();
|
|
}
|
|
|
|
|
|
|