474 lines
11 KiB
C++
474 lines
11 KiB
C++
|
|
|
|
#pragma once
|
|
#include "lts_base.h"
|
|
#include "lts_dialog_button_box.h"
|
|
#include "lts_widgets_export.h"
|
|
#include "requirement_widget.h"
|
|
|
|
#include <NGLLogger/NGLLoggerBootstrap.h>
|
|
#include <QCheckBox>
|
|
#include <QComboBox>
|
|
#include <QDateTimeEdit>
|
|
#include <QDebug>
|
|
#include <QLineEdit>
|
|
#include <QObject>
|
|
#include <QPlainTextEdit>
|
|
#include <QPointer>
|
|
#include <QPushButton>
|
|
#include <QRadioButton>
|
|
#include <QSlider>
|
|
#include <QSpinBox>
|
|
#include <QTextEdit>
|
|
#include <QWidget>
|
|
|
|
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 <typename T>
|
|
|
|
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 <typename T>
|
|
|
|
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 <typename T>
|
|
|
|
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 <typename T, typename S>
|
|
|
|
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 <typename T, typename S>
|
|
|
|
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<LtsBaseLayoutWidget> m_baseLayoutWidget;
|
|
bool m_isClosable;
|
|
TopicInfo m_topicInfo;
|
|
|
|
public:
|
|
QString m_topicLockedBy;
|
|
|
|
private:
|
|
bool m_noLockTopic;
|
|
bool m_unchangeableDialog;
|
|
QPointer<LtsDialogHelper> m_dialogHelper;
|
|
NGL::INGLLogger& m_logger;
|
|
|
|
QString m_title;
|
|
QString m_onlineHelpFileName;
|
|
QString m_menuGroup;
|
|
QString m_identifier;
|
|
|
|
QPointer<OverlayContainer> m_overlayContainer;
|
|
QPointer<QWidget> 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 <typename WidgetType, typename SignalFunc> bool addChangesMadeSignal(QWidget* widget, SignalFunc signal)
|
|
{
|
|
WidgetType* concreteWidget = qobject_cast<WidgetType*>(widget);
|
|
|
|
if (!concreteWidget)
|
|
return false;
|
|
|
|
connect(concreteWidget, signal, this, &LtsDialog::slotChangesMade);
|
|
return true;
|
|
}
|
|
|
|
template <typename WidgetType> void setWidgetsReadonly(bool readonly)
|
|
{
|
|
const auto children = findChildren<WidgetType*>();
|
|
for (WidgetType* widget : children)
|
|
{
|
|
widget->setProperty("lastReadOnlyState", widget->isReadOnly());
|
|
widget->setReadOnly(readonly);
|
|
}
|
|
}
|
|
|
|
template <typename WidgetType> void setWidgetsDisabled(bool disabled)
|
|
{
|
|
const auto children = findChildren<WidgetType*>();
|
|
for (WidgetType* widget : children)
|
|
{
|
|
widget->setProperty("lastEnabledState", widget->isEnabled());
|
|
widget->setEnabled(!disabled);
|
|
}
|
|
}
|
|
|
|
template <typename WidgetType> void restoreReadonly()
|
|
{
|
|
const auto children = findChildren<WidgetType*>();
|
|
for (WidgetType* widget : children)
|
|
{
|
|
QVariant lastState = widget->property("lastReadOnlyState");
|
|
if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool))
|
|
widget->setReadOnly(lastState.toBool());
|
|
}
|
|
}
|
|
|
|
template <typename WidgetType> void restoreEnabled()
|
|
{
|
|
const auto children = findChildren<WidgetType*>();
|
|
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;
|
|
};
|
|
|
|
template <typename T> T* initDialog(T* dialog)
|
|
{
|
|
if (!dialog->init())
|
|
{
|
|
dialog->deleteLater();
|
|
return nullptr;
|
|
}
|
|
return dialog;
|
|
}
|
|
|
|
template <typename T, typename... F> T* initDialog(T* dialog, F&&... f)
|
|
{
|
|
if (!dialog->init(std::forward<F>(f)...))
|
|
{
|
|
dialog->deleteLater();
|
|
return nullptr;
|
|
}
|
|
return dialog;
|
|
}
|
|
|
|
template <typename T, typename... F> T* createThrowableDialog(F&&... f)
|
|
{
|
|
T* dlg = nullptr;
|
|
|
|
try
|
|
{
|
|
dlg = new T(std::forward<F>(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;
|
|
}
|
|
|
|
} // namespace LtsWidgets
|