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

811 lines
18 KiB
C++
Executable File

#include "lts_dialog.h"
#include "lts_progress_dialog_helper.h"
#include "lts_message_dialog.h"
#include "lts_dialog_helper.h"
#include "lts_dialog_button_box.h"
#include "lts_base_layout_widget.h"
#include "lts_date_time_edit.h"
#include <QHBoxLayout>
#include <QProgressBar>
#include <QLineEdit>
#include <QComboBox>
#include <QCheckBox>
#include <QSpinBox>
#include <QDateTimeEdit>
#include <QSlider>
#include <QPlainTextEdit>
#include <QTextEdit>
#include <QWidget>
#include <QRadioButton>
#include <QTableView>
#include <QTableWidget>
#include <QListView>
#include <QListWidget>
#include <QSlider>
#include <QScroller>
#include <QScrollArea>
#include <QMenu>
#include <QInputDialog>
#include <QHBoxLayout>
#include <QPainter>
#include <QColor>
#include <QMetaMethod>
#include <QDebug>
#include <LtsSession/lts_session_data.h>
namespace LtsWidgets
{
int LtsDialog::s_object_count = 0;
class OverlayContainer : public QWidget
{
Q_OBJECT
public:
OverlayContainer(QWidget *parent);
protected:
void paintEvent(QPaintEvent *e) override;
};
OverlayContainer::OverlayContainer(QWidget *parent)
: QWidget(parent)
{
setAttribute(Qt::WA_TranslucentBackground);
}
void OverlayContainer::paintEvent(QPaintEvent *e)
{
QPainter p(this);
p.fillRect(rect(), { 80, 80, 80, 200 });
QWidget::paintEvent(e);
}
LtsDialog::LtsDialog(QWidget *parent, ButtonCombination buttonCombination, bool closeable)
: QWidget()
, m_changesMade(false)
, m_firstShow(true)
, m_baseLayoutWidget(nullptr)
, m_isClosable(closeable)
, m_noLockTopic(false)
, m_unchangeableDialog(false)
, m_dialogHelper(new LtsDialogHelper(nullptr))
, m_buttonBox(nullptr)
, m_uiRequirements(new UiRequirementList())
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsWidget.LtsDialog"))
{
Q_UNUSED(parent);
s_object_count++;
m_dialogHelper->setDialog(this);
m_buttonBox = m_dialogHelper->getButtonBox();
addDebugMenuButton();
connect(m_buttonBox->getButton(DialogButton::Close), &QPushButton::clicked, this, &LtsDialog::slotClose);
switch(buttonCombination)
{
case ButtonCombination::OkCancel:
{
m_buttonBox->getButton(DialogButton::Close)->setText(tr("Cancel"));
connect(m_buttonBox->getButton(DialogButton::Ok), &QPushButton::clicked, this, &LtsDialog::slotOkay);
break;
}
case ButtonCombination::OkApplyCancel:
{
m_buttonBox->getButton(DialogButton::Close)->setText(tr("Cancel"));
connect(m_buttonBox->getButton(DialogButton::Ok), &QPushButton::clicked, this, &LtsDialog::slotOkay);
connect(m_buttonBox->getButton(DialogButton::Apply), &QPushButton::clicked, this, &LtsDialog::slotApply);
m_buttonBox->getButton(DialogButton::Apply)->setVisible(true);
break;
}
case ButtonCombination::CloseOnly:
{
m_buttonBox->getButton(DialogButton::Ok)->setVisible(false);
setUnchangeable();
break;
}
default:
case ButtonCombination::SeamlessDialog:
{
m_buttonBox->setVisible(false);
setContentsMargins(0,0,0,0);
m_dialogHelper->setContentsMargins(0,0,0,0);
QLayout *l = m_dialogHelper->layout();
if (l)
{
l->setContentsMargins(0,0,0,0);
l->setMargin(0);
}
else
{
qWarning() << "LtsDialog::c_tor: Dialog Helper has no layout to set margins";
}
break;
}
}
if (!closeable)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setVisible(false);
m_buttonBox->getButton(LtsWidgets::DialogButton::Close)->setVisible(false);
}
}
LtsDialog::~LtsDialog()
{
delete m_uiRequirements;
if (m_overlayWidget)
m_overlayWidget->setParent(nullptr);
s_object_count--;
}
void LtsDialog::setOverlay(QWidget *widget)
{
if (m_overlayContainer)
{
if (m_overlayWidget)
{
m_overlayWidget->hide();
m_overlayWidget->setParent(nullptr);
m_overlayWidget->hide();
m_overlayWidget = nullptr;
}
m_overlayContainer->hide();
m_overlayContainer->setParent(nullptr);
m_overlayContainer->hide();
m_overlayContainer->deleteLater();
m_overlayContainer = nullptr;
}
OverlayContainer *overlayContainer = new OverlayContainer(m_dialogHelper);
connect(m_dialogHelper.data(), &LtsDialogHelper::signalSizeChanged,
overlayContainer, [overlayContainer](const QSize &size)
{
overlayContainer->setGeometry(QRect(QPoint(0, 0), size));
});
overlayContainer->setGeometry(QRect(QPoint(0, 0), m_dialogHelper->size()));
m_overlayContainer = overlayContainer;
QHBoxLayout *l = new QHBoxLayout;
m_overlayContainer->setLayout(l);
widget->setAutoFillBackground(true);
l->addWidget(widget, 0, Qt::AlignCenter);
widget->show();
connect(widget, &QWidget::destroyed,
m_overlayContainer.data(), &QObject::deleteLater);
m_overlayWidget = widget;
m_overlayContainer->show();
m_overlayContainer->raise();
}
void LtsDialog::unsetOverlay()
{
if (m_overlayWidget)
m_overlayWidget->setParent(nullptr);
if (!m_overlayContainer)
return;
m_overlayContainer->setParent(nullptr);
m_overlayContainer->deleteLater();
}
LtsDialogHelper *LtsDialog::getHelper()
{
return m_dialogHelper;
}
LtsBaseLayoutWidget* LtsDialog::baseLayoutWidget()
{
return m_baseLayoutWidget;
}
void LtsDialog::setOnlineHelpFilename(const QString &fileName)
{
m_onlineHelpFileName = fileName;
QPushButton *btn = m_buttonBox->getButton(DialogButton::Help);
if (btn == nullptr)
return;
if (LtsSessionData::LtsSessionData::getInstance()->isTablet() && strcmp(PROJECTBUILD, "guez") == 0)
return;
connect(btn, &QPushButton::clicked,
this, [this]()
{
emit signalShowOnlineHelp(m_onlineHelpFileName);
});
btn->setVisible(true);
}
void LtsDialog::addDebugMenuButton()
{
#ifdef LTS_DEBUG
QMenu *menu = new QMenu(this);
menu->addAction(QStringLiteral("simulate changes"), this, &LtsDialog::slotChangesMade);
menu->addAction(QStringLiteral("unchange"), this, &LtsDialog::__unchange__);
menu->addAction(QStringLiteral("retranslate"), this, &LtsDialog::retranslate);
menu->addAction(QStringLiteral("force unlock"), this, [this]() { setUnchangeable(false); });
menu->addAction(QStringLiteral("set unchangeable"), this, [this]() { setUnchangeable(); });
menu->addAction(QStringLiteral("try lock"), this, &LtsDialog::tryLockTopic);
menu->addAction(QStringLiteral("set closable"), this, [this]() { m_isClosable = true; });
menu->addAction(QStringLiteral("set unclosable"), this, [this]() { m_isClosable = false; });
menu->addAction(QStringLiteral("clear requirements"), this, [this] { m_uiRequirements->clear(); });
menu->addAction(QStringLiteral("enable all button box buttons"), this, [this]()
{
const auto children = m_buttonBox->findChildren<QPushButton *>();
for (QPushButton *pb : children)
pb->setEnabled(true);
});
menu->addAction(QStringLiteral("show button box button .."), this, [this]()
{
QString buttonObjectName = QInputDialog::getText(this, QString(), QStringLiteral("Enter button object name"));
if (buttonObjectName.isEmpty())
return;
const QList<QPushButton *> buttons = m_buttonBox->findChildren<QPushButton *>(buttonObjectName);
int btnCount = buttons.count();
if (btnCount == 0)
{
LtsMessageDialog::showMessage(this, QStringLiteral("button not found"));
return;
}
if (btnCount > 1)
{
QStringList buttonStringList;
buttonStringList.reserve(buttons.size());
for (QPushButton *pb : buttons)
buttonStringList += pb->objectName();
LtsMessageDialog::showMessage(this, QStringLiteral("button ambiguous: %1").arg(buttonStringList.join(QStringLiteral(", "))));
return;
}
buttons.at(0)->setVisible(true);
});
QPushButton *debugBtn = m_buttonBox->getButton(DialogButton::_debug_);
debugBtn->setMenu(menu);
debugBtn->setVisible(true);
#endif
}
void LtsDialog::updateWindowTitle()
{
QString completeTitle = m_title;
if (m_changesMade)
completeTitle.insert(0, QStringLiteral("\u2022"));
if (!m_topicLockedBy.isEmpty())
completeTitle.push_back(QString(QStringLiteral(" - READ-ONLY (%1)")).arg(m_topicLockedBy));
QWidget::setWindowTitle(completeTitle);
if (m_dialogHelper != nullptr)
m_dialogHelper->setWindowTitle(completeTitle);
}
void LtsDialog::setWindowTitle(const QString &title)
{
m_title = title;
updateWindowTitle();
}
void LtsDialog::setBaseLayoutWidget(LtsBaseLayoutWidget *baseLayoutWidget)
{
m_baseLayoutWidget = baseLayoutWidget;
}
void LtsDialog::setIdentifier(const QString &identifier)
{
m_identifier = identifier;
tableColumnOrganiserSetting();
}
void LtsDialog::addConnections(QWidget *widget)
{
if (addChangesMadeSignal<QLineEdit>(widget, &QLineEdit::textChanged)) return;
if (addChangesMadeSignal<QDateTimeEdit>(widget, &QDateTimeEdit::dateTimeChanged)) return;
if (addChangesMadeSignal<QComboBox>(widget, &QComboBox::currentTextChanged)) return;
if (addChangesMadeSignal<QCheckBox>(widget, &QCheckBox::stateChanged)) return;
if (addChangesMadeSignal<QSpinBox>(widget, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged))) return;
if (addChangesMadeSignal<QDoubleSpinBox>(widget, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged))) return;
if (addChangesMadeSignal<QSlider>(widget, &QSlider::valueChanged)) return;
if (addChangesMadeSignal<QPlainTextEdit>(widget, &QPlainTextEdit::textChanged)) return;
if (addChangesMadeSignal<QTextEdit>(widget, &QTextEdit::textChanged)) return;
if (addChangesMadeSignal<QAbstractButton>(widget, &QAbstractButton::toggled)) return;
if (addChangesMadeSignal<LtsDateTimeEdit>(widget, &LtsDateTimeEdit::dateTimeChanged)) return;
}
void LtsDialog::setUnchangeable(bool unchangeable)
{
m_unchangeableDialog = unchangeable;
}
bool LtsDialog::addDialogFixed(LtsDialog *dialog, const char *menuGroupUntranslated, const QString &identifier, const LayoutArea &layoutArea, bool setClosable, bool focusNewTab)
{
return addDialog(dialog, tr(menuGroupUntranslated) , identifier, layoutArea, setClosable, focusNewTab);
}
bool LtsDialog::addDialog(LtsDialog *dialog, const QString &menuGroup, const QString &identifier, const LayoutArea &layoutArea, bool setClosable, bool focusNewTab)
{
if (!m_baseLayoutWidget)
{
qCritical() << "LtsDialog: addDialog: no base layout set - cannot add Dialog !";
return false;
}
return m_baseLayoutWidget->addWidget(dialog, menuGroup, identifier, layoutArea, setClosable, focusNewTab);
}
bool LtsDialog::amIFocused() const
{
if (!m_baseLayoutWidget)
{
qCritical() << "LtsDialog: addDialog: no base layout set - cannot check for focus!";
return false;
}
return m_baseLayoutWidget->isDialogFocused(this);
}
bool LtsDialog::focusDialog(const QString &menuGroup, const QString &identifier, const LayoutArea &layoutArea)
{
if (!m_baseLayoutWidget)
{
qCritical() << "LtsDialog: addDialog: no base layout set - cannot focus Dialog !";
return false;
}
return m_baseLayoutWidget->focusTab(menuGroup, identifier, layoutArea);
}
void LtsDialog::showEvent(QShowEvent *event)
{
emit visibilityChanged(true);
bool tmp = m_unchangeableDialog;
if (!m_firstShow)
{
QWidget::showEvent(event);
return;
}
m_unchangeableDialog = true;
m_firstShow = false;
QList<QWidget *> listenWidgets = findChildren<QWidget *>();
for (auto i = listenWidgets.begin(); i != listenWidgets.end(); ++i)
{
QWidget *widget = *i;
QVariant isConst = widget->property("const");
if (isConst.isValid() && isConst.toBool())
continue;
if (!tmp)
addConnections(widget);
#ifdef TABLET_MODE
LtsWidgets::addTouchScroll(widget);
#endif
}
QWidget::showEvent(event);
m_unchangeableDialog = tmp;
}
void LtsDialog::tryLockTopic()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_topicInfo.isValid())
return;
if (m_topicInfo.isLocked())
{
WARNING_LOG(m_logger) << LOGFUNCTION << " tried to lock with an already locked topic info, return";
return;
}
if (m_noLockTopic)
return;
bool bIsConnected = isSignalConnected(QMetaMethod::fromSignal(&LtsDialog::signalLockTopic));
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " signalLockTopic(): "
<< ", TopicName =" << m_topicInfo.topicName()
<< ", entity =" << m_topicInfo.entityId()
<< ", signalLockTopic isConnected=" << bIsConnected;
if (bIsConnected)
{
emit signalLockTopic(m_topicInfo);
m_topicInfo.setLocked();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void LtsDialog::initTopicLockHandler(const QString &topicName, int entityId)
{
m_topicInfo.setTopicName(topicName);
m_topicInfo.setEntity(entityId);
m_topicInfo.setValid();
}
void LtsDialog::tryLockTopicNew()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
tryLockTopic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void LtsDialog::tryLockTopicNew(const QString &topicName, int entityId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", topicName='" << topicName << "'"
<< ", entityId=" << entityId;
if (m_topicInfo.entityId() != entityId)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " topicName='" << topicName << "'"
<< " change from " << m_topicInfo.entityId() << " to " << entityId;
m_topicInfo.setLocked(false);
}
m_topicInfo.setTopicName(topicName);
m_topicInfo.setEntity(entityId);
m_topicInfo.setValid();
tryLockTopic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", topicName='" << topicName << "'"
<< ", entityId=" << entityId;
}
void LtsDialog::triggerTopicLock()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " !!trigger!!";
tryLockTopic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void LtsDialog::translate(const QString &title)
{
bool isAlreadyUnchangeable = unchangeable();
if (!isAlreadyUnchangeable)
setUnchangeable(true);
setWindowTitle(title);
if (!isAlreadyUnchangeable)
setUnchangeable(false);
{
bool isNowAlreadyUnchangeable = unchangeable();
QPushButton *b = m_buttonBox->getButton(DialogButton::ReadOnly);
if (b)
{
connect(b, &QPushButton::clicked, this, &LtsDialog::onReadOnlyButtonClicked, Qt::UniqueConnection);
b->setVisible(isNowAlreadyUnchangeable && !m_topicLockedBy.isEmpty());
if (b->isVisible())
b->setToolTip(tr("Locked by: %1").arg(m_topicLockedBy));
else
b->setToolTip({});
}
}
}
void LtsDialog::slotLock(const QString &lockedBy)
{
setUnchangeable(true);
m_topicLockedBy = lockedBy;
lock();
retranslate();
}
void LtsDialog::slotUnlock()
{
setUnchangeable(false);
m_topicLockedBy.clear();
unlock();
retranslate();
}
void LtsDialog::lock()
{
setWidgetsReadonly<QLineEdit>(true);
setWidgetsReadonly<QDateTimeEdit>(true);
setWidgetsReadonly<QSpinBox>(true);
setWidgetsReadonly<QDoubleSpinBox>(true);
setWidgetsReadonly<QPlainTextEdit>(true);
setWidgetsReadonly<QTextEdit>(true);
setWidgetsDisabled<QComboBox>(true);
setWidgetsDisabled<QCheckBox>(true);
setWidgetsDisabled<QRadioButton>(true);
setWidgetsDisabled<QSlider>(true);
setWidgetsDisabled<QTableView>(true);
setWidgetsDisabled<QTableWidget>(true);
setWidgetsDisabled<QListView>(true);
setWidgetsDisabled<QListWidget>(true);
setWidgetsDisabled<QPushButton>(true);
}
void LtsDialog::unlock()
{
restoreReadonly<QLineEdit>();
restoreReadonly<QDateTimeEdit>();
restoreReadonly<QSpinBox>();
restoreReadonly<QDoubleSpinBox>();
restoreReadonly<QPlainTextEdit>();
restoreReadonly<QTextEdit>();
restoreEnabled<QComboBox>();
restoreEnabled<QCheckBox>();
restoreEnabled<QRadioButton>();
restoreEnabled<QSlider>();
restoreEnabled<QTableView>();
restoreEnabled<QTableWidget>();
restoreEnabled<QListView>();
restoreEnabled<QListWidget>();
}
void LtsDialog::slotChangesMade()
{
if (m_unchangeableDialog)
return;
m_changesMade = true;
updateWindowTitle();
m_buttonBox->getButton(DialogButton::Ok)->setEnabled(true);
m_buttonBox->getButton(DialogButton::Apply)->setEnabled(true);
emit signalChangesMade();
}
void LtsDialog::resetChanges()
{
m_changesMade = false;
updateWindowTitle();
m_buttonBox->getButton(DialogButton::Ok)->setEnabled(false);
m_buttonBox->getButton(DialogButton::Apply)->setEnabled(false);
emit signalChangesReset();
}
bool LtsDialog::_apply()
{
if (m_uiRequirements->checkRequirements(this) && apply())
{
resetChanges();
return true;
}
return false;
}
Button LtsDialog::askApplyDiscardCancel()
{
return LtsMessageDialog::askApplyDiscardCancel(this);
}
void LtsDialog::slotApply()
{
_apply();
}
void LtsDialog::slotOkay()
{
if (_apply())
_close();
}
void LtsDialog::slotHide()
{
_hide();
}
void LtsDialog::slotClose()
{
if ((m_changesMade) && (!m_unchangeableDialog))
{
switch (askApplyDiscardCancel())
{
case Button::Apply:
slotOkay();
break;
case Button::Discard:
_discard();
break;
default:
break;
}
}
else
{
_close();
}
}
void LtsDialog::onReadOnlyButtonClicked()
{
if (m_topicLockedBy.isEmpty())
return;
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Locked by: %1").arg(m_topicLockedBy));
}
void LtsDialog::closeRequest()
{
slotClose();
}
void LtsDialog::_hide()
{
if (m_dialogHelper != nullptr)
{
emit signalHide(m_dialogHelper);
}
}
void LtsDialog::_close()
{
resetChanges();
aboutToClose();
if (m_dialogHelper != nullptr)
m_dialogHelper->close();
}
void LtsDialog::_discard()
{
dialogCanceled();
_close();
}
}
#include "lts_dialog.moc"