474 lines
9.9 KiB
C++
Executable File
474 lines
9.9 KiB
C++
Executable File
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "lts_base.h"
|
|
#include "lts_widgets_export.h"
|
|
#include "ui_requirement.h"
|
|
#include "lts_dialog_button_box.h"
|
|
|
|
#include <NGLLogger/NGLLoggerBootstrap.h>
|
|
|
|
#include <QPushButton>
|
|
#include <QLineEdit>
|
|
#include <QComboBox>
|
|
#include <QCheckBox>
|
|
#include <QSpinBox>
|
|
#include <QDateTimeEdit>
|
|
#include <QSlider>
|
|
#include <QPlainTextEdit>
|
|
#include <QTextEdit>
|
|
#include <QWidget>
|
|
#include <QRadioButton>
|
|
#include <QPointer>
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
NGL::INGLLogger &m_logger;
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
}
|