#pragma once #include "lts_base.h" #include "lts_widgets_export.h" #include "ui_requirement.h" #include "lts_dialog_button_box.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace LtsWidgets { class TopicInfo { public: int entityId() const { return m_entityId; } const QString &topicName() const { return m_topicName; } bool isLocked() const { return m_locked; } bool isValid() const { return m_valid; } void setEntity(int entityId) { m_entityId = entityId; } void setTopicName(const QString &topicName) { m_topicName = topicName; } void setLocked(bool locked = true) { m_locked = locked; } void setValid() { m_valid = true; } private: QString m_topicName; int m_entityId{0}; bool m_locked{false}; bool m_valid{false}; }; class LtsBaseLayoutWidget; class LtsDialogHelper; class LtsProgressDialogHelper; class LtsDialogButtonBox; class LtsToolBarArea; class OverlayContainer; enum class ButtonCombination { OkApplyCancel, OkCancel, CloseOnly, SeamlessDialog, }; class LTSWIDGETS_EXPORT LtsDialog : public QWidget { Q_OBJECT Q_PROPERTY(bool unchangeable READ unchangeable WRITE setUnchangeable) public: static int s_object_count; explicit LtsDialog(QWidget *parent = nullptr, ButtonCombination buttonCombination = ButtonCombination::CloseOnly, bool closeable = true); ~LtsDialog(); LtsDialogHelper *getHelper(); bool hasUnsavedChanges() const { return m_changesMade || m_currentlyBlocking; } virtual void retranslate() = 0; void closeRequest(); void setUnchangeable(bool unchangeable = true); bool unchangeable() const { return m_unchangeableDialog; } bool addDialog(LtsDialog *dialog, const QString &menuGroup, const QString &identifier, const LayoutArea &layoutArea = LayoutArea::eDialogTab, bool setClosable = true, bool focusNewTab = true); Q_DECL_DEPRECATED bool addDialogFixed(LtsDialog *dialog, const char *menuGroupUntranslated, const QString &identifier, const LayoutArea &layoutArea = LayoutArea::eDialogTab, bool setClosable = true, bool focusNewTab = true); bool focusDialog(const QString &menuGroup, const QString &identifier, const LayoutArea &layoutArea); bool amIFocused() const; void setBaseLayoutWidget(LtsBaseLayoutWidget *baseLayoutWidget); void __unchange__() { resetChanges(); } void setClosable(bool closable) { m_isClosable = closable; } bool isClosable() const { return m_isClosable; } virtual void aboutToClose() {} void setMenuGroup(const QString &menuGroup) { m_menuGroup = menuGroup; } const QString &menuGroup() const { return m_menuGroup; } void setIdentifier(const QString &identifier); virtual void tableColumnOrganiserSetting(){}; const QString &identifier() const { return m_identifier; } void setOverlay(QWidget *widget); void unsetOverlay(); static inline void setMinWidthForWidgetHelper(QWidget *w) { int width = w->sizeHint().width(); w->setMinimumWidth(width); } QString windowTitle() const { return m_title; } void tryLockTopicNew(); virtual void tryLockTopicNew (const QString &topicName, int entityId = -1); void triggerTopicLock(); void setOnlineHelpFilename(const QString &fileName); void setCurrentlyBlocking(bool currentlyBlocking = true) { m_currentlyBlocking = currentlyBlocking; } signals: void startMainSelect(LtsWidgets::LayoutArea); void endMainSelect(LtsWidgets::LayoutArea); void signalChangesMade(); void signalHide(QObject *object); void signalChangesReset(); void signalFocused(); void visibilityChanged(bool visible); void signalLockTopic(const LtsWidgets::TopicInfo &topicInfo); void signalShowOnlineHelp(const QString &fileName); protected: void translate(const QString &title); template void translate(T *ui, const QString &title) { translate(title); if (ui) ui->retranslateUi(this); m_uiRequirements->retranslate(); } void hideEvent(QHideEvent *event) override { QWidget::hideEvent(event); emit visibilityChanged(false); } template void translate(T *ui, const QString &custom, bool isNew, const QString &title) { QString newTitle; if (!isNew) { if (unchangeable()) { if (custom.isEmpty()) newTitle = (tr("Show %1").arg(title)); else newTitle = (tr("Show %1: %2").arg(title, custom)); } else { if (custom.isEmpty()) newTitle = (tr("Edit %1").arg(title)); else newTitle = (tr("Edit %1: %2").arg(title, custom)); tryLockTopicNew(); } } else { newTitle = (tr("New %1").arg(title)); m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->hide(); m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setText(tr("Create")); } translate(ui, newTitle); } template void translate(T* ui, const QString &customUniqueTopicName, int topicId, const QString &custom, const QString &title) { Q_UNUSED(customUniqueTopicName); initTopicLockHandler(customUniqueTopicName, topicId); translate(ui, custom , (topicId < 1 ), title); } template void translate(T *ui, const S &data, const QString &custom, const QString &title) { translate(ui, QString::fromUtf8(typeid(data).name()), data.id(), custom , title); } template void translate(T *ui, const S &data, const QString &title) { translate(ui, data, QString::fromStdString(data.name()), title); } virtual void dialogCanceled() {} LtsBaseLayoutWidget* baseLayoutWidget(); void setNoTopicLock() { m_noLockTopic = true; } private: friend class LtsDialogHelper; bool m_changesMade; bool m_currentlyBlocking { false }; bool m_firstShow; QPointer m_baseLayoutWidget; bool m_isClosable; TopicInfo m_topicInfo; public: QString m_topicLockedBy; private: bool m_noLockTopic; bool m_unchangeableDialog; QPointer m_dialogHelper; QString m_title; QString m_onlineHelpFileName; QString m_menuGroup; QString m_identifier; QPointer m_overlayContainer; QPointer m_overlayWidget; bool _apply(); void _close(); void _discard(); void _hide(); void resetChanges(); void addDebugMenuButton(); void tryLockTopic(); void initTopicLockHandler(const QString &topicName, int entityId); void setWindowTitle(const QString &title); void updateWindowTitle(); void addConnections(QWidget *widget); template bool addChangesMadeSignal(QWidget *widget, SignalFunc signal) { WidgetType *concreteWidget = qobject_cast(widget); if (!concreteWidget) return false; connect(concreteWidget, signal, this, &LtsDialog::slotChangesMade); return true; } template void setWidgetsReadonly(bool readonly) { const auto children = findChildren(); for (WidgetType *widget : children ) { widget->setProperty("lastReadOnlyState", widget->isReadOnly()); widget->setReadOnly(readonly); } } template void setWidgetsDisabled(bool disabled) { const auto children = findChildren(); for (WidgetType *widget : children) { widget->setProperty("lastEnabledState", widget->isEnabled()); widget->setEnabled(!disabled); } } template void restoreReadonly() { const auto children = findChildren(); for (WidgetType *widget : children) { QVariant lastState = widget->property("lastReadOnlyState"); if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool)) widget->setReadOnly(lastState.toBool()); } } template void restoreEnabled() { const auto children = findChildren(); for (WidgetType *widget : children) { QVariant lastState = widget->property("lastEnabledState"); if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool)) widget->setEnabled(lastState.toBool()); } } public slots: void slotChangesMade(); void slotHide(); void slotLock(const QString &lockedBy); void slotUnlock(); private slots: void slotApply(); void slotOkay(); void slotClose(); void onReadOnlyButtonClicked(); protected: virtual void lock(); virtual void unlock(); virtual bool apply() { return true; } void showEvent(QShowEvent *event) override; Button askApplyDiscardCancel(); LtsDialogButtonBox *m_buttonBox; UiRequirementList *m_uiRequirements; NGL::INGLLogger &m_logger; }; template T *initDialog(T *dialog) { if (!dialog->init()) { dialog->deleteLater(); return nullptr; } return dialog; } template T *initDialog(T *dialog, F&&... f) { if (!dialog->init(std::forward(f)...)) { dialog->deleteLater(); return nullptr; } return dialog; } template T *createThrowableDialog(F&&... f) { T *dlg = nullptr; try { dlg = new T(std::forward(f)...); } catch (const char *s) { fprintf(stderr, "Dialog could not be created: %s\n", s); return nullptr; } catch (const QString &msg) { fprintf(stderr, "Dialog could not be created: %s\n", msg.toStdString().c_str()); return nullptr; } catch (...) { fprintf(stderr, "Dialog could not be created: unknown error\n"); return nullptr; } return dlg; } }