Continues migration with DDS, Common

This commit is contained in:
torsten committed 2026-07-17 12:41:42 +02:00
1 parent 9b15cee841
commit fa48db111e
668 files changed
+111841 -2

No files matched your search

+210
View File
@@ -0,0 +1,210 @@
#
# $Id$
# $HeadURL$
# $Author$
#
#
# Lts Widgets library
#
SET(ltswidgets_SRCS
#lts_abstract_table_model.h
#lts_checkable_table_model.h
lts_abstract_sequence_widget.cpp
lts_abstract_sequence_widget.h
lts_background_widget.cpp
lts_background_widget.h
lts_base.h
lts_base_layout_widget.cpp
lts_base_layout_widget.h
lts_column_filter_proxy_model.cpp
lts_column_filter_proxy_model.h
lts_combo_box.cpp
lts_combo_box.h
lts_selection_popup.cpp
lts_selection_popup.h
lts_drag_icon.cpp
lts_drag_icon.h
#lts_drop_handler.h
lts_elided_label.cpp
lts_elided_label.h
lts_events.cpp
lts_events.h
lts_frameless_dialog.cpp
lts_frameless_dialog.h
lts_grid_layout.cpp
lts_grid_layout.h
lts_height_plot_widget.cpp
lts_height_plot_widget.h
lts_message_dialog.cpp
lts_message_dialog.h
lts_message_dialog_helper.cpp
lts_message_dialog_helper.h
lts_profile_button.cpp
lts_profile_button.h
lts_progress_dialog_helper.cpp
lts_progress_dialog_helper.h
lts_splitter.cpp
lts_splitter.h
lts_splitter_handle.cpp
lts_splitter_handle.h
lts_tab_bar.cpp
lts_tab_bar.h
lts_tab_widget.cpp
lts_tab_widget.h
lts_tab_sequence_widget.cpp
lts_tab_sequence_widget.h
lts_tool_bar.cpp
lts_tool_bar.h
lts_tool_box.cpp
lts_tool_box.h
lts_tool_bar_area.cpp
lts_tool_bar_area.h
lts_dialog.cpp
lts_dialog.h
lts_dialog_helper.cpp
lts_dialog_helper.h
lts_dialog_button_box.cpp
lts_dialog_button_box.h
lts_operator_menu.cpp
lts_operator_menu.h
lts_image_editor.cpp
lts_image_editor.h
lts_led_widget.cpp
lts_led_widget.h
ui_requirement.cpp
ui_requirement.h
#lts_widgets_export.h
lts_picture_view.cpp
lts_picture_view.h
lts_global_wait_dialog.cpp
lts_global_wait_dialog.h
lts_wait_dialog.cpp
lts_wait_dialog.h
lts_splash.cpp
lts_splash.h
lts_info_dialog.cpp
lts_info_dialog.h
lts_spinbox.cpp
lts_spinbox.h
lts_multi_range_spinbox.cpp
lts_multi_range_spinbox.h
lts_text_editor.cpp
lts_text_editor.h
lts_text_edit_dialog.h
lts_text_edit_dialog.cpp
lts_range_slider.cpp
lts_range_slider.h
lts_notification_box.cpp
lts_notification_box.h
lts_msec_date_time_edit.cpp
lts_msec_date_time_edit.h
lts_bitfield_widget.cpp
lts_bitfield_widget.h
lts_overlay_loading.cpp
lts_angle_edit.cpp
lts_angle_edit.h
lts_text_editor2.h
lts_text_editor2.cpp
LtsImageCropper/lts_image_cropper.cpp
)
#if (TABLET_MODE)
# LIST(APPEND ltswidgets_SRCS
# lts_date_time_edit_touch.h
# lts_date_time_edit_touch.cpp
# )
# NGL_WRAP_UI(ltswidgets_SRCS
# lts_date_time_edit_touch.ui
# )
#else()
LIST(APPEND ltswidgets_SRCS
lts_date_time_edit.h
lts_date_time_edit.cpp
lts_date_time_edit_p.h
lts_date_time_edit_p.cpp
)
#endif()
NGL_WRAP_UI(ltswidgets_SRCS
lts_selection_popup.ui
lts_base_layout.ui
lts_tool_bar_area.ui
lts_overlay_loading.ui
lts_dialog_button_box.ui
lts_operator_menu.ui
lts_dialog_helper.ui
lts_info_dialog.ui
lts_text_editor.ui
lts_notification_box.ui
lts_angle_edit.ui
lts_date_time_edit_touch.ui
)
NGL_ADD_BIG_RESOURCES(ltswidgets_SRCS resources/lts_resources.qrc)
NGL_ADD_LIBRARY(WS TOOLSWS TOOLSSV LtsWidgets SHARED ${ltswidgets_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsWidgets
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsWidgets
PRIVATE
Qt5::Network # for QHostInfo - for portability
Qt5::Svg
ngltools
ngltranslator
TabBarTabStyle
LtsSessionData
LtsUtilsSettings
PUBLIC
LtsUtilsCore
Qt5::Core
Qt5::Widgets
Qt5::Gui
)
NGL_INSTALL_TARGET(LtsWidgets)
#
# Designer-Plugin
#
SET(ltswidgetsplugin_SRCS ltswidgetsplugin.cpp ltswidgetsplugin.json)
NGL_ADD_LIBRARY(WS ltswidgetsplugin MODULE ${ltswidgetsplugin_SRCS})
NGL_TARGET_LINK_LIBRARIES(ltswidgetsplugin LtsWidgets ltsCoordWidget LtsDataView LtsFileDialog LtsReportDisplay svcFlmCommon)
NGL_SET_TARGET_PROPERTIES(ltswidgetsplugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/designer)
NGL_INSTALL_TARGET(ltswidgetsplugin DESTINATION lib/designer COMPONENT Devel)
IF(BUILD_TESTING)
# picture_editing_test
SET(pet_SRCS
tests/lts_picture_editing.cpp
tests/lts_picture_editing.h
tests/lts_picture_editing_main.cpp
)
NGL_WRAP_UI(pet_SRCS
tests/lts_picture_editing.ui
)
NGL_ADD_EXECUTABLE(WS NO_TRANSLATION picture_editing_test ${pet_SRCS})
NGL_TARGET_LINK_LIBRARIES(picture_editing_test
LtsWidgets
)
# # LtsWidgetsTest
# SET(src_test
# tests/main.cpp
# tests/window.h
# tests/window.cpp
# )
# NGL_ADD_EXECUTABLE(WS NO_TRANSLATION LtsWidgetsTest ${src_test})
# NGL_TARGET_LINK_LIBRARIES(LtsWidgetsTest
# LtsWidgets
# )
ENDIF()
+208
View File
@@ -0,0 +1,208 @@
#
# $Id$
# $HeadURL$
# $Author$
#
#
# Lts Widgets library
#
SET(ltswidgets_SRCS
#lts_abstract_table_model.h
#lts_checkable_table_model.h
lts_abstract_sequence_widget.cpp
lts_abstract_sequence_widget.h
lts_background_widget.cpp
lts_background_widget.h
lts_base.h
lts_base_layout_widget.cpp
lts_base_layout_widget.h
lts_column_filter_proxy_model.cpp
lts_column_filter_proxy_model.h
lts_combo_box.cpp
lts_combo_box.h
lts_selection_popup.cpp
lts_selection_popup.h
lts_drag_icon.cpp
lts_drag_icon.h
#lts_drop_handler.h
lts_elided_label.cpp
lts_elided_label.h
lts_events.cpp
lts_events.h
lts_frameless_dialog.cpp
lts_frameless_dialog.h
lts_grid_layout.cpp
lts_grid_layout.h
lts_height_plot_widget.cpp
lts_height_plot_widget.h
lts_message_dialog.cpp
lts_message_dialog.h
lts_message_dialog_helper.cpp
lts_message_dialog_helper.h
lts_profile_button.cpp
lts_profile_button.h
lts_progress_dialog_helper.cpp
lts_progress_dialog_helper.h
lts_splitter.cpp
lts_splitter.h
lts_splitter_handle.cpp
lts_splitter_handle.h
lts_tab_bar.cpp
lts_tab_bar.h
lts_tab_widget.cpp
lts_tab_widget.h
lts_tab_sequence_widget.cpp
lts_tab_sequence_widget.h
lts_tool_bar.cpp
lts_tool_bar.h
lts_tool_box.cpp
lts_tool_box.h
lts_tool_bar_area.cpp
lts_tool_bar_area.h
lts_dialog.cpp
lts_dialog.h
lts_dialog_helper.cpp
lts_dialog_helper.h
lts_dialog_button_box.cpp
lts_dialog_button_box.h
lts_operator_menu.cpp
lts_operator_menu.h
lts_image_editor.cpp
lts_image_editor.h
lts_led_widget.cpp
lts_led_widget.h
ui_requirement.cpp
ui_requirement.h
#lts_widgets_export.h
lts_picture_view.cpp
lts_picture_view.h
lts_global_wait_dialog.cpp
lts_global_wait_dialog.h
lts_wait_dialog.cpp
lts_wait_dialog.h
lts_splash.cpp
lts_splash.h
lts_info_dialog.cpp
lts_info_dialog.h
lts_spinbox.cpp
lts_spinbox.h
lts_multi_range_spinbox.cpp
lts_multi_range_spinbox.h
lts_text_editor.cpp
lts_text_editor.h
lts_text_edit_dialog.h
lts_text_edit_dialog.cpp
lts_range_slider.cpp
lts_range_slider.h
lts_notification_box.cpp
lts_notification_box.h
lts_msec_date_time_edit.cpp
lts_msec_date_time_edit.h
lts_bitfield_widget.cpp
lts_bitfield_widget.h
lts_overlay_loading.cpp
lts_angle_edit.cpp
lts_angle_edit.h
LtsImageCropper/lts_image_cropper.cpp
)
#if (TABLET_MODE)
# LIST(APPEND ltswidgets_SRCS
# lts_date_time_edit_touch.h
# lts_date_time_edit_touch.cpp
# )
# NGL_WRAP_UI(ltswidgets_SRCS
# lts_date_time_edit_touch.ui
# )
#else()
LIST(APPEND ltswidgets_SRCS
lts_date_time_edit.h
lts_date_time_edit.cpp
lts_date_time_edit_p.h
lts_date_time_edit_p.cpp
)
#endif()
NGL_WRAP_UI(ltswidgets_SRCS
lts_selection_popup.ui
lts_base_layout.ui
lts_tool_bar_area.ui
lts_overlay_loading.ui
lts_dialog_button_box.ui
lts_operator_menu.ui
lts_dialog_helper.ui
lts_info_dialog.ui
lts_text_editor.ui
lts_notification_box.ui
lts_angle_edit.ui
lts_date_time_edit_touch.ui
)
NGL_ADD_BIG_RESOURCES(ltswidgets_SRCS resources/lts_resources.qrc)
NGL_ADD_LIBRARY(WS TOOLSWS TOOLSSV LtsWidgets SHARED ${ltswidgets_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsWidgets
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsWidgets
PRIVATE
Qt5::Network # for QHostInfo - for portability
Qt5::Svg
ngltools
ngltranslator
TabBarTabStyle
LtsSessionData
LtsUtilsSettings
PUBLIC
LtsUtilsCore
Qt5::Core
Qt5::Widgets
Qt5::Gui
)
NGL_INSTALL_TARGET(LtsWidgets)
#
# Designer-Plugin
#
SET(ltswidgetsplugin_SRCS ltswidgetsplugin.cpp ltswidgetsplugin.json)
NGL_ADD_LIBRARY(WS ltswidgetsplugin MODULE ${ltswidgetsplugin_SRCS})
NGL_TARGET_LINK_LIBRARIES(ltswidgetsplugin LtsWidgets ltsCoordWidget LtsDataView LtsFileDialog LtsReportDisplay svcFlmCommon)
NGL_SET_TARGET_PROPERTIES(ltswidgetsplugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/designer)
NGL_INSTALL_TARGET(ltswidgetsplugin DESTINATION lib/designer COMPONENT Devel)
IF(BUILD_TESTING)
# picture_editing_test
SET(pet_SRCS
tests/lts_picture_editing.cpp
tests/lts_picture_editing.h
tests/lts_picture_editing_main.cpp
)
NGL_WRAP_UI(pet_SRCS
tests/lts_picture_editing.ui
)
NGL_ADD_EXECUTABLE(WS NO_TRANSLATION picture_editing_test ${pet_SRCS})
NGL_TARGET_LINK_LIBRARIES(picture_editing_test
LtsWidgets
)
# # LtsWidgetsTest
# SET(src_test
# tests/main.cpp
# tests/window.h
# tests/window.cpp
# )
# NGL_ADD_EXECUTABLE(WS NO_TRANSLATION LtsWidgetsTest ${src_test})
# NGL_TARGET_LINK_LIBRARIES(LtsWidgetsTest
# LtsWidgets
# )
ENDIF()
+131
View File
@@ -0,0 +1,131 @@
#include "lts_image_cropper.h"
#include <QGraphicsItem>
#include <QMouseEvent>
#include <QApplication>
namespace LtsWidgets
{
LtsImageCropper::LtsImageCropper(QWidget *parent, const QSize &size, const QPixmap &pixmap)
: QGraphicsView(parent)
, m_scene(new QGraphicsScene(this))
, m_maxScale(2.0f)
, m_multiplier(1.0f)
{
if(!size.isNull())
setFixedSize(size);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFrameStyle(QFrame::NoFrame);
setDragMode(QGraphicsView::ScrollHandDrag);
setTransformationAnchor(QGraphicsView::AnchorViewCenter);
m_scene->setBackgroundBrush(Qt::Dense6Pattern);
setScene(m_scene);
setPixmap(pixmap);
}
LtsImageCropper::~LtsImageCropper()
{
delete m_pixmapItem;
}
void LtsImageCropper::setPixmap(const QPixmap &pixmap)
{
if(pixmap.isNull())
return;
delete m_pixmapItem;
m_pixmapItem = new QGraphicsPixmapItem(pixmap);
m_scene->addItem(m_pixmapItem);
setTransform(QTransform());
m_currentZoom = 1.0;
double sx = static_cast<double>(size().height()) / pixmap.height();
double sy = static_cast<double>(size().width()) / pixmap.width();
if(sx > 1 )
scale(sx,sx);
if(sy > 1)
scale(sy,sy);
double ratioWidth = 1.0 * size().width() / pixmap.width();
double ratioHeight = 1.0 * size().height() / pixmap.height();
m_minScale = qMax(ratioHeight,ratioWidth);
calculateScaleStep();
m_scene->setSceneRect(pixmap.rect());
centerOn(m_scene->sceneRect().center());
}
void LtsImageCropper::setImage(const QImage &image)
{
setPixmap(QPixmap::fromImage(image));
}
void LtsImageCropper::setMultiplier(double multiplier)
{
m_multiplier = multiplier;
calculateScaleStep();
}
void LtsImageCropper::calculateScaleStep()
{
m_stepScale = (m_maxScale - m_minScale) / 100.0;
}
QImage LtsImageCropper::image()
{
return grab().toImage();
}
void LtsImageCropper::wheelEvent(QWheelEvent *event)
{
if(!m_pixmapItem)
return;
auto value = event->pixelDelta();
if(value.isNull())
value = event->angleDelta() / 15.0;
double scrollZoom = m_stepScale * value.y() * m_multiplier / 8.0;
m_currentZoom += scrollZoom;
if(m_currentZoom > m_maxScale)
m_currentZoom = m_maxScale;
else if (m_currentZoom < m_minScale)
m_currentZoom = m_minScale;
setTransform(QTransform(m_currentZoom, transform().m12(), transform().m13(),
transform().m21(), m_currentZoom, transform().m23(),
transform().m31(), transform().m32(), 1));
}
void LtsImageCropper::mousePressEvent(QMouseEvent *event)
{
QApplication::setOverrideCursor(Qt::DragMoveCursor);
update();
QGraphicsView::mousePressEvent(event);
}
void LtsImageCropper::mouseReleaseEvent(QMouseEvent *event)
{
QApplication::restoreOverrideCursor();
update();
QGraphicsView::mouseReleaseEvent(event);
}
}
+80
View File
@@ -0,0 +1,80 @@
#pragma once
#include "lts_widgets_export.h"
#include <QGraphicsView>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsImageCropper : public QGraphicsView
{
Q_OBJECT
Q_PROPERTY(QPixmap pixMap READ pixmap WRITE setPixmap)
Q_PROPERTY(double multiplier READ multiplier WRITE setMultiplier)
Q_PROPERTY(double maxZoom READ maxZoom WRITE setMaxZoom)
public:
LtsImageCropper(QWidget *parent = nullptr, const QSize &size = {} , const QPixmap &pixmap = {});
~LtsImageCropper();
void setPixmap(const QPixmap &pixmap);
void setImage(const QImage &image);
void setMultiplier(double multiplier);
void setMaxZoom(double maxZoom) { m_maxScale = maxZoom; }
QPixmap pixmap() { return grab(); }
QImage image();
double multiplier() const { return m_multiplier; }
double maxZoom() const { return m_maxScale; }
private:
QGraphicsScene *m_scene = nullptr;
QGraphicsPixmapItem *m_pixmapItem = nullptr;
double m_currentZoom;
double m_minScale;
double m_maxScale;
double m_stepScale;
double m_multiplier;
void calculateScaleStep();
protected:
void wheelEvent(QWheelEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
};
}
+120
View File
@@ -0,0 +1,120 @@
#include "lts_abstract_sequence_widget.h"
#include <QToolButton>
namespace LtsWidgets
{
LtsAbstractSequenceWidget::LtsAbstractSequenceWidget(QWidget *parent, const bool &readOnly)
: QGroupBox(parent)
, m_readOnly(readOnly)
, m_pbAddMember(new QToolButton)
{
m_pbAddMember->setIcon(QIcon(QLatin1String(":/icons/png/add.png")));
connect(m_pbAddMember, &QToolButton::clicked, this, &LtsAbstractSequenceWidget::addMember);
}
LtsAbstractSequenceWidget::~LtsAbstractSequenceWidget()
{
}
void LtsAbstractSequenceWidget::addWidget(QWidget* widget, bool isReadOnly, bool isButtonVisible)
{
addMemberWidget(widget, isReadOnly, isButtonVisible);
m_pbAddMember->setDisabled(isReadOnly);
m_pbAddMember->setVisible(isButtonVisible);
}
int LtsAbstractSequenceWidget::getMemberlistSize(){
return m_memberList.size();
}
void LtsAbstractSequenceWidget::getValue(QWidget *data,
const QString &findObjectName) const
{
if(!findChild<QWidget *>(findObjectName))
return;
data = findChild<QWidget *>(findObjectName);
}
void LtsAbstractSequenceWidget::setMemberCount(int count)
{
QWidget *child = nullptr;
do
{
child = findChild<QWidget *>(getObjectName(++count));
delete child;
}
while (child);
m_memberList.removeAll(nullptr);
}
uint32_t LtsAbstractSequenceWidget::getMemberCount() const
{
int count = 0;
QWidget *child = findChild<QWidget *>(getObjectName(count+1));
while(child)
{
count++;
child = findChild<QWidget *>(getObjectName(count+1));
}
return count;
}
QToolButton *LtsAbstractSequenceWidget::pbAddMember() const
{
return m_pbAddMember;
}
QString LtsAbstractSequenceWidget::getObjectName(int index) const
{
return QString::number(index);
}
void LtsAbstractSequenceWidget::addMemberWidget(QWidget *member, bool isReadOnly, bool isButtonVisible)
{
QToolButton *button = new QToolButton();
button->setIcon(QIcon(QLatin1String(":/icons/png/remove.png")));
button->setDisabled(isReadOnly);
connect(button, &QToolButton::clicked, member, &QWidget::deleteLater);
connect(member, &QWidget::destroyed, this, &LtsAbstractSequenceWidget::deleteMemberWidget);
connect(member, &QWidget::destroyed, button, &QToolButton::deleteLater);
m_memberList.push_back(member);
setupMemberWidget(member, button, member->objectName(), isButtonVisible);
}
void LtsAbstractSequenceWidget::deleteMemberWidget(QObject *member)
{
QWidget *w = qobject_cast<QWidget*>(member);
if(!w)
return;
for(auto child : w->children())
child->deleteLater();
m_memberList.removeAll(w);
for(int i=0; i<m_memberList.size(); i++)
{
m_memberList[i]->setObjectName(getObjectName(i + 1));
for(auto child : m_memberList[i]->children())
{
if(child->objectName().isEmpty())
continue;
QString childName = child->objectName();
QString newId = QString::number(i + 1);
child->setObjectName(childName.replace(QRegExp(QLatin1String(".([0-9]*)")), newId));
}
}
}
}
+89
View File
@@ -0,0 +1,89 @@
#ifndef LTS_ABSTRACT_SEQUENCE_WIDGET_H
#define LTS_ABSTRACT_SEQUENCE_WIDGET_H
#pragma once
#include <QGroupBox>
#include <QList>
#include "lts_widgets_export.h"
class QToolButton;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsAbstractSequenceWidget : public QGroupBox
{
Q_OBJECT
public:
explicit LtsAbstractSequenceWidget(QWidget *parent = nullptr, const bool &readOnly = false);
~LtsAbstractSequenceWidget();
virtual void addWidget(QWidget* widget, bool isReadOnly, bool isButtonVisible = true);
virtual void getValue(QWidget *contentType,
const QString &findObjectName) const;
virtual void setMemberCount(int count);
virtual uint32_t getMemberCount() const;
virtual int getMemberlistSize();
protected:
virtual QToolButton *pbAddMember() const;
virtual QString getObjectName(int index) const;
virtual void setupMemberWidget(QWidget *child, QToolButton *pbChild, const QString &objectName, bool isButtonVisible = true) = 0;
signals:
void addMember();
private slots:
virtual void addMemberWidget(QWidget *member, bool isReadOnly, bool isButtonVisible = true);
virtual void deleteMemberWidget(QObject *member);
private:
bool m_readOnly;
QToolButton *m_pbAddMember = nullptr;
QList<QWidget*> m_memberList;
};
}
#endif
+286
View File
@@ -0,0 +1,286 @@
#pragma once
#include "lts_base.h"
#include <LtsUtilsCore/data_modification_enum.h>
#include <QVector>
#include <QAbstractTableModel>
#include <memory>
#include <algorithm>
namespace LtsWidgets
{
template<class T>
class LtsAbstractTableModel : public QAbstractTableModel
{
public:
LtsAbstractTableModel(const QVector<QString> &header, QObject *parent)
: QAbstractTableModel(parent)
, m_vecColumns(header)
{}
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal && section>= 0 && section < m_vecColumns.size())
return m_vecColumns[section];
return QAbstractTableModel::headerData(section, orientation, role);
}
bool isEmpty(const QModelIndex &parent = QModelIndex())
{
return parent.isValid() ? true : m_vecData.isEmpty();
}
int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
return parent.isValid() ? 0 : m_vecData.size();
}
int columnCount(const QModelIndex &parent = QModelIndex()) const override
{
return parent.isValid() ? 0 : m_vecColumns.size();
}
void clear()
{
beginResetModel();
m_vecData.clear();
endResetModel();
}
bool indexIsValid(const QModelIndex &idx) const
{
if (!idx.isValid())
return false;
if (idx.row() < 0 || idx.row() >= m_vecData.size())
return false;
return true;
}
virtual bool removeRow(int row)
{
return removeRows(row, 1);
}
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
{
if (parent.isValid())
return false;
if (row < 0 || row >= m_vecData.size())
return false;
int range = std::min(row + count, m_vecData.size());
beginRemoveRows(QModelIndex(), row, range - 1);
m_vecData.erase(m_vecData.begin() + row, m_vecData.begin() + range);
endRemoveRows();
return true;
}
virtual bool insertRow(const T &item)
{
if (isFiltered(item, DataModification::eAdded) || isDeletedInternal(item))
return false;
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
m_vecData.append(item);
endInsertRows();
return true;
}
template <typename CONT>
void insertRows(const CONT &items)
{
if (items.isEmpty())
return;
const int cntBefore = m_vecData.size();
for (const auto &item : items)
{
if (isFiltered(item, DataModification::eAdded) || isDeletedInternal(item))
continue;
m_vecData += item;
}
const int cntAfter = m_vecData.size();
if (cntBefore == cntAfter)
return;
beginInsertRows(QModelIndex(), cntBefore, cntAfter - 1);
endInsertRows();
}
void setData(const QVector<T> &vecData)
{
clear();
insertRows(vecData);
}
void update()
{
if (!m_vecData.isEmpty())
emit dataChanged(index(0, 0), index(m_vecData.size() - 1, columnCount() - 1));
}
T getRowData(int row) const
{
if (row < 0 || row >= m_vecData.size())
return T();
return m_vecData.at(row);
}
bool setRowData(int row, const T &data)
{
if (row < 0 || row >= m_vecData.size())
return false;
m_vecData[row] = data;
emit dataChanged(index(row, 0), index(row, columnCount() - 1));
return true;
}
QModelIndex findIndexForId(int id, int column = 0) const
{
const int row = findRowForId(id);
if (row < 0)
return QModelIndex();
return index(row, column);
}
int getId(const QModelIndex &mi) const
{
if (!indexIsValid(mi))
return -1;
return getIdInternal(m_vecData.at(mi.row()));
}
protected:
template <class C>
class HasId
{
template <class CLS>
static std::true_type testSignature(const int &(CLS::*)() const);
template <class CLS>
static std::true_type testSignature(int (CLS::*)() const);
template <class CLS>
static decltype(testSignature(&CLS::id)) test(std::nullptr_t);
template <class CLS>
static std::false_type test(...);
public:
using type = decltype(test<C>(nullptr));
static const bool value = type::value;
};
template <typename F = T, typename std::enable_if<HasId<F>::value, int>::type = 0>
int getIdInternal(const F &data) const
{
return data.id();
}
virtual int getId(const T &data) const
{
Q_ASSERT(false);
Q_UNUSED(data);
return -1;
}
template < typename F = T, typename std::enable_if < !HasId<F>::value, int>::type = 0>
int getIdInternal(const F &data) const
{
return getId(data);
}
template <class C>
class HasIsDeleted
{
template <class CLS>
static std::true_type testSignature(const bool &(CLS::*)() const);
template <class CLS>
static std::true_type testSignature(bool (CLS::*)() const);
template <class CLS>
static decltype(testSignature(&CLS::isDeleted)) test(std::nullptr_t);
template <class CLS>
static std::false_type test(...);
public:
using type = decltype(test<C>(nullptr));
static const bool value = type::value;
};
template <typename F = T, typename std::enable_if<HasIsDeleted<F>::value, int>::type = 0>
bool isDeletedInternal(const F &data) const
{
return data.isDeleted();
}
virtual int isDeleted(const T &data) const
{
Q_UNUSED(data);
return false;
}
template < typename F = T, typename std::enable_if < !HasIsDeleted<F>::value, int>::type = 0>
bool isDeletedInternal(const F &data) const
{
return isDeleted(data);
}
virtual bool isFiltered(const T &data, DataModification modType) const
{
Q_UNUSED(data);
Q_UNUSED(modType);
return false;
}
virtual bool onDataChanged(const T &data, DataModification modType)
{
if (isFiltered(data, modType))
return false;
const int id = getIdInternal(data);
const int row = findRowForId(id);
if (modType == DataModification::eRemoved || isDeletedInternal(data))
{
if (row >= 0)
return removeRow(row);
return false;
}
if (modType == DataModification::eAdded && row < 0)
return insertRow(data);
return setRowData(row, data);
}
int findRowForId(int id) const
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (getIdInternal(m_vecData.at(i)) == id)
return i;
}
return -1;
}
QVector<T> m_vecData;
QVector<QString> m_vecColumns;
};
}
+246
View File
@@ -0,0 +1,246 @@
#include "lts_angle_edit.h"
#include "ui_lts_angle_edit.h"
#include <cmath>
namespace LtsWidgets
{
inline constexpr double pi() { return M_PI; }
inline constexpr double deg2rad() { return pi() / 180.; }
inline constexpr double rad2deg() { return 1. / deg2rad(); }
constexpr int maxAngleDeg = 360;
constexpr int maxAngleMil = 6400;
constexpr std::tuple<int,int,int,int> c_limDeg (0, maxAngleDeg,0, 10);
constexpr std::tuple<int,int,int, int> c_limMil(0, maxAngleMil,0, 50);
constexpr std::tuple<int,int,int, int> c_limRad(-99999, 99999, 3, 1);
inline constexpr double mil2Deg(const double &mil)
{
return maxAngleDeg * mil / maxAngleMil;
}
inline constexpr double deg2Mil(const double &angleDeg)
{
return maxAngleMil * angleDeg / maxAngleDeg;
}
inline constexpr double deg2Rad(const double &angleDeg)
{
return angleDeg * deg2rad();
}
inline constexpr double rad2Degree(const double &angleRad)
{
return angleRad * 180/pi();
}
inline constexpr double mil2Rad(const double &mil)
{
return deg2Rad(mil2Deg(mil));
}
inline constexpr double rad2Mil(const double &angleRad)
{
return deg2Mil(rad2Degree(angleRad));
}
LtsAngleEdit::LtsAngleEdit(QWidget *parent) :
QWidget(parent),
m_ui(new Ui_LtsAngleEdit)
{
m_ui->setupUi(this);
}
LtsAngleEdit::~LtsAngleEdit()
{
delete m_ui;
}
void LtsAngleEdit::initAngleEditWidget(const unsigned int sboxCount)
{
m_dboxLimitMap.insert(AngleUnitType::Deg, c_limDeg);
m_dboxLimitMap.insert(AngleUnitType::Mil, c_limMil);
m_dboxLimitMap.insert(AngleUnitType::Rad, c_limRad);
m_hiddenUnits.clear();
m_hiddenUnits.insert((int)AngleUnitType::Rad);
for(unsigned int i=0; i<sboxCount; ++i)
{
QSharedPointer<QDoubleSpinBox> spinbox = QSharedPointer<QDoubleSpinBox>(new QDoubleSpinBox(this) );
spinbox->setValue(0);
spinbox->setAlignment(Qt::AlignRight);
spinbox->setMinimumWidth(91);
spinbox.data()->setObjectName(spinBoxName+QString::number(m_sBoxMap.count()));
m_ui->hLayoutSpinbox->addWidget(spinbox.data(), 0);
m_sBoxMap.insert(m_sBoxMap.count(), spinbox);
}
m_ui->hLayoutSpinbox->setContentsMargins(1,1,1,1);
connect(m_ui->cBoxAngleUnit, qOverload<int>(&QComboBox::currentIndexChanged),
this, &LtsAngleEdit::onCBoxAngleUnitChanged);
setCboxUnit();
}
void LtsAngleEdit::setValue(const double value, unsigned int dboxIndex)
{
if ((int)dboxIndex > m_sBoxMap.count())
return;
auto spinbox = m_sBoxMap.value(dboxIndex);
spinbox->setValue(value);
}
void LtsAngleEdit::setValue(const double value, AngleUnitType valueUnit, unsigned int dboxIndex)
{
setValue(getAngleConverted(value, getAngleCurrentUnit(), valueUnit),dboxIndex);
}
void LtsAngleEdit::hideUnits(const QVector<AngleUnitType> &list)
{
for(auto u : list)
m_hiddenUnits.insert((int)u);
setCboxUnit();
}
void LtsAngleEdit::showUnits(const QVector<AngleUnitType> &list)
{
for (const auto &u : list)
m_hiddenUnits.remove((int)u);
setCboxUnit();
}
void LtsAngleEdit::setCboxUnit()
{
m_ui->cBoxAngleUnit->clear();
const std::vector<AngleUnitType> allUnits = {AngleUnitType::Deg, AngleUnitType::Mil, AngleUnitType::Rad};
for(const auto &u : allUnits)
{
if (m_hiddenUnits.contains((int)u))
continue;
m_ui->cBoxAngleUnit->insertItem(static_cast<int>(u), toString(u),static_cast<int>(u));
}
setAngleUnit(AngleUnitType::Deg);
}
void LtsAngleEdit::setValue(const double value, AngleUnitType valueUnit)
{
setValue(getAngleConverted(value, getAngleCurrentUnit(), valueUnit),0);
}
void LtsAngleEdit::setAngleUnit(const AngleUnitType &type)
{
m_ui->cBoxAngleUnit->setCurrentIndex(static_cast<int>(type));
}
LtsAngleEdit::AngleUnitType LtsAngleEdit::getAngleCurrentUnit() const
{
return static_cast<AngleUnitType>(m_ui->cBoxAngleUnit->currentIndex());
}
double LtsAngleEdit::getAngle(unsigned int sboxIndex) const
{
if ((int)sboxIndex > m_sBoxMap.count())
return 0;
auto spinbox = m_sBoxMap.value(sboxIndex);
return spinbox->value();
}
QString LtsAngleEdit::toString(LtsAngleEdit::AngleUnitType t)
{
switch(t)
{
case AngleUnitType::Deg:
return tr("Degree");
case AngleUnitType::Mil:
return tr("Mil");
case AngleUnitType::Rad:
return tr("Radian");
default:
return tr("");
}
return tr("");
}
void LtsAngleEdit::onCBoxAngleUnitChanged()
{
AngleUnitType newUnit = static_cast<AngleUnitType>(m_ui->cBoxAngleUnit->currentData().toInt());
for(auto dbox : qAsConst(m_sBoxMap))
{
const double value = getAngleConverted(dbox->value(), newUnit, m_currAngleUnit);
auto mapVal = m_dboxLimitMap.value(newUnit);
dbox->setMinimum(std::get<LimTuple::AngleMin>(mapVal));
dbox->setMaximum(std::get<LimTuple::AngleMax>(mapVal));
dbox->setDecimals(std::get<LimTuple::DecimalPlace>(mapVal));
dbox->setSingleStep(std::get<LimTuple::SingleStep>(mapVal));
dbox->setValue(value);
}
m_currAngleUnit = newUnit;
}
double LtsAngleEdit::getAngleConverted(const double angle, LtsAngleEdit::AngleUnitType newAngleUnit, LtsAngleEdit::AngleUnitType oldAngleUnit)
{
double convertedAngle = angle;
if (oldAngleUnit == AngleUnitType::Deg && newAngleUnit == AngleUnitType::Mil )
convertedAngle = deg2Mil(angle);
else if (oldAngleUnit == AngleUnitType::Deg && newAngleUnit == AngleUnitType::Rad )
convertedAngle = deg2Rad(angle);
else if (oldAngleUnit == AngleUnitType::Mil && newAngleUnit == AngleUnitType::Deg )
convertedAngle = mil2Deg(angle);
else if (oldAngleUnit == AngleUnitType::Mil && newAngleUnit == AngleUnitType::Rad )
convertedAngle = mil2Rad(angle);
else if (oldAngleUnit == AngleUnitType::Rad && newAngleUnit == AngleUnitType::Deg )
convertedAngle = rad2Degree(angle);
else if (oldAngleUnit == AngleUnitType::Rad && newAngleUnit == AngleUnitType::Mil )
convertedAngle = rad2Mil(angle);
return convertedAngle;
}
void LtsAngleEdit::setEnable(int sbIndex, bool enabled)
{
if ((int)sbIndex > m_sBoxMap.count())
return;
m_sBoxMap.value(sbIndex)->setEnabled(enabled);
}
void LtsAngleEdit::showSpinbox(int sbIndex, bool visible)
{
if ((int)sbIndex > m_sBoxMap.count())
return;
m_sBoxMap.value(sbIndex)->setVisible(visible);
}
}
+71
View File
@@ -0,0 +1,71 @@
#pragma once
#include <QWidget>
#include <QDoubleSpinBox>
#include <QSet>
#include <LtsWidgets/lts_widgets_export.h>
class Ui_LtsAngleEdit;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsAngleEdit : public QWidget
{
Q_OBJECT
public:
explicit LtsAngleEdit(QWidget *parent = nullptr);
~LtsAngleEdit();
enum class AngleUnitType : unsigned int
{
Deg = 0,
Mil = 1,
Rad = 2
};
Q_ENUM(AngleUnitType)
enum LimTuple : int
{
AngleMin,
AngleMax,
DecimalPlace,
SingleStep
};
const QString spinBoxName = QStringLiteral("sboxAngleValue");
QString toString(AngleUnitType t);
void setAngleUnit(const AngleUnitType &type);
void setValue(const double value, unsigned int dboxIndex=0);
void setValue(const double value, AngleUnitType valueUnit);
void setValue(const double value, AngleUnitType valueUnit, unsigned int dboxIndex);
void hideUnits(const QVector<AngleUnitType> &list);
void showUnits(const QVector<AngleUnitType> &list);
LtsAngleEdit::AngleUnitType getAngleCurrentUnit() const;
void initAngleEditWidget(const unsigned int sboxCount);
double getAngle(unsigned int sboxIndex = 0) const;
double getAngleConverted(const double angle, LtsAngleEdit::AngleUnitType newAngleUnit, LtsAngleEdit::AngleUnitType oldAngleUnit);
void setEnable(int sbIndex, bool enabled);
void showSpinbox(int sbIndex, bool visible);
protected:
void setCboxUnit();
private Q_SLOTS:
void onCBoxAngleUnitChanged();
private:
Ui_LtsAngleEdit *m_ui;
QMap<int, QSharedPointer<QDoubleSpinBox>> m_sBoxMap;
QMap<AngleUnitType, std::tuple<int,int,int,int>> m_dboxLimitMap;
AngleUnitType m_currAngleUnit;
QSet<int> m_hiddenUnits;
};
}
+49
View File
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsAngleEdit</class>
<widget class="QWidget" name="LtsAngleEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>107</width>
<height>34</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<layout class="QHBoxLayout" name="hLayoutSpinbox"/>
</item>
<item>
<widget class="QComboBox" name="cBoxAngleUnit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+137
View File
@@ -0,0 +1,137 @@
#include "lts_background_widget.h"
#include <QPaintEvent>
#include <QPainter>
#include <QDebug>
#ifdef Q_OS_WIN
#include <QtPlatformHeaders/qwindowswindowfunctions.h>
#endif
namespace LtsWidgets
{
LtsBackgroundWidget::LtsBackgroundWidget(QWidget *parent)
: QDialog(parent)
, m_isUltraWide(false)
{
setMouseTracking(true);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint );
setWindowTitle(QStringLiteral("Splash"));
setBackground();
}
void LtsBackgroundWidget::setBackground()
{
static const auto backgroundFiles =
{
QStringLiteral(":/project/background.png"),
QStringLiteral(":/project/background.jpg"),
};
static const auto backgroundFilesWide =
{
QStringLiteral(":/project/background_wide.png"),
QStringLiteral(":/project/background_wide.jpg"),
};
m_pixmap = QPixmap();
for (const QString &f : m_isUltraWide ? backgroundFilesWide : backgroundFiles)
{
if (!QFile::exists(f))
continue;
m_pixmap = QPixmap(f);
if (m_pixmap.isNull())
continue;
break;
}
if (m_pixmap.isNull())
{
if (m_isUltraWide)
{
m_isUltraWide = false;
setBackground();
}
else
{
qWarning() << "BackgroundWidget::c_tor: file missing or is not a valid image ':/project/background.png'";
}
}
}
void LtsBackgroundWidget::setUltraWide(bool set)
{
if (set == m_isUltraWide)
return;
m_isUltraWide = set;
setBackground();
update();
}
void LtsBackgroundWidget::resizeEvent(QResizeEvent *e)
{
setUltraWide(width() > 3000);
QDialog::resizeEvent(e);
}
void LtsBackgroundWidget::paintEvent(QPaintEvent *e)
{
if (!m_pixmap.isNull())
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.drawPixmap(0, 0, width(), height(), m_pixmap);
}
QDialog::paintEvent(e);
}
bool LtsBackgroundWidget::event(QEvent *e)
{
if (e->type() == QEvent::KeyPress ||
e->type() == QEvent::MouseButtonPress ||
e->type() == QEvent::MouseButtonRelease ||
e->type() == QEvent::MouseMove)
{
emit signalOperatorAction();
e->ignore();
return true;
}
return QDialog::event(e);
}
void LtsBackgroundWidget::showFullScreen()
{
#ifdef Q_OS_WIN
winId();
QWindowsWindowFunctions::setHasBorderInFullScreen(windowHandle(), true);
#endif
QDialog::showFullScreen();
raise();
}
void LtsBackgroundWidget::closeEvent(QCloseEvent *e)
{
#ifdef DEVEL
deleteLater();
#else
e->ignore();
#endif
}
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include "lts_widgets_export.h"
#include <QDialog>
class QPixmap;
class QEvent;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsBackgroundWidget : public QDialog
{
Q_OBJECT
public:
explicit LtsBackgroundWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *e) override;
void closeEvent(QCloseEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
bool event(QEvent *e) override;
private:
void setBackground();
void setUltraWide(bool set = true);
signals:
void signalOperatorAction();
public slots:
void showFullScreen();
private:
QPixmap m_pixmap;
bool m_isUltraWide;
};
}
+274
View File
@@ -0,0 +1,274 @@
#pragma once
#include "lts_widgets_export.h"
#include <LtsUtilsCore/lts_translatable_identifier.h>
#include <QString>
#include <QString>
#include <QIcon>
#include <QScrollArea>
#include <QScroller>
#include <QAbstractItemView>
#include <functional>
namespace LtsWidgets
{
class LtsDialog;
inline QString readableDuration(qint64 msecs, bool foldDays = true)
{
if (msecs == 0)
return QObject::tr("---");
if (msecs % 1000 != 0 && msecs < 1000 * 60)
return QObject::tr("%1 seconds").arg(QLocale().toString(msecs / 1000.0, 'f', 3));
qint64 secs = msecs / 1000;
qint64 mins = secs / 60;
qint64 hours = mins / 60;
qint64 days = hours / 24;
if (foldDays)
days = 0;
else
hours = hours % 24;
mins = mins % 60;
secs = secs % 60;
if (!secs && !mins && !hours)
return QObject::tr("%n day(s)", "", days);
if (!secs && !mins && !days)
return QObject::tr("%n hour(s)", "", hours);
if (!secs && !hours && !days)
return QObject::tr("%n minute(s)", "", mins);
if (!mins && !hours && !days)
return QObject::tr("%n second(s)", "", secs);
QString strSecs = QObject::tr("%1s").arg(secs, 2, 10, QLatin1Char('0'));
QString strMins = QObject::tr("%1m").arg(mins, 2, 10, QLatin1Char('0'));
QString strHours = QObject::tr("%1h").arg(hours, 2, 10, QLatin1Char('0'));
QString strDays = QObject::tr("%1d").arg(days);
QString retVal;
if (days)
retVal += strDays + QLatin1Char(' ');
if (days || hours)
retVal.append(strHours);
if (mins || hours || days)
retVal.append(strMins);
if (secs)
retVal.append(strSecs);
return retVal;
}
inline void addTouchScroll(QWidget *widget)
{
if (!widget)
return;
widget->setAttribute(Qt::WA_AcceptTouchEvents);
{
QScrollArea *sca = qobject_cast<QScrollArea *>(widget);
if (sca)
{
QScroller::grabGesture(sca->viewport(), QScroller::LeftMouseButtonGesture);
return;
}
}
{
QAbstractItemView *aiv = qobject_cast<QAbstractItemView *>(widget);
if (aiv)
{
QScroller::grabGesture(aiv->viewport(), QScroller::LeftMouseButtonGesture);
aiv->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
aiv->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
return;
}
}
}
enum class ButtonSize
{
eDefault = 40,
};
enum class ButtonStyle
{
eAll = 1,
eTextOnly,
eIconOnly,
eTextNextToIcon
};
enum class LayoutArea
{
eUnknown,
eInfoTab,
eDialogTab,
eSpecialTab,
eMainTab,
};
enum class ExercisePart
{
ePlanning,
eExecution,
eAfterAction,
eSpecial,
};
namespace ExerciseState
{
enum State
{
eUnknown = 0,
eCreated = 1 << 0,
eStarted = 1 << 1,
ePaused = 1 << 2,
eStopped = 1 << 4,
eTerminated = 1 << 5,
eAll = eCreated | eStarted | ePaused | eStopped | eTerminated
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFlags<State>)
}
typedef ExerciseState::State ExcState;
typedef QFlags<ExcState> ExerciseStates;
enum class CreateInstantType
{
DontCreateInstant,
CreateInstantAndAddAction,
CreateInstantAndDiscardAction,
};
struct PluginData
{
using createWidgetFuncPtr = std::function<LtsDialog*(QWidget *)>;
using directFuncPtr = std::function<void(const LtsWidgets::PluginData &)>;
createWidgetFuncPtr createWidgetFunc = nullptr;
directFuncPtr directFunc = nullptr;
QStringList iconPaths;
QIcon menuIcon;
QString tooltip;
qulonglong dropHandlerKey = 0;
QString menuText;
QString menuGroup;
LtsUtils::LtsTranslatableIdentifier translatableMenuGroup;
QString identifier;
bool closable = true;
LayoutArea layoutArea = LayoutArea::eDialogTab;
int operatorRight = 0;
CreateInstantType createInstant = CreateInstantType::DontCreateInstant;
bool visibleInMenu = true;
ExercisePart exercisePart = ExercisePart::eSpecial;
ExerciseStates exerciseStates = ExerciseState::eAll;
PluginData() = default;
PluginData(const QString &_menuGroup,
const QString &_menuText,
const QString &_identifier,
const createWidgetFuncPtr &_cwfp,
int _operatorRight,
ExercisePart _exercisePart = ExercisePart::eSpecial,
ExerciseStates _exerciseStates = ExerciseState::eAll)
: PluginData(_menuGroup, _menuText, _identifier, QIcon(), _cwfp, _operatorRight, _exercisePart, _exerciseStates)
{}
PluginData(const QString &_menuGroup,
const QString &_menuText,
const QString &_identifier,
const QIcon &_icon,
const createWidgetFuncPtr &_cwfp,
int _operatorRight,
ExercisePart _exercisePart = ExercisePart::eSpecial,
ExerciseStates _exerciseStates = ExerciseState::eAll)
: createWidgetFunc(_cwfp)
, menuIcon(_icon)
, menuText(_menuText)
, menuGroup(_menuGroup)
, identifier(_identifier)
, operatorRight(_operatorRight)
, exercisePart(_exercisePart)
, exerciseStates(_exerciseStates)
{
}
static PluginData createGroup(const QString &menuGroup,
const QString &menuText,
const QString &identifier,
int operatorRight)
{
return PluginData(menuGroup, menuText, identifier, nullptr, operatorRight, ExercisePart::eSpecial);
}
bool isValid() const { return createWidgetFunc != nullptr; }
};
class LTSWIDGETS_EXPORT Designer
{
Q_GADGET
public:
enum ButtonSize
{
eDefault = static_cast<int>(LtsWidgets::ButtonSize::eDefault),
};
Q_ENUM(ButtonSize)
enum ButtonStyle
{
eAll = static_cast<int>(LtsWidgets::ButtonStyle::eAll),
eTextOnly = static_cast<int>(LtsWidgets::ButtonStyle::eTextOnly),
eIconOnly = static_cast<int>(LtsWidgets::ButtonStyle::eIconOnly),
eTextNextToIcon = static_cast<int>(LtsWidgets::ButtonStyle::eTextNextToIcon)
};
Q_ENUM(ButtonStyle)
enum LayoutArea
{
eUnknownArea = static_cast<int>(LtsWidgets::LayoutArea::eUnknown),
eInfoTab = static_cast<int>(LtsWidgets::LayoutArea::eInfoTab),
eDialogTab = static_cast<int>(LtsWidgets::LayoutArea::eDialogTab),
eSpecialTab = static_cast<int>(LtsWidgets::LayoutArea::eSpecialTab),
eMainTab = static_cast<int>(LtsWidgets::LayoutArea::eMainTab)
};
Q_ENUM(LayoutArea)
};
}
Q_DECLARE_METATYPE(LtsWidgets::Designer::ButtonSize)
Q_DECLARE_METATYPE(LtsWidgets::Designer::ButtonStyle)
Q_DECLARE_METATYPE(LtsWidgets::Designer::LayoutArea)
Q_DECLARE_METATYPE(LtsWidgets::ButtonSize)
Q_DECLARE_METATYPE(LtsWidgets::ButtonStyle)
Q_DECLARE_METATYPE(LtsWidgets::LayoutArea)
+645
View File
@@ -0,0 +1,645 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsBaseLayoutWidget</class>
<widget class="QWidget" name="LtsBaseLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<height>768</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>1024</width>
<height>768</height>
</size>
</property>
<property name="windowTitle">
<string>Operator Application</string>
</property>
<property name="windowIcon">
<iconset resource="resources/lts_resources.qrc">
<normaloff>:/rde_icon_256.png</normaloff>:/rde_icon_256.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="topLayoutWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="lbRdeSplitterLeft">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">RDE_SPLITTER_LEFT</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbProjectLogo">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;PROJECT_LOGO&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="lbAppName">
<property name="toolTip">
<string>App name</string>
</property>
<property name="text">
<string notr="true">%APP_NAME%</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bulle0">
<property name="text">
<string notr="true">•</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbCurrentTime">
<property name="toolTip">
<string>System time</string>
</property>
<property name="text">
<string notr="true">%CUR_TIME%</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lbExerciseName">
<property name="toolTip">
<string>Exercise name</string>
</property>
<property name="text">
<string notr="true">%EX_NAME%</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bullet1">
<property name="text">
<string notr="true">•</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbExercisePhase">
<property name="toolTip">
<string>Exercise phase</string>
</property>
<property name="text">
<string notr="true">%EX_PHASE%</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bullet2">
<property name="text">
<string notr="true">•</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbExerciseStatus">
<property name="toolTip">
<string>Exercise status</string>
</property>
<property name="text">
<string notr="true">%EX_STATUS%</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bullet3">
<property name="text">
<string notr="true">•</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbExerciseTime">
<property name="toolTip">
<string>Exercise time</string>
</property>
<property name="text">
<string notr="true">%EX_TIME%</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bullet4">
<property name="text">
<string notr="true">•</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbPartitionType">
<property name="toolTip">
<string>Session type (Live or Replay)</string>
</property>
<property name="text">
<string notr="true">%PART_TYPE%</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbCustomTextBullet">
<property name="text">
<string notr="true">•</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbCustomText">
<property name="toolTip">
<string>Session type (Live or Replay)</string>
</property>
<property name="text">
<string notr="true">%CUSTOM_TEXT%</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="LtsWidgets::LtsToolBarArea" name="toolBar">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="notificationLayoutWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3"/>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbDebug">
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">[debug]</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsProfileButton" name="profileButton">
<property name="minimumSize">
<size>
<width>48</width>
<height>48</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>48</width>
<height>48</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsSplitter" name="masterSplitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>10</number>
</property>
<widget class="LtsWidgets::LtsTabWidget" name="infoWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="movable">
<bool>true</bool>
</property>
</widget>
<widget class="LtsWidgets::LtsSplitter" name="mainSplitter">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>10</number>
</property>
<widget class="LtsWidgets::LtsTabWidget" name="mainWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="toolTip">
<string notr="true"/>
</property>
<property name="movable">
<bool>true</bool>
</property>
</widget>
<widget class="LtsWidgets::LtsTabWidget" name="detailWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="movable">
<bool>true</bool>
</property>
</widget>
</widget>
<widget class="LtsWidgets::LtsSplitter" name="rightSplitter">
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>10</number>
</property>
<widget class="QWidget" name="naviWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="pbPlanning">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Planning</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pbExecution">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Execution</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pbAfterAction">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>After Action</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="pbSpecial">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Extras</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>100</height>
</size>
</property>
<widget class="LtsWidgets::LtsToolBox" name="naviActionsPlanning">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
</widget>
<widget class="LtsWidgets::LtsToolBox" name="naviActionsExecution">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
</widget>
<widget class="LtsWidgets::LtsToolBox" name="naviActionsAfterAction">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
</widget>
<widget class="LtsWidgets::LtsToolBox" name="naviActionsSpecial">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="LtsWidgets::LtsTabWidget" name="specialWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="movable">
<bool>true</bool>
</property>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsProfileButton</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_profile_button.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsSplitter</class>
<extends>QSplitter</extends>
<header>LtsWidgets/lts_splitter.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsTabWidget</class>
<extends>QTabWidget</extends>
<header>LtsWidgets/lts_tab_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsToolBarArea</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_tool_bar_area.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsToolBox</class>
<extends>QToolBox</extends>
<header>LtsWidgets/lts_tool_box.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="resources/lts_resources.qrc"/>
</resources>
<connections/>
</ui>
File diff suppressed because it is too large. Load diff
+346
View File
@@ -0,0 +1,346 @@
#pragma once
#include "lts_base.h"
#include "lts_widgets_export.h"
#include "lts_notification_box.h"
#include "qevent.h"
#include <memory>
#include <QMap>
#include <QPointer>
#include <QWidget>
class QButtonGroup;
class QPropertyAnimation;
class QPushButton;
class QTimer;
class QToolButton;
namespace Ui
{
class LtsBaseLayoutWidget;
}
namespace IDL
{
enum class PartitionType;
}
namespace LtsUtils { class Promise; }
namespace LtsWidgets
{
class LtsDragIcon;
class LtsProgressDialogHelper;
class LtsTabWidget;
class LtsToolBarArea;
class LtsToolBox;
struct ExerciseData
{
QString exName;
QString exDescription;
int phId = -1;
QString phName;
QString phDescription;
QString exStateString;
ExcState exState = ExerciseState::eUnknown;
QColor exStateCol;
QString partitionType;
bool operator==(const ExerciseData &o) const
{
return exName == o.exName &&
exDescription == o.exDescription &&
phId == o.phId &&
phName == o.phName &&
phDescription == o.phDescription &&
exStateString == o.exStateString &&
exState == o.exState &&
exStateCol == o.exStateCol &&
partitionType == o.partitionType;
}
bool operator!=(const ExerciseData &o) const
{
return !operator ==(o);
}
};
class LTSWIDGETS_EXPORT LtsBaseLayoutWidget : public QWidget
{
Q_OBJECT
public:
explicit LtsBaseLayoutWidget(QWidget *parent = nullptr, bool splitMenu = true);
~LtsBaseLayoutWidget();
void hideVisibleLayouts();
void resetLayoutVisibility();
void setMenuVisible(bool visible);
bool isMenuVisible() const;
bool isTopBarVisible() const;
void setTopBarVisible(bool visible);
bool isMenuCollapsed() const;
void collapseMenu(bool collapse = true);
void setSessionInfo(const int domainId, const IDL::PartitionType &partitionType, const int partitionId, const QString &workspaceId);
LtsDragIcon *addMenuAction(const PluginData &plData, bool isFirstRun = false);
bool removeMenuAction(const PluginData &plData);
bool removeMenuAction(LtsDragIcon *icon);
bool removeMenuAction(const QString &byIdentifier);
void clearMenuActions();
void setAppName(const QString &appName);
bool isDialogFocused(const LtsDialog *dialog) const;
void setCustomText(const QString &text);
const QString customText() const;
LtsTabWidget *getTabFromLayoutArea(LayoutArea area) const;
LtsDialog *getWidget(const QString &menuGroup, const QString &identifier, LayoutArea area = LayoutArea::eUnknown);
QWidget *getMenu() const;
LtsToolBarArea *getToolbar() const;
void setOperatorName(const QString &operatorName, bool showTerminalButton);
void setProfilePicture(const QPixmap &profilePicture);
void setExerciseData(const ExerciseData &data);
void initilizationFinished();
void addNotification(QToolButton *noti);
bool isWidgetsHidden() const;
bool notificationExists(const QString &identifier) const;
const QMap<LtsDragIcon *, PluginData> &mapButtons() const { return m_mapButtons; }
void setToolBarActions(const QStringList &actions);
QStringList toolBarActions() const;
void setFunctionKeys(const QMap<int, QString> &actions);
QMap<int, QString> functionKeys() const;
void setWorkspaceId(const QString &workspaceId) { m_workspaceId = workspaceId; }
void showMessage(const QString &title, const QString &text, LtsNotificationBox::MessageType type = LtsNotificationBox::MessageType::Info, const std::function<void(const QString &link)> &clickedLinkCallback = nullptr, bool closeOnLinkClicked = true, const QString &identifier = {});
bool messageIdentifierExists(const QString &identifier) const;
void executeAction(const QString &actionIdentifier);
bool isSecondaryWidget() const { return m_isSecondaryWidget; }
void setSecondaryWidget() { m_isSecondaryWidget = true; }
void removeQueuedMessage(const QString &messageIdentifier);
public slots:
bool slotClose();
void slotLogout();
void slotScreenCountChanged(int count);
void onMenuEntryClicked();
void onHideAnimated();
void onReShowAnimated();
bool addWidget(LtsWidgets::LtsDialog *dialog, const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area = LayoutArea::eUnknown, bool setClosable = true, bool focusNewTab = true);
bool addOrReplaceWidget(LtsDialog *dialog, const QString &menuGroup, const QString &identifier, LayoutArea area = LayoutArea::eUnknown, bool setClosable = true, bool focusNewTab = true );
bool focusTab(const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area);
void executeCreateInstantFunctions(const LtsWidgets::PluginData &plData);
void setExerciseTime(qint64 mSecsSinceEpoch);
bool haveUnsavedChanges();
bool notifyUnsavedChanges();
void setIrreplaceableOnce() { m_irreplaceableOnce = true; }
bool irreplaceableReset() { bool r = m_irreplaceableOnce; m_irreplaceableOnce = false; return r; }
bool isIrreplaceable() const { return m_irreplaceableOnce; }
void showWidgets();
void hideWidgets();
private slots:
void slotOperatorMenuClicked();
void setCurrentTime();
signals:
void signalClose();
void signalLogout();
void signalShowOperatorSettings();
void signalRetranslateActions();
void signalSwap();
void signalStapleTopicLockHandler(LtsWidgets::LtsDialog *widget);
void signalSuccessfullyPlaced();
void signalNotifyUnsavedChanges(bool &reject);
protected:
void closeEvent(QCloseEvent *event) override;
void showEvent(QShowEvent *event) override;
void changeEvent(QEvent *e) override;
private:
void addDebugMenu();
void retranslate();
void addTouchScroll(QWidget *widget);
LtsDragIcon *createButton(const PluginData &plData);
int getIndexOfTab(LtsTabWidget *tab);
LtsToolBox *getToolBox(const ExercisePart &exercisePart) const;
QPushButton *getExercisePartButton(const ExercisePart &exercisePart) const;
void checkExercisePartButtonVisibility();
void checkMenuGroup(const QString &menuGroup, const ExercisePart &exercisePart);
bool isDialogFocused(const LtsDialog *dialog, const LayoutArea &layoutArea) const;
bool isDialogFocused(const LtsDialog *dialog, const LtsTabWidget *tab) const;
void applyExerciseStateRestricition();
void executePluginData(const PluginData &plData);
void showNextQueuedMessage();
struct Message
{
public:
QString title;
QString text;
LtsNotificationBox::MessageType type;
std::function<void(const QString &link)> clickedLinkCallback;
bool closeOnLinkClicked;
QString identifier;
};
ExerciseData m_exerciseData;
QMap<LtsDragIcon *, PluginData> m_mapButtons;
QList<int> m_mainSplitterSizes;
QList<int> m_menuSplitterSizes;
bool m_isHidden;
QPropertyAnimation *m_currentAnimation{nullptr};
Ui::LtsBaseLayoutWidget *m_ui{nullptr};
IDL::PartitionType m_partitionType;
int m_domainId;
int m_partitionId;
QString m_operatorName;
bool m_firstShow;
bool m_showTerminalButton;
qint64 m_exerciseTime;
QTimer *m_setCurrentTimeTimer{nullptr};
bool m_irreplaceableOnce;
QButtonGroup *m_bg{nullptr};
QString m_workspaceId;
int m_screenCount;
bool m_menuCollapsed;
QMap<QPointer<LtsWidgets::LtsTabWidget>, bool> m_oldLayoutVisibilityStates;
LtsNotificationBox *m_notiBox{nullptr};
QStringList m_notFoundYet;
bool m_isSecondaryWidget { false };
QVector<Message> m_currentMessage;
QVector<Message> m_messageQueue;
};
}
+129
View File
@@ -0,0 +1,129 @@
#include "lts_bitfield_widget.h"
#include <QPainter>
namespace LtsWidgets
{
LtsBitfieldWidget::LtsBitfieldWidget(QWidget *parent, quint8 value)
: QWidget(parent)
, m_value(value)
{
setObjectName(QString::fromUtf8("LtsBitfieldWidget"));
}
void LtsBitfieldWidget::paintEvent(QPaintEvent *pe)
{
QWidget::paintEvent(pe);
QPainter painter;
painter.begin(this);
painter.setPen(Qt::SolidLine);
if (m_hasCaption)
{
QFont font = painter.font();
font.setPointSizeF( (height()/2.0 > width()/8.0) ? width()/8.0 : height()/2.0 );
painter.setFont(font);
}
for (int i = 0; i < 8; ++i)
{
QRectF bitGraphic;
bitGraphic.setLeft(width() / 8.0 * i);
bitGraphic.setWidth((width() / 8.0) - 1);
bitGraphic.setHeight(height() - 1);
bool bitVal = (m_value & (1 << (7 - i))) > 0;
painter.fillRect(bitGraphic, QBrush(bitVal ? m_onColor : m_offColor, Qt::SolidPattern));
if (m_hasCaption)
{
painter.setPen(bitVal ? m_offColor : m_onColor);
painter.drawText(bitGraphic, Qt::AlignCenter, bitVal ? QStringLiteral("1") : QStringLiteral("0"));
}
painter.setPen(Qt::gray);
painter.drawRect(bitGraphic);
}
painter.end();
}
void LtsBitfieldWidget::setHasCaption(bool hasCaption)
{
if (m_hasCaption == hasCaption)
return;
m_hasCaption = hasCaption;
repaint();
emit hasCaptionChanged(hasCaption);
}
void LtsBitfieldWidget::setOnColor(const QColor &onColor)
{
if (m_onColor == onColor)
return;
m_onColor = onColor;
repaint();
}
void LtsBitfieldWidget::setOffColor(const QColor &offColor)
{
if (m_offColor == offColor)
return;
m_offColor = offColor;
repaint();
}
void LtsBitfieldWidget::mousePressEvent(QMouseEvent *event)
{
if (!m_isEditable)
{
QWidget::mousePressEvent(event);
return;
}
for (int i = 0; i < 8; ++i)
{
if (event->pos().x() > width()/8 * i &&
event->pos().x() < width()/8 * (i + 1))
{
m_value ^= (1 << (7 - i));
emit valueChanged(m_value);
break;
}
}
repaint();
}
void LtsBitfieldWidget::setEditable(bool editable)
{
if (m_isEditable == editable)
return;
m_isEditable = editable;
emit isEditableChanged(m_isEditable);
}
void LtsBitfieldWidget::setValue(quint8 value)
{
if (m_value == value)
return;
m_value = value;
repaint();
emit valueChanged(m_value);
}
}
+95
View File
@@ -0,0 +1,95 @@
#pragma once
#include <QWidget>
#include <QMouseEvent>
#include "lts_widgets_export.h"
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsBitfieldWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(quint8 value READ value WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(bool isEditable READ isEditable WRITE setEditable NOTIFY isEditableChanged)
Q_PROPERTY(bool hasCaption READ hasCaption WRITE setHasCaption NOTIFY hasCaptionChanged)
Q_PROPERTY(QColor onColor READ onColor WRITE setOnColor)
Q_PROPERTY(QColor offColor READ offColor WRITE setOffColor)
public:
explicit LtsBitfieldWidget(QWidget *parent = nullptr, quint8 value = 0);
signals:
void valueChanged(quint8 newValue);
void isEditableChanged(bool option);
void hasCaptionChanged(bool option);
public slots:
void setValue(quint8 value);
void setEditable(bool editable);
void setHasCaption(bool hasCaption);
void setOnColor(const QColor &onColor);
void setOffColor(const QColor &offColor);
public:
quint8 value() const { return m_value; }
bool isEditable() const { return m_isEditable; }
bool hasCaption() const { return m_hasCaption; }
QColor onColor() const {return m_onColor;}
QColor offColor() const {return m_offColor;}
private:
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *pe) override;
private:
quint8 m_value = 0;
bool m_isEditable = true;
bool m_hasCaption = true;
QColor m_onColor = Qt::black;
QColor m_offColor = Qt::white;
};
}
+131
View File
@@ -0,0 +1,131 @@
#pragma once
#include "lts_abstract_table_model.h"
namespace LtsWidgets
{
template<class T>
class LtsCheckableTableModel : public LtsAbstractTableModel<T>
{
public:
LtsCheckableTableModel(const QVector<QString> &header, int checkableColumn, QObject *parent)
: LtsAbstractTableModel<T>(header, parent)
, m_checkableColumn(checkableColumn)
{
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
{
if (role == Qt::CheckStateRole && index.column() == m_checkableColumn && LtsAbstractTableModel<T>::indexIsValid(index))
return LtsAbstractTableModel<T>::m_vecData.at(index.row()).first ? Qt::Checked : Qt::Unchecked;
return QVariant();
}
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
{
if (role == Qt::CheckStateRole)
{
switchCheckbox(index);
return true;
}
return QAbstractItemModel::setData(index, value, role);
}
Qt::ItemFlags flags(const QModelIndex &index) const override
{
Qt::ItemFlags flags(LtsWidgets::LtsAbstractTableModel<T>::flags(index) & ~Qt::ItemIsSelectable);
if (index.column() == m_checkableColumn)
return flags.setFlag(Qt::ItemIsUserCheckable);
return flags;
}
QVector<int> getCheckedIds() const
{
QVector<int> ids;
for (int row = 0; row < LtsAbstractTableModel<T>::rowCount(); ++row)
{
const T &entry = LtsAbstractTableModel<T>::m_vecData.at(row);
if (entry.first)
ids << entry.second.id();
}
return ids;
}
QVector<int> getUncheckedIds() const
{
QVector<int> ids;
for (int row = 0; row < LtsAbstractTableModel<T>::rowCount(); ++row)
{
const T &entry = LtsAbstractTableModel<T>::m_vecData.at(row);
if (!entry.first)
ids << entry.second.id();
}
return ids;
}
bool setChecked(const QVector<int> &vecCheckedIds)
{
for (int row = 0; row < LtsAbstractTableModel<T>::rowCount(); ++row)
{
T &entry = LtsAbstractTableModel<T>::m_vecData[row];
bool bContains = vecCheckedIds.contains(entry.second.id());
if (entry.first != bContains)
{
entry.first = bContains;
const QModelIndex idx(LtsAbstractTableModel<T>::index(row, m_checkableColumn, QModelIndex()));
emit LtsAbstractTableModel<T>::dataChanged(idx, idx, {Qt::CheckStateRole});
}
}
return true;
}
bool isFiltered(const T &data, DataModification modType) const override
{
Q_UNUSED(data);
Q_UNUSED(modType);
return false;
}
public slots:
void switchCheckbox(const QModelIndex &index)
{
auto entry = LtsAbstractTableModel<T>::getRowData(index.row());
entry.first = !entry.first;
LtsAbstractTableModel<T>::setRowData(index.row(), entry);
}
void selectAll()
{
for (int row = 0; row < LtsAbstractTableModel<T>::rowCount(); ++row)
{
T entry = LtsAbstractTableModel<T>::m_vecData.at(row);
entry.first = true;
LtsAbstractTableModel<T>::setRowData(row, entry);
}
}
void unselectAll()
{
for (int row = 0; row < LtsAbstractTableModel<T>::rowCount(); ++row)
{
T entry = LtsAbstractTableModel<T>::m_vecData.at(row);
entry.first = false;
LtsAbstractTableModel<T>::setRowData(row, entry);
}
}
private:
int m_checkableColumn;
};
}
+156
View File
@@ -0,0 +1,156 @@
#include "lts_column_filter_proxy_model.h"
#include <LtsUtilsCore/variant_operators.h>
#include <QRegularExpression>
namespace LtsWidgets
{
LtsColumnFilterProxyModel::LtsColumnFilterProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
{
setSortCaseSensitivity(Qt::CaseInsensitive);
}
bool LtsColumnFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
return LtsUtils::lessThan(sourceModel()->data(left), sourceModel()->data(right));
}
void LtsColumnFilterProxyModel::onSetColumnStringFilter(const QString &newFilterString, int column)
{
setColumnStringFilter(newFilterString, column);
}
void LtsColumnFilterProxyModel::onSetColumnDataFilter(const QVariant &newFilterData, int column)
{
setColumnDataFilter(newFilterData, column);
}
void LtsColumnFilterProxyModel::setColumnStringFilter(const QString &newFilterString, int column)
{
if (column < 0)
return;
auto it = m_columnStringFilters.find(column);
if (newFilterString.isEmpty())
{
if (it == m_columnStringFilters.end())
return;
m_columnStringFilters.erase(it);
}
else
{
auto rx = QRegularExpression(newFilterString,
QRegularExpression::CaseInsensitiveOption);
if (it == m_columnStringFilters.end())
{
m_columnStringFilters.insert(column, rx);
}
else
{
if (rx == it.value())
return;
it.value() = rx;
}
}
invalidateFilter();
}
void LtsColumnFilterProxyModel::setColumnDataFilter(const QVariant &newFilterData, int column)
{
if (column < 0)
return;
auto it = m_columnDataFilters.find(column);
if (newFilterData.isNull())
{
if (it == m_columnDataFilters.end())
return;
m_columnDataFilters.erase(it);
}
else
{
if (it == m_columnDataFilters.end())
{
m_columnDataFilters[column] = newFilterData;
}
else
{
if (newFilterData == it.value())
return;
it.value() = newFilterData;
}
}
invalidateFilter();
}
bool LtsColumnFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
const auto sm = sourceModel();
bool bRet = true;
for (auto it = m_columnDataFilters.begin(); bRet && it != m_columnDataFilters.end(); ++it)
{
const QModelIndex idx = sm->index(source_row, it.key(), source_parent);
const QVariant _data = sm->data(idx, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole).toString();
bRet = _data == it.value();
if (!bRet)
break;
}
for (auto it = m_columnStringFilters.begin(); bRet && it != m_columnStringFilters.end(); ++it)
{
const QRegularExpression &rx = it.value();
if (!rx.isValid())
continue;
const QModelIndex idx = sm->index(source_row, it.key(), source_parent);
const QString _data = sm->data(idx, Qt::DisplayRole).toString();
bRet = _data.contains(rx);
if (!bRet)
break;
}
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
if (!bRet && m_bRecursiveFiltering)
{
const QModelIndex idx = sm->index(source_row, 0, source_parent);
if (checkIfOneChildIsVisible(idx))
return true;
}
#endif
return bRet;
}
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
void LtsColumnFilterProxyModel::setRecursiveFilteringEnabled(bool recursive)
{
if (m_bRecursiveFiltering == recursive)
return;
m_bRecursiveFiltering = recursive;
invalidateFilter();
}
bool LtsColumnFilterProxyModel::recursiveFilteringEnabled() const
{
return m_bRecursiveFiltering;
}
bool LtsColumnFilterProxyModel::checkIfOneChildIsVisible(const QModelIndex &parent) const
{
const auto sm = sourceModel();
const int childCount = sm->rowCount(parent);
for (int i = 0; i < childCount; ++i)
{
if (filterAcceptsRow(i, parent))
return true;
}
return false;
}
#endif
}
+122
View File
@@ -0,0 +1,122 @@
#pragma once
#include <LtsWidgets/lts_widgets_export.h>
#include <LtsUtilsCore/variant_operators.h>
#include <QDataStream>
#include <QIcon>
#include <QRegularExpression>
#include <QSortFilterProxyModel>
#include <QVector>
namespace LtsWidgets
{
struct ComboboxFilterData
{
QString text;
QVariant data;
QIcon icon;
inline bool operator<(const ComboboxFilterData &cfd)
{
return LtsUtils::lessThan(data, cfd.data);
}
inline friend QDataStream &operator<<(QDataStream &ds, const ComboboxFilterData &cfd)
{
ds << cfd.text << cfd.data << cfd.icon;
return ds;
}
inline friend QDataStream &operator>>(QDataStream &ds, ComboboxFilterData &cfd)
{
ds >> cfd.text >> cfd.data >> cfd.icon;
return ds;
}
};
struct ComboboxFilterContent
{
QVector<ComboboxFilterData> data;
bool sortItems = false;
bool isValid() const { return m_isValid; }
QVariant toVariant() const
{
if (!isValid())
return QVariant();
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << (*this);
return ba;
}
static ComboboxFilterContent fromVariant(const QVariant &v)
{
ComboboxFilterContent ret;
QDataStream ds(v.toByteArray());
ds.startTransaction();
ds >> ret;
ds.commitTransaction();
ret.m_isValid = ds.status() == QDataStream::Ok;
return ret;
}
inline friend QDataStream &operator<<(QDataStream &ds, const ComboboxFilterContent &cfc)
{
ds << cfc.data << cfc.sortItems;
return ds;
}
inline friend QDataStream &operator>>(QDataStream &ds, ComboboxFilterContent &cfc)
{
ds >> cfc.data >> cfc.sortItems;
return ds;
}
private:
bool m_isValid = true;
};
class LTSWIDGETS_EXPORT LtsColumnFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
static constexpr int ComboboxFilterRole = Qt::UserRole + 17;
explicit LtsColumnFilterProxyModel(QObject *parent = nullptr);
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
void setRecursiveFilteringEnabled(bool recursive);
bool recursiveFilteringEnabled() const;
#endif
const QHash<int, QRegularExpression> &columnStringFilters() const { return m_columnStringFilters; }
const QHash<int, QVariant> &columnDataFilters() const { return m_columnDataFilters; }
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
virtual void setColumnStringFilter(const QString &newFilterString, int column);
virtual void setColumnDataFilter(const QVariant &newFilterData, int column);
public slots:
void onSetColumnStringFilter(const QString &newFilterString, int column);
void onSetColumnDataFilter(const QVariant &newFilterData, int column);
protected:
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
bool checkIfOneChildIsVisible(const QModelIndex &parent) const;
#endif
private:
QHash<int, QRegularExpression> m_columnStringFilters;
QHash<int, QVariant> m_columnDataFilters;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
bool m_bRecursiveFiltering = false;
#endif
};
}
+75
View File
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsColumnOrganiserWidget</class>
<widget class="QWidget" name="LtsColumnOrganiserWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>419</width>
<height>402</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QTableView" name="tableView">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>178</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="resetButton">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="applyButton">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+118
View File
@@ -0,0 +1,118 @@
#include "lts_combo_box.h"
#include "lts_selection_popup.h"
#include "lts_message_dialog.h"
#include <QGuiApplication>
#include <QShowEvent>
#ifdef NEVER
# include <QDebug>
#endif
namespace LtsWidgets
{
bool LtsComboBox::s_useSelectionDialog = false;
LtsComboBox::LtsComboBox(QWidget *parent)
: QComboBox(parent)
, m_currentIndex(-1)
{
connect(this, &LtsComboBox::signalExternallyChanged,
this, &LtsComboBox::signalRefill);
}
void LtsComboBox::setUseSelectionDialog(bool bUseSelectionDialog)
{
s_useSelectionDialog = bUseSelectionDialog;
}
void LtsComboBox::showEvent(QShowEvent *e)
{
QComboBox::showEvent(e);
m_currentIndex = currentIndex();
}
void LtsComboBox::enterEvent(QEvent *e)
{
BaseClass::enterEvent(e);
emit signalEnterEvent();
}
void LtsComboBox::leaveEvent(QEvent *e)
{
BaseClass::leaveEvent(e);
emit signalLeaveEvent();
}
void LtsComboBox::showPopup()
{
bool bUseSelectionDialog = s_useSelectionDialog;
if (QGuiApplication::queryKeyboardModifiers() == Qt::ControlModifier)
bUseSelectionDialog = !bUseSelectionDialog;
if (!bUseSelectionDialog)
{
QComboBox::showPopup();
return;
}
if (!model()->rowCount())
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("There are no items available!"));
return;
}
LtsSelectionPopup* popup = new LtsSelectionPopup(model(), currentIndex(), this);
popup->setAttribute(Qt::WA_DeleteOnClose);
#ifdef NEVER
connect(popup, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::currentIndexChanged), this, [](int idx){
qCritical() << " LtsComboBox: called: currentIndexChanged(int), idx=" << idx;
});
connect(popup, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::activated), this, [](int idx){
qCritical() << " LtsComboBox: called: activated(int), idx=" << idx;
});
#endif
connect(popup, &LtsSelectionPopup::currentIndexChanged,
this, &LtsComboBox::userChangedIndex);
connect(popup, &LtsSelectionPopup::activated,
this, static_cast<void (LtsComboBox::*)(int)>(&LtsComboBox::activated));
popup->show();
}
void LtsComboBox::userChangedIndex(int index)
{
m_currentIndex = index;
setCurrentIndex(index);
}
bool LtsComboBox::hasValueChanged() const
{
if (m_currentIndex == -1)
return false;
return !(currentIndex() == m_currentIndex);
}
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include "lts_widgets_export.h"
#include <QComboBox>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsComboBox : public QComboBox
{
Q_OBJECT
using BaseClass = QComboBox;
public:
explicit LtsComboBox(QWidget *parent = nullptr);
~LtsComboBox() = default;
static void setUseSelectionDialog(bool bUseSelectionDialog);
bool hasValueChanged() const;
void setExternalContentType(int ect) { m_externalContentType = ect; }
int externalContentType() const { return m_externalContentType; }
protected:
void showPopup() override;
void showEvent(QShowEvent *e) override;
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *) override;
protected slots:
void userChangedIndex(int index);
signals:
void signalExternallyChanged();
void signalRefill();
void signalEnterEvent();
void signalLeaveEvent();
private:
int m_currentIndex;
int m_externalContentType;
static bool s_useSelectionDialog;
};
}
File diff suppressed because it is too large. Load diff
+213
View File
@@ -0,0 +1,213 @@
#pragma once
#include "lts_widgets_export.h"
#include "qcheckbox.h"
#include "qpushbutton.h"
#include <QWidget>
#include <functional>
namespace Ui
{
class LtsDateTimeEditLe;
class LtsDateTimeEdit;
}
class QLineEdit;
class QShortcut;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsDateTimeEdit : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool autoForward READ getAutoForward WRITE setAutoForward)
Q_PROPERTY(bool editTimezone READ getEditTimezone WRITE setEditTimezone)
Q_PROPERTY(bool withButtons READ getWithButtons WRITE setWithButtons)
Q_PROPERTY(bool withSlider READ getWithSlider WRITE setWithSlider)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
Q_PROPERTY(bool withNowButton READ withNowButton WRITE setWithNowButton)
Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY toggled)
public:
using CurrentTimeCallback = std::function<qint64()>;
explicit LtsDateTimeEdit(QWidget *parent = nullptr, bool withNowButton = true, bool checkable = false);
~LtsDateTimeEdit();
bool setupUiTouch();
qint64 msecsSinceEpoch() const;
bool isEmpty() const;
bool isValidDate() const;
void setAutoForward(const bool af) { m_autoForward = af; }
bool getAutoForward() const { return m_autoForward; }
void setEditTimezone(const bool edit);
bool getEditTimezone() const { return m_editTimezone; }
void setWithButtons(const bool buttons);
bool getWithButtons() const { return m_withButtons; }
void setWithSlider(const bool slider);
bool getWithSlider() const { return m_withSlider; }
void setReadOnly(const bool readOnly);
bool isReadOnly() const { return m_readOnly; }
void setCheckable(bool checkable);
bool isCheckable() const { return m_checkable; }
void setChecked(bool bChecked);
bool isChecked() const;
void setWithNowButton(bool nowButton);
bool withNowButton() const { return m_withNowButton; }
void setMinimumTimeMSec(qint64 msec);
qint64 minimumTimeMSec() const { return m_minTimeMSec; }
void setMaximumTimeMSec(qint64 msec);
qint64 maximumTimeMSec() const { return m_maxTimeMSec; }
void setMinMaxTimeMSec(qint64 min, qint64 max) { setMinimumTimeMSec(min); setMaximumTimeMSec(max); }
void setRetrieveCurrentTimeCallback(const CurrentTimeCallback &cb);
bool setTimezone(char tz);
char getTimezone() const;
qint64 getTimezoneAsSecs() const;
void setSubWidgetsProperties(const QString &name, const QVariant &value);
Q_SIGNALS:
void dateTimeChanged();
void toggled(bool on);
public Q_SLOTS:
bool setMsecsSinceEpoch(qint64 msec, bool setToNearestPossible = true);
void clear();
private:
void clearTimezone();
void setMinMaxMonth(int minMonth, int maxMonth);
bool setMonth(int month);
int getMonth() const;
bool setDay(int day);
int getDay() const;
bool setHHMMSS(int hour, int minute, int second);
int getHour() const;
int getMinute() const;
int getSecond() const;
bool setYear(int year);
int getYear() const;
bool isEmptyDay() const;
bool isEmptyHHMMSS() const;
bool isEmptyTimezone() const;
bool isEmptyMonth() const;
bool isEmptyYear() const;
bool hasFocus() const;
bool isDataAcceptable();
void showInvalidData(bool setFocus);
bool isLineEditDataAcceptable(QLineEdit *le) const;
bool isDayAcceptable() const;
bool isHHMMSSAcceptable() const;
bool isMonthAcceptable() const;
bool isYearAcceptable() const;
bool isTzAcceptable() const;
QCheckBox* checkBox() const;
QPushButton* pbNow() const;
private Q_SLOTS:
void setFixedDateTime();
void setOffsetDateTime();
void setSliderValue(int val);
void valueDayChanged(const QString &str);
void fixupHHMMSS();
void valueMonthChanged(const QString &str);
void valueMonthChanged2(const QString &str);
void valueTimezoneChangedStr(const QString &str);
void valueTimezoneChangedInt(int newTimezone);
void valueYearChanged(const QString &str);
void onBackHourClicked();
void onBackMinuteClicked();
void onBackSecondClicked();
void onForwardSecondClicked();
void onForwardMinuteClicked();
void onForwardHourClicked();
void onCheckBoxChanged();
void disableControls();
void enableControls();
void enaDisaControls(bool bEnable);
void onFocusOutHHMMSS();
void onFocusOutTZ();
void onFocusOutDay();
void onFocusOutMonth();
void onFocusOutYear();
void onFocusOutBackspace();
void onFocusOut();
void onHmsWheelEvent(bool bForward, int cursorPos);
void onDayWheelEvent(bool bForward, int cursorPos);
void onMonthWheelEvent(bool bForward, int cursorPos);
void onYearWheelEvent(bool bForward, int cursorPos);
private:
Ui::LtsDateTimeEditLe *m_uiLe{nullptr};
Ui::LtsDateTimeEdit *m_uiTouch{nullptr};
QShortcut *m_scFixed = nullptr;
QShortcut *m_scOffset = nullptr;
CurrentTimeCallback m_getCurrentTimeCallback = nullptr;
qint64 m_minTimeMSec = 0;
qint64 m_maxTimeMSec = 0;
qint64 m_curTimeMSec = -1;
bool m_editTimezone = true;
bool m_autoForward = true;
bool m_withButtons = false;
bool m_withSlider = false;
bool m_readOnly = false;
bool m_checkable = false;
bool m_withNowButton = false;
int m_minMonth{0};
int m_maxMonth{0};
bool m_backspacePressed = false;
bool m_recursionAvoid = false;
bool m_dateIsAcceptable = false;
};
}
+118
View File
@@ -0,0 +1,118 @@
#include "lts_date_time_edit_p.h"
#include <QApplication>
#include <QRegularExpression>
#include <QValidator>
#include <QKeyEvent>
namespace LtsWidgets
{
void LineEdit::clear()
{
setStyleSheet(QString());
QLineEdit::clear();
}
bool LineEdit::isEmpty() const
{
return text().isEmpty();
}
void LineEdit::keyPressEvent(QKeyEvent *event)
{
const bool wasEmpty = isEmpty();
QLineEdit::keyPressEvent(event);
int keyCode = event->key();
if (keyCode == Qt::Key_Backspace && wasEmpty)
{
emit focusOutBackspace();
focusPreviousChild();
event->accept();
}
}
void LineEdit::contextMenuEvent(QContextMenuEvent *e)
{
Q_UNUSED(e);
}
void LineEdit::focusOutEvent(QFocusEvent *event)
{
QLineEdit::focusOutEvent(event);
emit focusOut();
}
DigitsLineEdit::DigitsLineEdit(QWidget *parent)
: LineEdit(parent)
{
setAlignment(Qt::AlignRight);
QRegularExpression rx(QLatin1String("[-]{0,1}[0-9 ]*"));
setValidator(new QRegularExpressionValidator(rx, this));
}
void DigitsLineEdit::setExactNumDigits(int num)
{
m_exactNumDigits = num;
QRegularExpression rx(QString::asprintf("^[0-9 ]{%d}$", num));
setValidator(new QRegularExpressionValidator(rx, this));
}
void DigitsLineEdit::setValue(int val)
{
QString str;
if (m_exactNumDigits == -1)
str.setNum(val);
else
str = QStringLiteral("%1").arg(val, m_exactNumDigits, 10, QLatin1Char('0'));
setText(str);
}
int DigitsLineEdit::getValue() const
{
if (text().isEmpty())
return 0;
return text().remove(QLatin1Char(' ')).toInt();
}
void DigitsLineEdit::setCursorPosition(int curPos)
{
curPos = curPos < 0 ? 1 : curPos;
QLineEdit::setCursorPosition(curPos);
}
void DigitsLineEdit::wheelEvent(QWheelEvent *event)
{
LineEdit::wheelEvent(event);
const QString txt = text();
if (m_exactNumDigits > 0 && txt.length() != m_exactNumDigits)
return;
event->accept();
int cursorPos = cursorPosition();
emit wheelEventReceived(event->delta() > 0, cursorPos);
}
void DigitsLineEdit::keyPressEvent(QKeyEvent *event)
{
LineEdit::keyPressEvent(event);
if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down)
{
const bool bUp = event->key() == Qt::Key_Up;
const int cursorPos = cursorPosition();
emit wheelEventReceived(bUp, cursorPos);
}
}
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <QLineEdit>
namespace LtsWidgets
{
class LineEdit : public QLineEdit
{
Q_OBJECT
public:
using QLineEdit::QLineEdit;
void clear();
bool isEmpty() const;
protected:
void contextMenuEvent(QContextMenuEvent *e) override;
void focusOutEvent(QFocusEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
Q_SIGNALS:
void focusOutBackspace();
void focusOut();
};
class DigitsLineEdit final : public LineEdit
{
Q_OBJECT
public:
DigitsLineEdit(QWidget *parent = nullptr);
void setExactNumDigits(int num);
void setCursorPosition(int curPos);
void setValue(int val);
int getValue() const;
Q_SIGNALS:
void wheelEventReceived(bool bForward, int cursorPos);
protected:
void wheelEvent(QWheelEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
int m_exactNumDigits = -1;
};
}
File diff suppressed because it is too large. Load diff
+206
View File
@@ -0,0 +1,206 @@
#pragma once
#include "lts_widgets_export.h"
#include <QWidget>
#include <functional>
namespace Ui
{
class LtsDateTimeEditLe;
class LtsDateTimeEdit;
}
class QLineEdit;
class QShortcut;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsDateTimeEdit : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool autoForward READ getAutoForward WRITE setAutoForward)
Q_PROPERTY(bool editTimezone READ getEditTimezone WRITE setEditTimezone)
Q_PROPERTY(bool withButtons READ getWithButtons WRITE setWithButtons)
Q_PROPERTY(bool withSlider READ getWithSlider WRITE setWithSlider)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
Q_PROPERTY(bool withNowButton READ withNowButton WRITE setWithNowButton)
Q_PROPERTY(bool withCheckBox READ withCheckBox WRITE setWithCheckBox)
public:
using CurrentTimeCallback = std::function<qint64()>;
explicit LtsDateTimeEdit(QWidget *parent = nullptr, bool withNowButton = true, bool withCheckBox = false);
~LtsDateTimeEdit();
bool setupUiTouch();
qint64 msecsSinceEpoch() const;
bool isEmpty() const;
bool isValidDate() const;
void setAutoForward(const bool af) { m_autoForward = af; }
bool getAutoForward() const { return m_autoForward; }
void setEditTimezone(const bool edit);
bool getEditTimezone() const { return m_editTimezone; }
void setWithButtons(const bool buttons);
bool getWithButtons() const { return m_withButtons; }
void setWithSlider(const bool slider);
bool getWithSlider() const { return m_withSlider; }
void setReadOnly(const bool readOnly);
bool isReadOnly() const { return m_readOnly; }
void setWithCheckBox(bool checkBoxEnabled);
bool withCheckBox() const { return m_withCheckBox; }
void setCheckBoxChecked(bool bChecked);
bool isCheckBoxChecked() const;
void setWithNowButton(bool nowButton);
bool withNowButton() const { return m_withNowButton; }
void setMinimumTimeMSec(qint64 msec);
qint64 minimumTimeMSec() const { return m_minTimeMSec; }
void setMaximumTimeMSec(qint64 msec);
qint64 maximumTimeMSec() const { return m_maxTimeMSec; }
void setMinMaxTimeMSec(qint64 min, qint64 max) { setMinimumTimeMSec(min); setMaximumTimeMSec(max); }
void setRetrieveCurrentTimeCallback(const CurrentTimeCallback &cb);
bool setTimezone(char tz);
char getTimezone() const;
qint64 getTimezoneAsSecs() const;
void setSubWidgetsProperties(const QString &name, const QVariant &value);
Q_SIGNALS:
void dateTimeChanged();
public Q_SLOTS:
bool setMsecsSinceEpoch(qint64 msec, bool setToNearestPossible = true);
void clear();
private:
void clearTimezone();
void setMinMaxMonth(int minMonth, int maxMonth);
bool setMonth(int month);
int getMonth() const;
bool setDay(int day);
int getDay() const;
bool setHHMMSS(int hour, int minute, int second);
int getHour() const;
int getMinute() const;
int getSecond() const;
bool setYear(int year);
int getYear() const;
bool isEmptyDay() const;
bool isEmptyHHMMSS() const;
bool isEmptyTimezone() const;
bool isEmptyMonth() const;
bool isEmptyYear() const;
bool hasFocus() const;
bool isDataAcceptable();
void showInvalidData(bool setFocus);
bool isLineEditDataAcceptable(QLineEdit *le) const;
bool isDayAcceptable() const;
bool isHHMMSSAcceptable() const;
bool isMonthAcceptable() const;
bool isYearAcceptable() const;
bool isTzAcceptable() const;
private Q_SLOTS:
void setFixedDateTime();
void setOffsetDateTime();
void setSliderValue(int val);
void valueDayChanged(const QString &str);
void fixupHHMMSS();
void valueMonthChanged(const QString &str);
void valueMonthChanged2(const QString &str);
void valueTimezoneChangedStr(const QString &str);
void valueTimezoneChangedInt(int newTimezone);
void valueYearChanged(const QString &str);
void onBackHourClicked();
void onBackMinuteClicked();
void onBackSecondClicked();
void onForwardSecondClicked();
void onForwardMinuteClicked();
void onForwardHourClicked();
void onCheckBoxChanged();
void disableControls();
void enableControls();
void enaDisaControls(bool bEnable);
void onFocusOutHHMMSS();
void onFocusOutTZ();
void onFocusOutDay();
void onFocusOutMonth();
void onFocusOutYear();
void onFocusOutBackspace();
void onFocusOut();
void onHmsWheelEvent(bool bForward, int cursorPos);
void onDayWheelEvent(bool bForward, int cursorPos);
void onMonthWheelEvent(bool bForward, int cursorPos);
void onYearWheelEvent(bool bForward, int cursorPos);
private:
Ui::LtsDateTimeEditLe *m_uiLe{nullptr};
Ui::LtsDateTimeEdit *m_uiTouch{nullptr};
QShortcut *m_scFixed = nullptr;
QShortcut *m_scOffset = nullptr;
CurrentTimeCallback m_getCurrentTimeCallback = nullptr;
qint64 m_minTimeMSec = 0;
qint64 m_maxTimeMSec = 0;
qint64 m_curTimeMSec = -1;
bool m_editTimezone = true;
bool m_autoForward = true;
bool m_withButtons = false;
bool m_withSlider = false;
bool m_readOnly = false;
bool m_withCheckBox = false;
bool m_withNowButton = false;
int m_minMonth{0};
int m_maxMonth{0};
bool m_backspacePressed = false;
bool m_recursionAvoid = false;
bool m_dateIsAcceptable = false;
};
}
+389
View File
@@ -0,0 +1,389 @@
#include "lts_date_time_edit_touch.h"
#include "ui_lts_date_time_edit_touch.h"
#include <ngltools/ngltools_dtg.h>
#include <LtsSession/lts_session_data.h>
#include <LtsUtilsSettings/settings.h>
#include <QShortcut>
namespace LtsWidgets
{
LtsDateTimeEdit::LtsDateTimeEdit(QWidget *parent, bool withNowButton, bool withCheckBox)
: QWidget(parent)
, m_withCheckBox(withCheckBox)
, m_withNowButton(withNowButton)
, m_tzOffset(0)
, m_minMonth(1)
, m_maxMonth(12)
, m_scFixed(new QShortcut(QKeySequence(Qt::ShiftModifier + Qt::Key_F2), this, SLOT(onSetFixedDateTime()), nullptr, Qt::WidgetWithChildrenShortcut))
, m_scOffset(new QShortcut(QKeySequence(Qt::Key_F2), this, SLOT(onSetOffsetDateTime()), nullptr, Qt::WidgetWithChildrenShortcut))
, m_getCurrentTimeCallback(nullptr)
, m_ui(new Ui::LtsDateTimeEdit)
{
m_ui->setupUi(this);
setFocusPolicy(Qt::StrongFocus);
for (int i = 65; i < 91; i++ )
{
if (QChar(i).toUpper() == QChar::fromLatin1('I'))
continue;
m_ui->cbxTimeZone->addItem(QChar(i), QChar(i));
}
connect(m_ui->pbNow, &QPushButton::clicked,
this, &LtsDateTimeEdit::onSetOffsetDateTime);
connect(m_ui->cbxMonth, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &LtsDateTimeEdit::onDateTimeChanged);
connect(m_ui->spDay, &QSpinBox::editingFinished,
this, &LtsDateTimeEdit::onDateTimeChanged);
connect(m_ui->spHour, &QSpinBox::editingFinished,
this, &LtsDateTimeEdit::onDateTimeChanged);
connect(m_ui->spMinutes, &QSpinBox::editingFinished,
this, &LtsDateTimeEdit::onDateTimeChanged);
connect(m_ui->spSeconds, &QSpinBox::editingFinished,
this, &LtsDateTimeEdit::onDateTimeChanged);
connect(m_ui->spYear, &QSpinBox::editingFinished,
this, &LtsDateTimeEdit::onDateTimeChanged);
connect(m_ui->checkBox, &QCheckBox::toggled,
this, &LtsDateTimeEdit::onCheckBoxChanged);
connect(m_ui->cbxTimeZone, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &LtsDateTimeEdit::onTimeZoneChanged);
connect(m_ui->cbxMonth, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &LtsDateTimeEdit::onMonthChanged);
m_tzOffset = DTG::timezone2Secs(QLatin1Char(DTG::timezone()).toLatin1());
m_ui->cbxTimeZone->setCurrentIndex(m_ui->cbxTimeZone->findText(QString(QLatin1Char(DTG::timezone()))));
onTimeZoneChanged();
setMinMaxMonth(1,12);
int offset = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("TimeSettings"), QStringLiteral("Offset"), 0).toLongLong()/1000;
m_ui->pbNow->setToolTip(tr("Set to current time plus %n second(s) offset", "", offset));
updateDateTimeType();
m_ui->checkBox->setVisible(m_withCheckBox);
m_ui->pbNow->setVisible(m_withNowButton);
}
LtsDateTimeEdit::~LtsDateTimeEdit()
{
delete m_ui;
}
void LtsDateTimeEdit::updateDateTimeType()
{
switch (DTG::dateTimeType())
{
case DTG::DateTimeType::DTG:
break;
case DTG::DateTimeType::DDMMYYYY_HHMMSS_Z:
break;
case DTG::DateTimeType::DDMMYYYY_Z_HHMMSS:
break;
default:
break;
}
}
bool LtsDateTimeEdit::setTimezone(char tz)
{
QChar tzLocal = QChar(QLatin1Char(tz)).toUpper();
if (tzLocal.toLatin1() == 'J')
tzLocal = QLatin1Char('Z');
m_ui->cbxTimeZone->setCurrentIndex(m_ui->cbxTimeZone->findData(tzLocal));
int offset = DTG::timezone2Secs(tzLocal.toLatin1());
if (offset != m_tzOffset)
{
const auto ms = msecsSinceEpoch();
m_tzOffset = offset;
setMsecsSinceEpoch(ms+m_tzOffset);
}
return true;
}
char LtsDateTimeEdit::getTimezone() const
{
QChar tz = m_ui->cbxTimeZone->currentText().at(0).toUpper();
if (tz.toLatin1() == 'J')
tz = QLatin1Char('Z');
if (tz.isNull())
return DTG::timezone();
return tz.toLatin1();
}
void LtsDateTimeEdit::setMinMaxMonth(int minMonth, int maxMonth )
{
if (m_minMonth != minMonth)
m_minMonth = minMonth;
if (m_maxMonth != maxMonth)
m_maxMonth = maxMonth;
int currentMonth = m_ui->cbxMonth->currentData().toInt();
m_ui->cbxMonth->blockSignals(true);
m_ui->cbxMonth->clear();
for (int i =1; i<= 12 ; i++)
{
if (i < m_minMonth)
continue;
if (i > m_maxMonth)
break;
QDate date(1777,i,1);
m_ui->cbxMonth->addItem(date.toString(QStringLiteral("MMM")),i);
}
m_ui->cbxMonth->setCurrentIndex(m_ui->cbxMonth->findData(currentMonth));
m_ui->cbxMonth->blockSignals(false);
}
void LtsDateTimeEdit::setDateTime(const QDateTime &datetime)
{
if (!datetime.isValid() && m_withCheckBox)
{
m_ui->checkBox->setChecked(false);
return;
}
QDateTime dt = datetime.toUTC().addSecs(m_tzOffset);
dt.setOffsetFromUtc(m_tzOffset);
QDateTime oldDateTime = dateTime();
if (dt == oldDateTime)
return;
blockSignals(true);
m_ui->spDay->setValue(dt.date().day());
m_ui->cbxMonth->setCurrentIndex(m_ui->cbxMonth->findData(dt.date().month()));
m_ui->spYear->setValue(dt.date().year()-2000);
m_ui->spHour->setValue(dt.time().hour());
m_ui->spMinutes->setValue(dt.time().minute());
m_ui->spSeconds->setValue(dt.time().second());
blockSignals(false);
const QDateTime dtNew = dateTime();
if (dtNew != oldDateTime)
emit dateTimeChanged();
}
void LtsDateTimeEdit::onDateTimeChanged()
{
emit dateTimeChanged();
QDateTime dateTime;
dateTime = dateTime.addYears(m_ui->spYear->value());
dateTime = dateTime.addMonths(m_ui->cbxMonth->currentData().toInt());
dateTime = dateTime.addDays(m_ui->spDay->value());
dateTime = dateTime.addSecs(m_ui->spHour->value()*60*60 + m_ui->spMinutes->value()*60 + m_ui->spSeconds->value());
if (dateTime.isValid())
{
m_dateTime = dateTime;
}
}
void LtsDateTimeEdit::onTimeZoneChanged()
{
if (m_ui->cbxMonth->currentText().isEmpty())
{
return;
}
QChar tz = m_ui->cbxTimeZone->currentText().at(0);
if (tz.isLower())
tz = tz.toUpper();
if (tz.toLatin1() == 'J')
tz = QLatin1Char('Z');
m_ui->cbxTimeZone->setCurrentIndex(m_ui->cbxTimeZone->findData(tz));
int offset = DTG::timezone2Secs(tz.toLatin1());
if (offset != m_tzOffset)
{
const auto ms = msecsSinceEpoch();
m_tzOffset = offset;
setMsecsSinceEpoch(ms+m_tzOffset);
}
}
void LtsDateTimeEdit::onMonthChanged(int month)
{
Q_UNUSED(month);
}
void LtsDateTimeEdit::setWithCheckBox(bool checkBoxEnabled)
{
if (m_withCheckBox == checkBoxEnabled)
return;
m_withCheckBox = checkBoxEnabled;
m_ui->checkBox->setVisible(m_withCheckBox);
if (!m_withCheckBox)
m_ui->checkBox->setChecked(true);
emit withCheckBoxChanged(m_withCheckBox);
}
bool LtsDateTimeEdit::isCheckBoxChecked() const
{
return m_ui->checkBox->isChecked();
}
void LtsDateTimeEdit::setWithNowButton(bool nowButton)
{
if (m_withNowButton == nowButton)
return;
m_withNowButton = nowButton;
m_ui->pbNow->setVisible(m_withNowButton);
emit withNowButtonChanged(m_withNowButton);
}
void LtsDateTimeEdit::onCheckBoxChanged(bool checked)
{
m_ui->spDay->setEnabled(checked);
m_ui->spHour->setEnabled(checked);
m_ui->spMinutes->setEnabled(checked);
m_ui->spSeconds->setEnabled(checked);
m_ui->spYear->setEnabled(checked);
m_ui->cbxMonth->setEnabled(checked);
m_ui->cbxTimeZone->setEnabled(checked);
m_ui->pbNow->setEnabled(checked);
emit dateTimeChanged();
}
void LtsDateTimeEdit::setMsecsSinceEpoch(qint64 mSecsSinceEpoch)
{
if (mSecsSinceEpoch == 0 && m_withCheckBox)
{
m_ui->checkBox->setChecked(false);
return;
}
m_ui->checkBox->setChecked(true);
setDateTime(QDateTime::fromMSecsSinceEpoch(mSecsSinceEpoch).toUTC());
}
qint64 LtsDateTimeEdit::msecsSinceEpoch() const
{
const QDateTime dt(dateTime());
if (dt.isNull())
return 0;
return dt.toMSecsSinceEpoch();
}
void LtsDateTimeEdit::clear()
{
m_ui->spDay->clear();
m_ui->spHour->clear();
m_ui->spMinutes->clear();
m_ui->spSeconds->clear();
m_ui->spYear->clear();
emit dateTimeChanged();
}
void LtsDateTimeEdit::setCheckBoxChecked(bool bChecked)
{
m_ui->checkBox->setChecked(bChecked);
}
QDateTime LtsDateTimeEdit::dateTime() const
{
if (!m_ui->checkBox->isChecked())
return QDateTime();
QDateTime final;
int year = 0;
if (m_ui->spYear->value() < 1000)
{
year=m_ui->spYear->value()+2000;
}
else
{
year=m_ui->spYear->value();
}
QDate date(year,m_ui->cbxMonth->currentData().toInt(), m_ui->spDay->value());
final.setDate(date);
final = final.addSecs(m_ui->spHour->value()*60*60 + m_ui->spMinutes->value()*60 + m_ui->spSeconds->value());
if (!final.isValid())
return QDateTime();
return QDateTime(final.date(), final.time(), Qt::OffsetFromUTC, m_tzOffset).toUTC();
}
void LtsDateTimeEdit::setMaximumTimeMSec(qint64 msec)
{
const auto maximumDate(QDateTime::fromMSecsSinceEpoch(msec).date());
m_ui->spYear->setMaximum(maximumDate.year()-2000);
}
qint64 LtsDateTimeEdit::minimumTimeMSec() const
{
QDate date;
date.setDate(m_ui->spYear->minimum(), m_maxMonth, m_ui->spMinutes->minimum() );
return QDateTime(date).toMSecsSinceEpoch();
}
void LtsDateTimeEdit::setMinimumTimeMSec(qint64 msec)
{
const auto minimumDate(QDateTime::fromMSecsSinceEpoch(msec).date());
m_ui->spYear->setMinimum(minimumDate.year()-2000);
}
void LtsDateTimeEdit::setRetrieveCurrentTimeCallback(const CurrentTimeCallback &cb)
{
m_getCurrentTimeCallback = cb;
}
void LtsDateTimeEdit::onSetFixedDateTime()
{
setMsecsSinceEpoch(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("TimeSettings"), QStringLiteral("FixedTime"), 0).toLongLong());
}
void LtsDateTimeEdit::onSetOffsetDateTime()
{
if (!m_getCurrentTimeCallback)
return;
qint64 offset = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("TimeSettings"), QStringLiteral("Offset"), 0).toLongLong();
setMsecsSinceEpoch((m_getCurrentTimeCallback() / 1000) * 1000 + offset);
}
void LtsDateTimeEdit::setSubWidgetsProperties(QString name, QVariant value)
{
m_ui->spDay->setProperty(name.toStdString().c_str(), value);
m_ui->spHour->setProperty(name.toStdString().c_str(), value);
m_ui->spMinutes->setProperty(name.toStdString().c_str(), value);
m_ui->spSeconds->setProperty(name.toStdString().c_str(), value);
m_ui->spYear->setProperty(name.toStdString().c_str(), value);
}
}
+140
View File
@@ -0,0 +1,140 @@
#pragma once
#include "lts_widgets_export.h"
#include <QDate>
#include <QWidget>
#include <functional>
class QDateTime;
namespace Ui
{
class LtsDateTimeEdit;
}
class QShortcut;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsDateTimeEdit : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool autoForward READ getAutoForward WRITE setAutoForward)
Q_PROPERTY(bool editTimezone READ getEditTimezone WRITE setEditTimezone)
Q_PROPERTY(bool withButtons READ getWithButtons WRITE setWithButtons)
Q_PROPERTY(bool withSlider READ getWithSlider WRITE setWithSlider)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
Q_PROPERTY(bool withNowButton READ withNowButton WRITE setWithNowButton)
Q_PROPERTY(bool withCheckBox READ withCheckBox WRITE setWithCheckBox)
public:
using CurrentTimeCallback = std::function<qint64()>;
explicit LtsDateTimeEdit(QWidget *parent = nullptr, bool withNowButton = true, bool withCheckBox = false);
~LtsDateTimeEdit();
qint64 msecsSinceEpoch() const;
bool isEmpty() const { return msecsSinceEpoch() == 0; }
void setAutoForward(const bool af) { m_autoForward = af; }
bool getAutoForward() const { return m_autoForward; }
void setEditTimezone(const bool edit) { m_editTimezone = edit; }
bool getEditTimezone() const { return m_editTimezone; }
void setWithButtons(const bool buttons) { m_withButtons = buttons; }
bool getWithButtons() const { return m_withButtons; }
void setWithSlider(const bool slider) { m_withSlider = slider; }
bool getWithSlider() const { return m_withSlider; }
void setReadOnly(const bool readOnly) { m_readOnly = readOnly; }
bool isReadOnly() const { return m_readOnly; }
bool withCheckBox() const { return m_withCheckBox; }
void setCheckBoxChecked(bool bChecked);
bool isCheckBoxChecked() const;
bool withNowButton() const { return m_withNowButton; }
void setDateTime(const QDateTime &datetime);
void setMinimumTimeMSec(qint64 msec);
qint64 minimumTimeMSec() const;
void setMaximumTimeMSec(qint64 msec);
qint64 maximumTimeMSec() const { return m_maxTimeMSec; };
void setMinMaxTimeMSec(qint64 min, qint64 max) { setMinimumTimeMSec(min); setMaximumTimeMSec(max); }
void setRetrieveCurrentTimeCallback(const CurrentTimeCallback &cb);
void updateDateTimeType();
bool setTimezone(char tz);
char getTimezone() const;
void setSubWidgetsProperties(QString name, QVariant value);
bool isValidDate() const
{
return m_dateTime.isValid();
}
private:
QDateTime dateTime() const;
void setMinMaxMonth(int minMonth, int maxMonth);
public slots:
void setWithCheckBox(bool checkBoxEnabled);
void setWithNowButton(bool nowButton);
void setMsecsSinceEpoch(qint64 mSecsSinceEpoch);
void clear();
void onSetFixedDateTime();
void onSetOffsetDateTime();
public slots:
void onDateTimeChanged();
signals:
void dateTimeChanged();
void withCheckBoxChanged(bool checkBoxEnabled);
void withNowButtonChanged(bool nowButton);
private slots:
void onCheckBoxChanged(bool checked);
void onTimeZoneChanged();
void onMonthChanged(int month);
private:
qint64 m_minTimeMSec = 0;
qint64 m_maxTimeMSec = 0;
qint64 m_curTimeMSec = -1;
bool m_editTimezone = true;
bool m_autoForward = true;
bool m_withButtons = false;
bool m_withSlider = false;
bool m_readOnly = false;
bool m_withCheckBox = false;
bool m_withNowButton = false;
int m_tzOffset;
int m_minMonth;
int m_maxMonth;
QShortcut *m_scFixed;
QShortcut *m_scOffset;
QDateTime m_dateTime;
CurrentTimeCallback m_getCurrentTimeCallback;
Ui::LtsDateTimeEdit *m_ui;
};
}
+181
View File
@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsDateTimeEdit</class>
<widget class="QWidget" name="LtsDateTimeEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>558</width>
<height>31</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>558</width>
<height>31</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="dtgLayout">
<item>
<widget class="QCheckBox" name="checkBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spDay">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>31</number>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="minimumSize">
<size>
<width>5</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spHour">
<property name="maximum">
<number>23</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spMinutes">
<property name="maximum">
<number>59</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spSeconds">
<property name="maximum">
<number>59</number>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="minimumSize">
<size>
<width>5</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbxTimeZone">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="minimumSize">
<size>
<width>5</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbxMonth">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spYear">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbNow">
<property name="text">
<string>Now</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+810
View File
@@ -0,0 +1,810 @@
#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"
+473
View File
@@ -0,0 +1,473 @@
#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;
}
}
+217
View File
@@ -0,0 +1,217 @@
#include "lts_dialog_button_box.h"
#include "ui_lts_dialog_button_box.h"
#include "lts_message_dialog.h"
#include <LtsSession/lts_session_data.h>
#include <QMenu>
namespace LtsWidgets
{
LtsDialogButtonBox::LtsDialogButtonBox(QWidget *parent)
: QWidget(parent)
, m_isTablet(LtsSessionData::LtsSessionData::getInstance()->isTablet())
, m_ui(new Ui::LtsDialogButtonBox)
{
m_ui->setupUi(this);
_setVisibilityForAll(false);
QMenu *libraryMenu = new QMenu(m_ui->pbLibrary);
libraryMenu->addAction(QIcon(QLatin1String(":/style/library_load.svg")),
tr("Load"), this, &LtsDialogButtonBox::signalLibraryLoadClicked);
libraryMenu->addAction(QIcon(QLatin1String(":/style/library_save.svg")),
tr("Save"), this, &LtsDialogButtonBox::signalLibrarySaveClicked);
m_ui->pbLibrary->setMenu(libraryMenu);
m_ui->pbOk->setVisible(true);
m_ui->pbClose->setVisible(true);
}
LtsDialogButtonBox::~LtsDialogButtonBox()
{
delete m_ui;
}
void LtsDialogButtonBox::_setVisibilityForAll(bool visible)
{
const auto buttons = findChildren<QPushButton *>();
for (QPushButton *button : buttons)
button->setVisible(visible);
}
void LtsDialogButtonBox::setText(DialogButton button, const QString &text)
{
QPushButton *btn = getButton(button);
if (btn)
btn->setText(text);
}
void LtsDialogButtonBox::setToolTip(DialogButton button, const QString &text)
{
QPushButton *btn = getButton(button);
if (btn)
btn->setToolTip(text);
}
void LtsDialogButtonBox::setIcon(DialogButton button, const QIcon &icon)
{
QPushButton *btn = getButton(button);
if (btn)
btn->setIcon(icon);
}
void LtsDialogButtonBox::setMenu(DialogButton button, QMenu *menu)
{
QPushButton *btn = getButton(button);
if (btn)
btn->setMenu(menu);
}
QPushButton *LtsDialogButtonBox::getButton(DialogButton button) const
{
switch (button)
{
case DialogButton::ReadOnly:
return m_ui->pbReadOnly;
case DialogButton::Ok:
return m_ui->pbOk;
case DialogButton::Apply:
return m_ui->pbApply;
case DialogButton::Close:
return m_ui->pbClose;
case DialogButton::Yes:
return m_ui->pbYes;
case DialogButton::No:
return m_ui->pbNo;
case DialogButton::Remove:
return m_ui->pbRemove;
case DialogButton::Hide:
return m_ui->pbHide;
case DialogButton::Add:
return m_ui->pbAdd;
case DialogButton::Help:
return m_ui->pbHelp;
case DialogButton::Edit:
return m_ui->pbEdit;
case DialogButton::Save:
return m_ui->pbSave;
case DialogButton::Load:
return m_ui->pbLoad;
case DialogButton::Show:
return m_ui->pbShow;
case DialogButton::Import:
return m_ui->pbImport;
case DialogButton::Export:
return m_ui->pbExport;
case DialogButton::Library:
return m_ui->pbLibrary;
case DialogButton::CenterMap:
return m_ui->pbCenterMap;
case DialogButton::ZoomMapTo:
return m_ui->pbZoomMapTo;
case DialogButton::Print:
return m_ui->pbPrint;
#ifdef LTS_DEBUG
case DialogButton::_debug_:
return m_ui->_pbChanges;
#endif
}
Q_ASSERT(false);
return nullptr;
}
void LtsDialogButtonBox::slotRemoveClicked()
{
if (LtsMessageDialog::showMessage(this,
tr("Are you sure you want to delete the selected entry(ies)?"),
tr("Remove selected entry(ies)"),
Behaviour::Modal,
Button::Yes | Button::No)
== Button::Yes)
emit signalRemoveClicked();
}
void LtsDialogButtonBox::setButtonsVisible(QPushButton *pb)
{
if (!pb || (pb == m_ui->pbPrint && m_isTablet))
return;
m_ui->line->setVisible(true);
pb->setVisible(true);
}
void LtsDialogButtonBox::setButtonVisible(DialogButton button, bool visible)
{
QPushButton *pb = getButton(button);
if (!pb)
return;
if (m_isTablet && pb == m_ui->pbPrint)
{
pb->setVisible(false);
return;
}
pb->setVisible(visible);
}
bool LtsDialogButtonBox::isButtonVisible(DialogButton button) const
{
const QPushButton *pb = getButton(button);
return (pb ? pb->isVisible() : false);
}
void LtsDialogButtonBox::setButtonEnabled(DialogButton button, bool enabled)
{
QPushButton *pb = getButton(button);
switch (button)
{
case DialogButton::Close:
case DialogButton::Ok:
case DialogButton::Apply:
{
#ifdef LTS_DEBUG
LtsMessageDialog::showMessage(this, QStringLiteral("Hier stimmt etwas nicht. Bitte MIKE bescheid geben WAS geklickt oder gemacht wurde als dieser Dialog auftauchte, damit ich es fixen kann. Danke."), QStringLiteral(">>> STOP <<<"));
#endif
break;
}
default:
break;
}
if (pb)
pb->setEnabled(enabled);
}
bool LtsDialogButtonBox::isButtonEnabled(DialogButton button) const
{
auto *that = const_cast<LtsDialogButtonBox *>(this);
const QPushButton *pb = that->getButton(button);
return (pb ? pb->isEnabled() : false);
}
}
+196
View File
@@ -0,0 +1,196 @@
#pragma once
#include "lts_widgets_export.h"
#include "lts_message_dialog.h"
#include <QWidget>
#include <QPushButton>
namespace Ui
{
class LtsDialogButtonBox;
}
namespace LtsWidgets
{
enum class DialogButton
{
ReadOnly,
Ok,
Apply,
Close,
Yes,
No,
Remove,
Hide,
Add,
Help,
Edit,
Save,
Load,
Show,
Import,
Export,
CenterMap,
ZoomMapTo,
Library,
Print,
#ifdef LTS_DEBUG
_debug_,
#endif
};
class LTSWIDGETS_EXPORT LtsDialogButtonBox : public QWidget
{
Q_OBJECT
public:
explicit LtsDialogButtonBox(QWidget *parent);
~LtsDialogButtonBox();
template <typename Func2>
void connectButton(DialogButton button, const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,
Func2 slot, Qt::ConnectionType type = Qt::AutoConnection)
{
{
switch (button)
{
#ifdef LTS_DEBUG
case DialogButton::_debug_:
#endif
case DialogButton::Close:
case DialogButton::Ok:
case DialogButton::ReadOnly:
case DialogButton::Apply:
case DialogButton::Help:
{
LtsMessageDialog::showMessage(this,
QStringLiteral("Bitte den fuer das Plugin verantwortlichen kontaktieren:<br />"
"m_buttonBox nicht mit Ok, Apply, Help, _debug_ oder Close verbinden<br />"
"Note: Bitte nur m_buttonBox verwenden, keine LtsDialogButtonBox selber erstellen"
"Ok & Apply werden automatisch zur virtual Methode 'apply()' im LtsDialog weitergeleitet.<br />"
"Close schließt einfach den Dialog - im Destruktor oder in 'aboutToClose()' ist der 'Close Code' gut aufgehoben.<br />"
"<br />"
"FIXEN !!!!!"),
QStringLiteral("--- STOP --- !!! FIXEN !!! ---"));
break;
}
default:
break;
}
}
QPushButton *theSender = getButton(button);
if (!theSender)
return;
switch (button)
{
case DialogButton::Remove:
{
connect(this, &LtsDialogButtonBox::signalRemoveClicked, receiver, slot, type);
connect(theSender, &QPushButton::clicked, this, &LtsDialogButtonBox::slotRemoveClicked);
break;
}
case DialogButton::Export:
case DialogButton::Import:
{
if (m_isTablet)
{
theSender->setVisible(false);
return;
}
Q_FALLTHROUGH();
}
default:
connect(theSender, &QPushButton::clicked, receiver, slot, type);
break;
}
setButtonsVisible(theSender);
}
template <typename Func1, typename Func2>
bool connectLibraryButton(const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,
Func1 slotLoad,
Func2 slotSave,
Qt::ConnectionType type = Qt::AutoConnection)
{
QPushButton *theSender = getButton(DialogButton::Library);
if (!theSender)
return false;
if (m_isTablet)
{
theSender->setVisible(false);
return true;
}
setButtonsVisible(theSender);
type = static_cast<Qt::ConnectionType>(type | Qt::UniqueConnection);
return (connect(this, &LtsDialogButtonBox::signalLibraryLoadClicked, receiver, slotLoad, type) &&
connect(this, &LtsDialogButtonBox::signalLibrarySaveClicked, receiver, slotSave, type));
}
void setText(DialogButton button, const QString &text);
void setToolTip(DialogButton button, const QString &text);
void setIcon(DialogButton button, const QIcon &icon);
void setMenu(DialogButton button, QMenu *menu);
void setButtonEnabled(DialogButton button, bool enabled = true);
bool isButtonEnabled(DialogButton button) const;
void setButtonVisible(DialogButton button, bool visible = true);
bool isButtonVisible(DialogButton button) const;
QPushButton *getButton(DialogButton button) const;
void _setVisibilityForAll(bool visible);
signals:
void signalRemoveClicked();
void signalHelpClicked();
void signalLibraryLoadClicked();
void signalLibrarySaveClicked();
private slots:
void slotRemoveClicked();
private:
const bool m_isTablet;
void setButtonsVisible(QPushButton *pb);
Ui::LtsDialogButtonBox *m_ui;
};
}
+326
View File
@@ -0,0 +1,326 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsDialogButtonBox</class>
<widget class="QWidget" name="LtsDialogButtonBox">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1706</width>
<height>46</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="leftSide" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="_pbChanges">
<property name="text">
<string notr="true">[debug]</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbHelp">
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/help_index.svg</normaloff>:/style/help_index.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbPrint">
<property name="text">
<string>Print</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/freq_plan.svg</normaloff>:/style/freq_plan.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbLibrary">
<property name="text">
<string>Library</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/library.svg</normaloff>:/style/library.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbImport">
<property name="text">
<string>Import</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/export_documents.svg</normaloff>:/style/export_documents.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbExport">
<property name="text">
<string>Export</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/import_documents.svg</normaloff>:/style/import_documents.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbCenterMap">
<property name="text">
<string>Center Map</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/center_to_object.svg</normaloff>:/style/center_to_object.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbZoomMapTo">
<property name="text">
<string>Zoom to</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/zoom_map_to.svg</normaloff>:/style/zoom_map_to.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="rightSide" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="pbReadOnly">
<property name="text">
<string>ReadOnly</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/warning.svg</normaloff>:/style/warning.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbOk">
<property name="text">
<string>OK</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/dialog-ok.svg</normaloff>:/style/dialog-ok.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbApply">
<property name="text">
<string>Apply</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/dialog-ok.svg</normaloff>:/style/dialog-ok.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbLoad">
<property name="text">
<string>Load</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/export_documents.svg</normaloff>:/style/export_documents.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbSave">
<property name="text">
<string>Save</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/import_documents.svg</normaloff>:/style/import_documents.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbAdd">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/document-new.svg</normaloff>:/style/document-new.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbEdit">
<property name="text">
<string>Edit</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/document-edit.svg</normaloff>:/style/document-edit.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbShow">
<property name="text">
<string>Show</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/filter_map_settings.svg</normaloff>:/style/filter_map_settings.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbYes">
<property name="text">
<string>Yes</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/dialog-ok.svg</normaloff>:/style/dialog-ok.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbNo">
<property name="text">
<string>No</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/dialog-close.svg</normaloff>:/style/dialog-close.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbRemove">
<property name="text">
<string>Remove</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/media-vcr-nopause.svg</normaloff>:/style/media-vcr-nopause.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbHide">
<property name="text">
<string>Hide</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/show_building_configuration.svg</normaloff>:/style/show_building_configuration.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbClose">
<property name="text">
<string>Close</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/dialog-close.svg</normaloff>:/style/dialog-close.svg</iconset>
</property>
<property name="shortcut">
<string>Ctrl+W</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+172
View File
@@ -0,0 +1,172 @@
#include "lts_dialog_helper.h"
#include "lts_dialog.h"
#include "ui_lts_dialog_helper.h"
#include <QScrollArea>
#include <QScrollBar>
#include <QDebug>
namespace LtsWidgets
{
class LDHScrollBar : public QScrollBar
{
Q_OBJECT
public:
using QScrollBar::QScrollBar;
void showEvent(QShowEvent *e) override
{
QScrollBar::showEvent(e);
emit scrollbarVisiblityChanged(true);
}
void hideEvent(QHideEvent *e) override
{
QScrollBar::hideEvent(e);
emit scrollbarVisiblityChanged(false);
}
Q_SIGNALS:
void scrollbarVisiblityChanged(bool visible);
};
LtsDialogHelper::LtsDialogHelper(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::LtsDialogHelper())
, m_dialog(nullptr)
{
m_ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
auto hScroll = new LDHScrollBar(this);
auto vScroll = new LDHScrollBar(this);
m_ui->scrollArea->setHorizontalScrollBar(hScroll);
m_ui->scrollArea->setVerticalScrollBar(vScroll);
connect(hScroll, &LDHScrollBar::scrollbarVisiblityChanged,
this, &LtsDialogHelper::onHScrollBarVisibilityChanged);
connect(vScroll, &LDHScrollBar::scrollbarVisiblityChanged,
this, &LtsDialogHelper::onVScrollBarVisibilityChanged);
#ifdef TABLET_MODE
QList<QWidget *> scrollWidgets = findChildren<QWidget *>();
for (auto i = scrollWidgets.begin(); i != scrollWidgets.end(); ++i)
{
QWidget *widget = *i;
QVariant isConst = widget->property("const");
if (isConst.isValid() && isConst.toBool())
continue;
LtsWidgets::addTouchScroll(widget);
}
#endif
m_ui->buttonBox->setMinimumHeight(m_ui->buttonBox->sizeHint().height());
}
LtsDialogHelper::~LtsDialogHelper()
{
m_ui->scrollArea->horizontalScrollBar()->disconnect(this);
m_ui->scrollArea->verticalScrollBar()->disconnect(this);
delete m_ui;
}
LtsDialogButtonBox *LtsDialogHelper::getButtonBox()
{
return m_ui->buttonBox;
}
void LtsDialogHelper::setDialog(LtsDialog *dialog)
{
if (m_dialog != nullptr)
return;
m_dialog = dialog;
m_dialog->setContentsMargins(QMargins());
if (m_dialog->layout())
m_dialog->layout()->setContentsMargins(QMargins());
m_ui->scrollArea->setWidget(m_dialog);
{
connect(dialog, &LtsDialog::destroyed, this, [this]()
{
m_dialog = nullptr;
deleteLater();
});
}
}
LtsDialog *LtsDialogHelper::getDialog()
{
return m_dialog;
}
void LtsDialogHelper::retranslate()
{
if (m_dialog == nullptr)
return;
m_dialog->setContentsMargins(QMargins());
if (m_dialog->layout())
m_dialog->layout()->setContentsMargins(QMargins());
bool oldChangesFlag = m_dialog->m_changesMade;
m_dialog->retranslate();
if (oldChangesFlag)
m_dialog->slotChangesMade();
else
m_dialog->resetChanges();
}
void LtsDialogHelper::resizeEvent(QResizeEvent *e)
{
emit signalSizeChanged(e->size());
}
void LtsDialogHelper::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange)
retranslate();
}
void LtsDialogHelper::onHScrollBarVisibilityChanged(bool visible)
{
if (m_dialog == nullptr || !m_dialog->layout())
return;
QMargins m = m_dialog->layout()->contentsMargins();
m.setBottom(visible ? -1 : 0);
m_dialog->layout()->setContentsMargins(m);
}
void LtsDialogHelper::onVScrollBarVisibilityChanged(bool visible)
{
if (m_dialog == nullptr || !m_dialog->layout())
return;
QMargins m = m_dialog->layout()->contentsMargins();
m.setRight(visible ? -1 : 0);
m_dialog->layout()->setContentsMargins(m);
}
}
#include "lts_dialog_helper.moc"
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include <QWidget>
#include <QSize>
namespace Ui
{
class LtsDialogHelper;
}
namespace LtsWidgets
{
class LtsDialogButtonBox;
class LtsDialog;
class LtsDialogHelper : public QWidget
{
Q_OBJECT
public:
explicit LtsDialogHelper(QWidget *parent = nullptr);
~LtsDialogHelper();
LtsDialogButtonBox *getButtonBox();
void setDialog(LtsDialog *dialog);
LtsDialog *getDialog();
bool compare(const LtsDialog *dialog) const { return (dialog == m_dialog); }
void retranslate();
signals:
void signalSizeChanged(const QSize &size);
private:
void resizeEvent(QResizeEvent *e) override;
void changeEvent(QEvent *e) override;
void onHScrollBarVisibilityChanged(bool visible);
void onVScrollBarVisibilityChanged(bool visible);
Ui::LtsDialogHelper *m_ui;
LtsDialog *m_dialog;
};
}
+70
View File
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsDialogHelper</class>
<widget class="QWidget" name="LtsDialogHelper">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>456</width>
<height>306</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
</widget>
</item>
<item alignment="Qt::AlignBottom">
<widget class="LtsWidgets::LtsDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>150</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDialogButtonBox</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_dialog_button_box.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+489
View File
@@ -0,0 +1,489 @@
#include "lts_drag_icon.h"
#include <QDrag>
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QAction>
#include <QVBoxLayout>
#include <QLabel>
#include <QPixmap>
#include <QToolButton>
#include <QButtonGroup>
#include <QPainter>
namespace LtsWidgets
{
class LtsToolButton : public QToolButton
{
Q_OBJECT
public:
explicit LtsToolButton(QWidget *parent)
: QToolButton(parent)
, m_sameWidgetDrop(false)
, m_isDraggable(true)
, m_startPos(QPoint())
{
setAutoFillBackground(false);
setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
}
virtual ~LtsToolButton() = default;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void setSameWidgetDrop(bool drop) { m_sameWidgetDrop = drop; }
bool sameWidgetDrop() const { return m_sameWidgetDrop; }
void setDraggable(bool isDraggable) { m_isDraggable = isDraggable; }
void dropEvent(QDropEvent *event) override
{
emit newDropEvent(event);
QToolButton::dropEvent(event);
}
void addMimeData(const QString &mimeType, const QByteArray &data);
bool removeMimeData(const QString &mimeType);
void removeAllMimeData() { m_mimeData.clear(); }
protected:
void initButton();
signals:
void newDropEvent(QDropEvent *e);
void dropSuc();
private:
void performDrag(QMouseEvent *event);
bool m_sameWidgetDrop;
bool m_isDraggable;
QPoint m_startPos;
QMap<QString, QByteArray> m_mimeData;
};
LtsDragIcon::LtsDragIcon(QWidget *parent)
: QWidget(parent)
, m_lay(nullptr)
, m_toolButton(nullptr)
, m_icon()
, m_dragLabel(new QLabel(this))
, m_text()
, m_style(ButtonStyle::eAll)
, m_forceFixedSize(false)
, m_isDraggable(true)
, m_dropHandlerKey(0L)
, m_buttonSize(ButtonSize::eDefault)
, m_showDragIcon(true)
{
setAutoFillBackground(false);
initButton();
}
void LtsDragIcon::setStyleToButton()
{
if (nullptr == m_toolButton) return;
switch (m_style)
{
case ButtonStyle::eIconOnly:
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setFixedSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
m_toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
} break;
case ButtonStyle::eTextOnly:
{
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
setFixedSize( QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) );
m_toolButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
layout()->setSizeConstraint( QLayout::SetDefaultConstraint );
} break;
case ButtonStyle::eTextNextToIcon:
{
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
setFixedSize( QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) );
m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
layout()->setSizeConstraint( QLayout::SetDefaultConstraint );
} break;
default: break;
}
}
void LtsDragIcon::initButton()
{
setMinimumSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize));
delete m_toolButton;
delete m_lay;
delete layout();
m_toolButton = new LtsToolButton(this);
m_toolButton->setDraggable(m_isDraggable);
connect(m_toolButton, &LtsToolButton::clicked, this, &LtsDragIcon::clicked);
connect(m_toolButton, &LtsToolButton::toggled, this, &LtsDragIcon::toggled);
connect(m_toolButton, &LtsToolButton::newDropEvent, this, &LtsDragIcon::newDropEvent);
connect(m_toolButton, &LtsToolButton::dropSuc, this, &LtsDragIcon::dropSuc);
m_toolButton->setIcon(modifyIcon(m_icon));
m_toolButton->setText(m_text);
generateToolTip();
m_toolButton->setIconSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
QVBoxLayout *box = new QVBoxLayout(this);
box->setMargin(0);
box->setSpacing(0);
box->addWidget(m_toolButton);
this->setLayout(box);
m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
if (m_forceFixedSize)
{
m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setFixedSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
}
else
{
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
}
setStyleToButton();
}
void LtsDragIcon::addToButtonGroup(QButtonGroup *btnGrp, int btnGrpId)
{
btnGrp->addButton(m_toolButton, btnGrpId);
}
void LtsDragIcon::setIcon(const QIcon &icon)
{
m_icon = icon;
(m_toolButton) ? m_toolButton->setIcon(modifyIcon(m_icon)) : initButton();
}
void LtsDragIcon::setMenu(QMenu *menu)
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->setMenu(menu);
}
QMenu *LtsDragIcon::menu() const
{
if (nullptr == m_toolButton)
return nullptr;
return m_toolButton->menu();
}
void LtsDragIcon::setText(const QString &text)
{
m_text = text;
(m_toolButton) ? generateToolTip() : initButton();
}
void LtsDragIcon::setContext(const QString &context)
{
m_context = context;
generateToolTip();
}
void LtsDragIcon::generateToolTip()
{
if (!m_toolButton || m_text.isEmpty())
return;
QString text(m_text);
if (!m_context.isEmpty())
text.prepend(m_context + QLatin1String(" - "));
m_toolButton->setText(m_text);
m_toolButton->setToolTip(text);
}
bool LtsDragIcon::isCheckable()
{
return (m_toolButton) ? m_toolButton->isCheckable() : false;
}
void LtsDragIcon::setDraggable(bool draggable)
{
m_isDraggable = draggable;
m_toolButton->setDraggable(m_isDraggable);
}
void LtsDragIcon::setCheckable(bool checkable)
{
m_toolButton->setCheckable(checkable);
}
bool LtsDragIcon::isChecked() const
{
return (m_toolButton) ? m_toolButton->isChecked() : false;
}
void LtsDragIcon::setChecked(bool checked)
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->setChecked(checked);
}
void LtsDragIcon::setSameWidgetDrop(bool drop)
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->setSameWidgetDrop(drop);
}
bool LtsDragIcon::sameWidgetDrop() const
{
if (nullptr == m_toolButton)
return false;
return m_toolButton->sameWidgetDrop();
}
void LtsDragIcon::addMimeData(const QString &mimeType, const QByteArray &data)
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->addMimeData(mimeType, data);
}
bool LtsDragIcon::removeMimeData(const QString &mimeType)
{
if (nullptr == m_toolButton)
initButton();
return m_toolButton->removeMimeData(mimeType);
}
void LtsDragIcon::removeAllMimeData()
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->removeAllMimeData();
}
void LtsDragIcon::setAcceptDrops(bool on)
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->setAcceptDrops(on);
}
void LtsDragIcon::dragEnterEvent(QDragEnterEvent *e)
{
if (m_toolButton)
m_toolButton->dragEnterEvent(e);
}
void LtsDragIcon::dropEvent(QDropEvent *e)
{
QWidget::dropEvent(e);
}
void LtsDragIcon::setButtonStyle(ButtonStyle style)
{
m_style = style;
setStyleToButton();
}
void LtsDragIcon::setIconSize(ButtonSize buttonSize)
{
m_buttonSize = buttonSize;
(m_toolButton) ? m_toolButton->setIconSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize))) : initButton();
}
void LtsDragIcon::setForceFixedSize(bool force)
{
m_forceFixedSize = force;
initButton();
}
void LtsDragIcon::setButtonVisible(bool visible)
{
if (nullptr == m_toolButton)
initButton();
m_toolButton->setVisible(visible);
}
bool LtsDragIcon::buttonVisible() const
{
if (nullptr == m_toolButton)
return false;
return m_toolButton->isVisible();
}
void LtsDragIcon::setAction(QAction *action)
{
QIcon icon = action->icon();
if(!icon.isNull())
m_icon = icon;
m_toolButton->setDefaultAction(action);
this->setObjectName(action->objectName());
}
void LtsDragIcon::changeEvent(QEvent *event)
{
if (event->type() == QEvent::EnabledChange)
emit enabledChanged(isEnabled());
}
void LtsToolButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
m_startPos = event->pos();
QToolButton::mousePressEvent(event);
}
void LtsToolButton::mouseReleaseEvent(QMouseEvent *event)
{
QToolButton::mouseReleaseEvent(event);
}
void LtsToolButton::mouseMoveEvent(QMouseEvent *event)
{
if (!m_isDraggable)
return;
if (event->buttons() & Qt::LeftButton) {
int distance = (event->pos() - m_startPos).manhattanLength();
if (distance >= 5)
{
this->setDown(false);
performDrag(event);
return;
}
}
QToolButton::mouseMoveEvent(event);
}
void LtsToolButton::performDrag(QMouseEvent *)
{
QWidget *item = this;
if (item)
{
LtsDragIcon *dragIcon = nullptr;
QString name;
while (dragIcon == nullptr)
{
if ((!item->objectName().isEmpty()) && (name.isNull()))
{
name = item->objectName();
}
item = item->parentWidget();
if (nullptr == item) return;
dragIcon = dynamic_cast<LtsDragIcon*>(item);
}
QMimeData *mimeData = new QMimeData();
mimeData->setText(name);
for(auto it = m_mimeData.cbegin(); it != m_mimeData.cend(); ++it)
mimeData->setData(it.key(), it.value());
if (dragIcon->dropHandlerKey() != 0L)
{
QByteArray data = QByteArray(QByteArray::number(dragIcon->dropHandlerKey()));
mimeData->setData(QLatin1String("DropHandlerPtr"),data);
}
QDrag *drag = new QDrag(item);
drag->setMimeData(mimeData);
QAction *action = defaultAction();
if ((action) && (dragIcon->showDragIcon()))
{
drag->setPixmap(action->icon().pixmap(16,16) );
}
else
{
drag->setPixmap(dragIcon->icon().pixmap(16, 16));
}
Qt::DropAction drop = drag->exec(Qt::CopyAction | Qt::MoveAction);
if (drop == Qt::MoveAction || drop == Qt::CopyAction )
emit dropSuc();
}
}
void LtsToolButton::dragEnterEvent(QDragEnterEvent *event)
{
QWidget *source =
qobject_cast<QWidget *>(event->source());
if (source && source != this) {
event->setDropAction(Qt::MoveAction);
event->accept();
}
QWidget::dragEnterEvent(event);
}
void LtsToolButton::addMimeData(const QString &mimeType, const QByteArray &data)
{
m_mimeData.insert(mimeType,data);
}
bool LtsToolButton::removeMimeData(const QString &mimeType)
{
return (m_mimeData.remove(mimeType) > 0);
}
#define SIZE 40
QIcon LtsDragIcon::modifyIcon(const QIcon &icon)
{
if (m_modification.isEmpty())
return icon;
QPixmap iconImage(icon.pixmap(SIZE*0.8, SIZE*0.8));
QPainter painter(&iconImage);
painter.save();
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform);
painter.setBrush(QColor("red"));
painter.setPen(QPen(QColor("red"), 3));
QFont f;
f.setFamily(QStringLiteral("Monospace"));
f.setPointSize(12);
f.setBold(true);
painter.setFont(f);
painter.drawText(QRect(0, 0, 28, 28), m_modification);
painter.restore();
return iconImage;
}
}
#include "lts_drag_icon.moc"
+246
View File
@@ -0,0 +1,246 @@
#pragma once
#include "lts_base.h"
#include "lts_drop_handler.h"
#include "lts_widgets_export.h"
#include <QString>
#include <QIcon>
#include <QWidget>
class QButtonGroup;
class QHBoxLayout;
class QLabel;
class QMenu;
namespace LtsWidgets {
class LtsToolButton;
class LTSWIDGETS_EXPORT LtsDragIcon : public QWidget
{
public:
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(QString context READ context WRITE setContext)
Q_PROPERTY(QString identifier READ identifier WRITE setIdentifier)
Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
Q_PROPERTY(LtsWidgets::Designer::ButtonSize eButtonSize READ iconSizeDesigner WRITE setIconSizeDesigner)
Q_PROPERTY(bool eForceFixedSize READ isForceFixedSize WRITE setForceFixedSize)
Q_PROPERTY(bool isCheckable READ isCheckable WRITE setCheckable)
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
Q_PROPERTY(bool showDragIcon READ showDragIcon WRITE setShowDragIcon)
Q_PROPERTY(bool isDraggable READ isDraggable WRITE setDraggable)
Q_PROPERTY(LtsWidgets::Designer::ButtonStyle eStyle READ buttonStyleDesigner WRITE setButtonStyleDesigner)
void setButtonStyleDesigner(Designer::ButtonStyle t) { setButtonStyle(static_cast<ButtonStyle>(t)); }
Designer::ButtonStyle buttonStyleDesigner() const { return static_cast<Designer::ButtonStyle>(buttonStyle()); }
void setIconSizeDesigner(Designer::ButtonSize t) { setIconSize(static_cast<ButtonSize>(t)); }
Designer::ButtonSize iconSizeDesigner() const { return static_cast<Designer::ButtonSize>(iconSize()); }
public:
explicit LtsDragIcon(QWidget *parent);
virtual ~LtsDragIcon() = default;
void setMenu(QMenu *menu);
QMenu* menu() const;
void setText(const QString &text);
QString text() const { return m_text; }
void setContext(const QString &context);
QString context() const { return m_context; }
void setCheckable(bool checkable);
bool isCheckable();
void setDraggable(bool draggable);
bool isDraggable() const { return m_isDraggable; }
void setChecked(bool checked);
bool isChecked() const;
void setShowDragIcon(bool showDragIcon) { m_showDragIcon = showDragIcon; }
bool showDragIcon() const { return m_showDragIcon; }
void setSameWidgetDrop(bool drop);
bool sameWidgetDrop() const;
void setButtonStyle(ButtonStyle style);
ButtonStyle buttonStyle() const { return m_style; }
void setIconSize(ButtonSize buttonSize);
ButtonSize iconSize() const { return m_buttonSize; }
void setButtonVisible(bool visible);
bool buttonVisible() const;
void setIcon(const QIcon &icon);
QIcon icon() const { return m_icon; }
void setForceFixedSize(bool force);
bool isForceFixedSize() const { return m_forceFixedSize; }
void setAction(QAction *action);
void addToButtonGroup(QButtonGroup *btnGrp, int btnGrpId);
void setDropHandlerKey(qulonglong key) { m_dropHandlerKey = key; }
void addMimeData(const QString &mimeType, const QByteArray &data);
bool removeMimeData(const QString &mimeType);
void removeAllMimeData();
void setAcceptDrops(bool on);
qulonglong dropHandlerKey() const { return m_dropHandlerKey; }
void setIdentifier(const QString &id) { m_identifier = id; }
QString identifier() const { return m_identifier; }
void setModification(const QString &id) { m_modification = id; setIcon(m_icon); }
QString modification() const { return m_modification; }
void removeModification() { m_modification = QString(); setIcon(m_icon);}
signals:
void clicked();
void toggled(bool);
void newDropEvent(QDropEvent *e);
void dropSuc();
void enabledChanged(bool);
protected:
void dragEnterEvent(QDragEnterEvent *e) override;
void dropEvent(QDropEvent *e) override;
void initButton();
private:
void setStyleToButton();
QIcon modifyIcon(const QIcon &icon);
void generateToolTip();
protected slots:
void changeEvent(QEvent *event) override;
private:
QHBoxLayout *m_lay;
LtsToolButton *m_toolButton;
QIcon m_icon;
QLabel *m_dragLabel;
QString m_text;
QString m_identifier;
QString m_modification;
ButtonStyle m_style;
bool m_forceFixedSize;
bool m_isDraggable;
qulonglong m_dropHandlerKey;
ButtonSize m_buttonSize;
bool m_showDragIcon;
QString m_context;
};
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
class QMimeData;
namespace LtsWidgets
{
class LtsDropHandler
{
public:
LtsDropHandler() = default;
virtual ~LtsDropHandler() = default;
LtsDropHandler( const LtsDropHandler & ) = delete;
LtsDropHandler & operator = ( const LtsDropHandler & ) = delete;
virtual void doDrop( int x, int y, const QMimeData * mimeData ) const = 0;
};
}
+60
View File
@@ -0,0 +1,60 @@
#include "lts_elided_label.h"
#include <QPaintEvent>
#include <QResizeEvent>
namespace LtsWidgets
{
void LtsElidedLabel::setElideMode(Qt::TextElideMode elideMode)
{
m_elideMode = elideMode;
m_cachedText.clear();
update();
}
void LtsElidedLabel::resizeEvent(QResizeEvent *e)
{
QLabel::resizeEvent(e);
m_cachedText.clear();
}
void LtsElidedLabel::paintEvent(QPaintEvent *e)
{
if (m_elideMode == Qt::ElideNone)
return QLabel::paintEvent(e);
updateCachedTexts();
QLabel::setText(m_cachedElidedText);
QLabel::paintEvent(e);
QLabel::setText(m_cachedText);
}
void LtsElidedLabel::updateCachedTexts()
{
const auto txt = text();
if (m_cachedText == txt)
return;
m_cachedText = txt;
const QFontMetrics fm(fontMetrics());
m_cachedElidedText = fm.elidedText(text(),
m_elideMode,
width(),
Qt::TextShowMnemonic);
if (!m_cachedText.isEmpty())
{
const QString showFirstCharacter = m_cachedText.at(0) + QStringLiteral("...");
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
const int width = fm.width(showFirstCharacter);
#else
const int width = fm.horizontalAdvance(showFirstCharacter);
#endif
setMinimumWidth(width + 1);
}
}
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <QLabel>
#include <LtsWidgets/lts_widgets_export.h>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsElidedLabel : public QLabel
{
Q_OBJECT
public:
Q_PROPERTY(Qt::TextElideMode ElideMode READ elideMode WRITE setElideMode)
using QLabel::QLabel;
void setElideMode(Qt::TextElideMode elideMode);
Qt::TextElideMode elideMode() const { return m_elideMode; }
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
private:
void updateCachedTexts();
private:
Qt::TextElideMode m_elideMode = Qt::ElideRight;
QString m_cachedElidedText;
QString m_cachedText;
};
}
+58
View File
@@ -0,0 +1,58 @@
#include "lts_events.h"
namespace LtsWidgets
{
QEvent::Type LtsLinkEvent::eventTypeId()
{
static QEvent::Type sLinkEventId = QEvent::None;
if (sLinkEventId == QEvent::None)
sLinkEventId = static_cast<QEvent::Type>(QEvent::registerEventType());
return sLinkEventId;
}
QEvent::Type SaveImageEvent::saveImageEventId()
{
static QEvent::Type sSaveImageEventId = QEvent::None;
if (sSaveImageEventId == QEvent::None)
sSaveImageEventId = static_cast<QEvent::Type>(QEvent::registerEventType());
return sSaveImageEventId;
}
QEvent::Type SetMarkerEvent::setMarkerEventId()
{
static QEvent::Type sSetMarkerEventId = QEvent::None;
if (sSetMarkerEventId == QEvent::None)
sSetMarkerEventId = static_cast<QEvent::Type>(QEvent::registerEventType());
return sSetMarkerEventId;
}
QEvent::Type AddMarkerEvent::addMarkerEventId()
{
static QEvent::Type sAddMarkerEventId = QEvent::None;
if (sAddMarkerEventId == QEvent::None)
sAddMarkerEventId = static_cast<QEvent::Type>(QEvent::registerEventType());
return sAddMarkerEventId;
}
QEvent::Type AddSnapshotEvent::addSnapshotEventId()
{
static QEvent::Type eventId = QEvent::None;
if (eventId == QEvent::None)
eventId = static_cast<QEvent::Type>(QEvent::registerEventType());
return eventId;
}
QEvent::Type SaveSnapshotEvent::saveSnapshotEventId()
{
static QEvent::Type eventId = QEvent::None;
if (eventId == QEvent::None)
eventId = static_cast<QEvent::Type>(QEvent::registerEventType());
return eventId;
}
}
+94
View File
@@ -0,0 +1,94 @@
#pragma once
#include "lts_widgets_export.h"
#include <QEvent>
#include <QPixmap>
#include <QPointer>
#include <QWidget>
#include <QUrl>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsLinkEvent : public QEvent
{
public:
explicit LtsLinkEvent(QUrl url, QWidget *sourceBaseLayoutWidget)
: QEvent(eventTypeId())
, m_url(std::move(url))
, m_sourceBaseLayoutWidget(sourceBaseLayoutWidget)
{}
static QEvent::Type eventTypeId();
QWidget *sourceBaseLayoutWidget() const { return m_sourceBaseLayoutWidget.data(); }
QUrl url() const { return m_url; }
private:
QUrl m_url;
QPointer<QWidget> m_sourceBaseLayoutWidget;
};
class LTSWIDGETS_EXPORT SaveImageEvent : public QEvent
{
public:
SaveImageEvent(QWidget *w, QPixmap &&pm)
: QEvent(saveImageEventId()), m_widget(w), m_pix(std::move(pm))
{}
const QPixmap &pixmap() const { return m_pix; }
QWidget *widget() const { return m_widget.data(); }
static QEvent::Type saveImageEventId();
private:
QPointer<QWidget> m_widget;
QPixmap m_pix;
};
class LTSWIDGETS_EXPORT AddMarkerEvent : public QEvent
{
public:
AddMarkerEvent()
: QEvent(addMarkerEventId())
{}
static QEvent::Type addMarkerEventId();
};
class LTSWIDGETS_EXPORT SetMarkerEvent : public QEvent
{
public:
SetMarkerEvent(const QString &description)
: QEvent(setMarkerEventId()), m_description(description)
{}
const QString &getDescription() const { return m_description; }
void setDescription(const QString &description) { m_description = description; }
static QEvent::Type setMarkerEventId();
private:
QString m_description;
};
class LTSWIDGETS_EXPORT AddSnapshotEvent : public QEvent
{
public:
AddSnapshotEvent()
: QEvent(addSnapshotEventId())
{}
static QEvent::Type addSnapshotEventId();
};
class LTSWIDGETS_EXPORT SaveSnapshotEvent : public QEvent
{
public:
SaveSnapshotEvent(const QString &description)
: QEvent(saveSnapshotEventId()), m_description(description)
{}
const QString &getDescription() const { return m_description; }
void setDescription(const QString &description) { m_description = description; }
static QEvent::Type saveSnapshotEventId();
private:
QString m_description;
};
}
+153
View File
@@ -0,0 +1,153 @@
#include "lts_frameless_dialog.h"
#include <QApplication>
#include <QRect>
#include <QStyle>
#include <QSize>
#include <QScreen>
#include <QScroller>
#include <QScrollArea>
#include <QDesktopWidget>
#include <QShowEvent>
#include <QTimer>
namespace LtsWidgets
{
LtsFramelessDialog::LtsFramelessDialog(QWidget *parent, const Behaviour &behaviour)
: QDialog(parent)
{
Qt::WindowFlags wf;
switch (behaviour)
{
case Behaviour::Modal:
{
#ifndef TABLET_MODE
setModal(true);
wf |= Qt::Dialog;
#else
wf |= Qt::Window;
#endif
wf |= Qt::WindowStaysOnTopHint;
break;
}
case Behaviour::Popup:
wf |= Qt::Popup;
break;
}
setWindowFlags(wf);
QTimer *t = new QTimer(this);
t->setInterval(250);
connect(t, &QTimer::timeout,
this, [this]()
{
QSize s = size();
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, screenRectFromPoint(QCursor::pos())));
});
}
LtsFramelessDialog::~LtsFramelessDialog()
{
}
QRect LtsFramelessDialog::screenRectFromPoint(const QPoint &pos) const
{
const auto screens = QGuiApplication::screens();
for (QScreen *screen : screens)
{
QRect s = screen->geometry().adjusted(-50, -50, 50, 50);
bool contains = s.contains(pos);
if (contains)
return screen->geometry();
}
return QRect();
}
void LtsFramelessDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
QTimer::singleShot(0, this, &LtsFramelessDialog::onUpdateGeometry);
#ifdef TABLET_MODE
QList<QWidget *> scrollWidgets = findChildren<QWidget *>();
for (auto i = scrollWidgets.begin(); i != scrollWidgets.end(); ++i)
{
QWidget *widget = *i;
QVariant isConst = widget->property("const");
if (isConst.isValid() && isConst.toBool())
continue;
addTouchScroll(widget);
}
#endif
}
void LtsFramelessDialog::addTouchScroll(QWidget *widget)
{
if (!widget)
return;
widget->setAttribute(Qt::WA_AcceptTouchEvents);
QScrollArea *sca = qobject_cast<QScrollArea *>(widget);
if (sca)
{
QScroller::grabGesture(sca->viewport(), QScroller::LeftMouseButtonGesture);
return;
}
}
void LtsFramelessDialog::onUpdateGeometry()
{
QRect r;
QWidget *p = parentWidget();
if (p)
{
QWidget *window = p->window();
QPoint global = window->mapToGlobal(QPoint(0,0));
QSize size = window->size();
r = QRect(global, size);
}
else
{
r = QGuiApplication::primaryScreen()->geometry();
}
QSize s = size();
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, r));
}
}
+46
View File
@@ -0,0 +1,46 @@
#pragma once
#include <QDialog>
#include "lts_base.h"
#include "lts_widgets_export.h"
namespace LtsWidgets
{
enum class Behaviour
{
Popup = 0,
Modal,
};
class LTSWIDGETS_EXPORT LtsFramelessDialog : public QDialog
{
Q_OBJECT
public:
explicit LtsFramelessDialog(QWidget *parent = nullptr, const Behaviour &behaviour = Behaviour::Popup);
virtual ~LtsFramelessDialog();
public Q_SLOTS:
void onUpdateGeometry();
private:
QRect screenRectFromPoint(const QPoint &pos) const;
void addTouchScroll(QWidget *widget);
protected:
void showEvent(QShowEvent *event) override;
};
}
+225
View File
@@ -0,0 +1,225 @@
#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();
}
+69
View File
@@ -0,0 +1,69 @@
#pragma once
#include "lts_widgets_export.h"
#include <QObject>
class QTimer;
class QWidget;
namespace LtsWidgets
{
class LtsDialog;
class LtsOverlayLoading;
class LtsProgressDialogHelper;
class LTSWIDGETS_EXPORT LtsGlobalWaitDialog : public QObject
{
Q_OBJECT
public:
static LtsGlobalWaitDialog* getInstance();
void wait(QWidget *parent, const QString &customText = QString());
void wait(const QString &customText = QString()) { wait(nullptr, customText); }
void done();
void setVisible(bool visible = true);
void setCustomText(const QString &customText = QString());
void unarm();
void rearm();
private:
friend struct LtsGlobalWaitDialogHandler;
LtsGlobalWaitDialog();
~LtsGlobalWaitDialog();
static void cleanupGwdInstance();
void showIt();
void hideIt();
int m_waitingCount;
bool m_visible;
bool m_armed { true };
LtsProgressDialogHelper *m_progressDialog;
QTimer *m_hideTimer;
};
}
class LTSWIDGETS_EXPORT Waiter
{
public:
explicit Waiter(const QString &customText = {});
explicit Waiter(LtsWidgets::LtsDialog *parent, const QString &customText = {});
~Waiter();
private:
LtsWidgets::LtsOverlayLoading *m_loadingOverlay { nullptr };
LtsWidgets::LtsDialog *m_parent { nullptr };
bool m_oldClosableState { false };
};
+128
View File
@@ -0,0 +1,128 @@
#include "lts_grid_layout.h"
#include <QResizeEvent>
namespace LtsWidgets
{
LtsGridLayout::LtsGridLayout(LtsWidgets::ButtonSize buttonSize, QWidget *parent, int maxColumn)
: QGridLayout(parent)
, m_buttonSize(buttonSize)
, m_defaultMaxColumn(maxColumn)
, m_maxColumn(maxColumn)
, m_colSize(0)
, m_autoSize(maxColumn < 0)
{
setSizeConstraint(SizeConstraint::SetNoConstraint);
setVerticalSpacing(1);
setMargin(0);
}
void LtsGridLayout::add_widget(QWidget *widget)
{
for (auto it = m_widgetList.cbegin(); it != m_widgetList.cend(); ++it)
{
if (*it == widget)
return;
}
connect(widget, &QWidget::destroyed, this, &LtsGridLayout::onWidgetDestroyed);
addWidgetInternal(widget);
m_widgetList.push_back(widget);
}
void LtsGridLayout::setAutoSize(bool enable)
{
m_autoSize = enable;
if (m_autoSize == false)
setMaxColumn(1);
else
{
m_maxColumn = -1;
m_oldSize = QSize();
m_oldGeo = QRect();
QResizeEvent e(sizeHint(), sizeHint());
onParentResize(&e);
setGeometry(QRect(0, 0, sizeHint().width(), sizeHint().height()));
}
}
void LtsGridLayout::setMaxColumn(int max)
{
m_maxColumn = max;
m_defaultMaxColumn = max;
m_colSize = 0;
for (QWidget *wid : qAsConst(m_widgetList))
removeWidget(wid);
for (QWidget *wid : qAsConst(m_widgetList))
addWidgetInternal(wid);
}
void LtsGridLayout::addWidgetInternal(QWidget *widget)
{
int current_row = 0;
int current_column = 0;
while (QLayoutItem *item = itemAtPosition(current_row, current_column))
{
if (!item->widget())
{
removeItem(item);
continue;
}
if (current_column == (m_maxColumn - 1))
{
current_column = 0;
++current_row;
}
else
++current_column;
}
if (current_row == 0)
m_colSize += 1;
QGridLayout::addWidget(widget, current_row, current_column);
}
void LtsGridLayout::onParentResize(QResizeEvent *e)
{
if (m_autoSize && m_oldSize != e->size())
{
bool bigger = (e->size().width() > m_oldSize.width());
m_oldSize = e->size();
int newWidth = m_oldSize.width();
int maxIconsInRow = newWidth / (static_cast<int>(m_buttonSize) + 4);
if (!bigger && newWidth <= (static_cast<int>(m_buttonSize)*m_colSize - static_cast<int>(m_buttonSize) / 2))
maxIconsInRow--;
if (m_maxColumn != maxIconsInRow)
setMaxColumn(maxIconsInRow);
}
}
void LtsGridLayout::onWidgetDestroyed()
{
QWidget *s = qobject_cast<QWidget*>(sender());
for (auto it = m_widgetList.begin(); it != m_widgetList.end(); ++it)
{
if (*it == s)
{
QGridLayout::removeWidget(s);
m_widgetList.erase(it);
setMaxColumn(m_maxColumn);
break;
}
}
}
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <QGridLayout>
#include <QVector>
#include "lts_widgets_export.h"
#include "lts_base.h"
class QWidget;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsGridLayout : public QGridLayout
{
Q_OBJECT
public:
explicit LtsGridLayout(LtsWidgets::ButtonSize buttonSize, QWidget *parent = nullptr, int maxColumn = 1);
void add_widget(QWidget *widget);
void setAutoSize(bool enable);
void setMaxColumn(int max);
private:
void addWidgetInternal(QWidget *widget);
public Q_SLOTS:
void onParentResize(QResizeEvent *e);
private Q_SLOTS:
void onWidgetDestroyed();
private:
LtsWidgets::ButtonSize m_buttonSize;
int m_defaultMaxColumn;
int m_maxColumn;
int m_colSize;
QVector<QWidget *> m_widgetList;
QRect m_oldGeo;
QSize m_oldSize;
bool m_autoSize;
};
}
+621
View File
@@ -0,0 +1,621 @@
#include "lts_height_plot_widget.h"
#include <QPainter>
#include <QPainterPath>
#include <QPen>
#include <QTransform>
#include <QMouseEvent>
#include <cmath>
static inline double getLength(const QPointF &p1, const QPointF &p2)
{
const double x = p1.x() - p2.x();
const double y = p1.y() - p2.y();
return sqrt(x * x + y * y);
}
class LtsHeightPlotWidget::Private
{
public:
Private()
: m_length(0)
, m_minElevation(0)
, m_maxElevation(0)
, m_nullX(0)
, m_nullY(0)
, m_scaleX(0)
, m_scaleY(0)
, m_fillBrush(Qt::gray)
, m_axisPen(Qt::black)
, m_mousePosPen(Qt::blue)
, m_markerPen(Qt::magenta)
, iPositionHint(1)
{
m_axisPen.setWidth(1);
m_viewLinePen.setWidth(1);
m_textFont.setPixelSize(10);
m_markerPen.setWidth(2);
m_markerPen.setCapStyle(Qt::RoundCap);
m_mousePosPen.setStyle(Qt::DashDotDotLine);
m_viewLinePen.setStyle(Qt::DashLine);
}
void clearPixmap();
double getDataHeight(double pos) const;
QPointF getDataPos(double pos) const;
int findDataPointIdx(const QPointF &point) const;
void clear();
void recalcData();
void setData(const QVector<QPair<QPointF, double> > &data);
void setMarks(const QVector<QPointF> &data);
void resize(const QSize &newSize);
void repaint();
void paintLines(QPainter &p) const;
QVector< QPair< QPointF, double > > m_data;
QVector< QPointF > m_marks;
QVector< QPair< double, double > > m_heightList;
double m_length;
double m_minElevation;
double m_maxElevation;
double m_nullX;
double m_nullY;
double m_scaleX;
double m_scaleY;
QPainterPath m_drawPoints;
QBrush m_fillBrush;
QPen m_axisPen;
QPen m_viewLinePen;
QPen m_mousePosPen;
QPen m_markerPen;
QFont m_textFont;
QPointF m_mousePos;
QPointF m_mouseLeftClickPos;
QSize m_curSize;
QTransform m_trans1;
QTransform m_trans2;
QTransform m_transInverted;
QTransform m_transCombined;
QPixmap m_pixmap;
mutable int iPositionHint;
};
double LtsHeightPlotWidget::Private::getDataHeight(double pos) const
{
if (m_heightList.count() <= 1)
return 0;
if (pos <= 0.)
return m_heightList[0].second;
if (pos >= m_heightList[m_heightList.count() - 1].first)
return m_heightList[m_heightList.count() - 1].second;
if (iPositionHint >= m_heightList.size())
iPositionHint = 1;
if (pos <= m_heightList[iPositionHint].first)
{
while (iPositionHint > 1 && pos <= m_heightList[iPositionHint - 1].first)
--iPositionHint;
}
else
{
while (iPositionHint < m_heightList.count() - 1 && pos > m_heightList[iPositionHint].first)
++iPositionHint;
}
const int iFound = iPositionHint;
const double x = m_heightList[iFound].first - m_heightList[iFound - 1].first;
const double y = m_heightList[iFound].second - m_heightList[iFound - 1].second;
const double m = y / x;
const double n = m_heightList[iFound].second - m * m_heightList[iFound].first;
return m * pos + n;
}
QPointF LtsHeightPlotWidget::Private::getDataPos(double pos) const
{
if (m_heightList.count() <= 1)
return QPointF();
if (pos <= 0.)
return m_data[0].first;
if (pos >= m_heightList[m_heightList.count() - 1].first)
return m_data[m_heightList.count() - 1].first;
if (pos <= m_heightList[iPositionHint].first)
{
while (iPositionHint > 1 && pos <= m_heightList[iPositionHint - 1].first)
--iPositionHint;
}
else
{
while (iPositionHint < m_heightList.count() - 1 && pos > m_heightList[iPositionHint].first)
++iPositionHint;
}
const int iFound = iPositionHint;
const double diff = m_heightList[iFound].first - m_heightList[iFound - 1].first;
double percentile = (pos - m_heightList[iFound - 1].first) / diff;
const QPointF &p1 = m_data[iFound - 1].first;
const QPointF p2 = m_data[iFound].first - m_data[iFound - 1].first;
return QPointF(p1.x() + p2.x() * percentile, p1.y() + p2.y() * percentile);
}
int LtsHeightPlotWidget::Private::findDataPointIdx(const QPointF &point) const
{
for (int i = 0; i < m_heightList.count() - 1; ++i)
{
const double x = m_data[i + 1].first.x() - m_data[i].first.x();
const double y = m_data[i + 1].first.y() - m_data[i].first.y();
const double m = y / x;
const double n = m_data[i].first.y() - m * m_data[i].first.x();
const double yRes = m * point.x() + n;
if (fabs(yRes - point.y()) < 1.)
{
const double len = getLength(m_data[ i ].first, point);
if (len <= m_heightList[i].first)
return i;
}
}
return -1;
}
void LtsHeightPlotWidget::Private::clear()
{
m_data.clear();
m_marks.clear();
m_length = 0;
m_minElevation = 0;
m_maxElevation = 0;
m_scaleX = 0;
m_scaleY = 0;
m_drawPoints = QPainterPath();
m_heightList.clear();
m_curSize = QSize();
iPositionHint = 1;
}
void LtsHeightPlotWidget::Private::clearPixmap()
{
m_pixmap = QPixmap();
}
inline double log5(double x)
{
return log10(x) / log10(5.);
}
void LtsHeightPlotWidget::Private::recalcData()
{
m_heightList.clear();
m_drawPoints = QPainterPath();
if (m_data.isEmpty())
{
clear();
return;
}
double length = 0;
double minElevation = m_data.at(0).second;
double maxElevation = minElevation;
for (int i = 1; i < m_data.count(); ++i)
{
length += getLength(m_data.at(i - 1).first, m_data.at(i).first);
minElevation = std::min(minElevation, m_data.at(i).second);
maxElevation = std::max(maxElevation, m_data.at(i).second);
}
if (minElevation < -10000.0) minElevation = -10000.0;
if (maxElevation < -10000.0) maxElevation = -10000.0;
if (minElevation > 10000.0) minElevation = 10000.0;
if (maxElevation > 10000.0) maxElevation = 10000.0;
if (qFuzzyCompare(minElevation, maxElevation))
{
minElevation -= 1.0;
maxElevation += 1.0;
}
double n2 = pow(5, floor(log5(fabs(minElevation))) - 1);
if (qFuzzyIsNull(n2))
n2 = 0.1;
m_minElevation = lrint(floor(minElevation / n2) * n2);
m_maxElevation = lrint(ceil(maxElevation / n2) * n2);
m_scaleY = pow(10, floor(log10(m_maxElevation - m_minElevation)) - 1);
if (m_scaleY < 0.1)
m_scaleY = 0.1;
m_nullY = m_minElevation;
if (m_minElevation < 0 && m_maxElevation > 0)
m_nullY = 0;
const double n = pow(10, floor(log10(length))) / 2;
m_length = lrint(ceil(length / n) * n);
m_scaleX = pow(10, floor(log10(length)) - 1);
if (m_scaleX < 0.1)
m_scaleX = 0.1;
m_nullX = 0;
double len = 0;
m_drawPoints.moveTo(len, m_data.at(0).second);
m_heightList.append(QPair<double, double>(len, m_data.at(0).second));
for (int i = 1; i < m_data.count(); ++i)
{
len += getLength(m_data.at(i - 1).first, m_data.at(i).first);
m_drawPoints.lineTo(len, m_data.at(i).second);
m_heightList.append(QPair<double, double>(len, m_data.at(i).second));
}
m_drawPoints.lineTo(len, m_minElevation);
m_drawPoints.lineTo(0, m_minElevation);
m_drawPoints.setFillRule(Qt::WindingFill);
}
void LtsHeightPlotWidget::Private::setData(const QVector< QPair< QPointF, double > > &data)
{
if (data.isEmpty())
{
clear();
return;
}
QSize tmp = m_curSize;
clear();
m_data = data;
recalcData();
resize(tmp);
}
void LtsHeightPlotWidget::Private::setMarks(const QVector< QPointF > &data)
{
m_marks = data;
recalcData();
repaint();
}
void LtsHeightPlotWidget::Private::resize(const QSize &newSize)
{
if (newSize == m_curSize)
return;
m_curSize = newSize;
const int border = 25;
const double width = m_curSize.width();
const double height = m_curSize.height();
const double minY = m_minElevation - m_scaleY;
const double maxY = m_maxElevation + m_scaleY;
const double wertebereichY = maxY - minY;
const double minX = 0 - m_scaleX;
const double maxX = m_length + m_scaleX;
const double wertebereichX = maxX - minX;
m_trans1.reset();
m_trans2.reset();
m_trans1.translate(10, height);
m_trans1.scale(1, -1);
m_trans1.translate(border, border);
m_trans1.scale(1, -1);
m_trans2.scale((width - 2 * border) / (wertebereichX),
(height - 2 * border) / (wertebereichY));
m_trans2.translate(0, minY);
m_trans2.scale(1, -1);
m_transInverted = m_trans1.inverted() * m_trans2.inverted();
m_transCombined = m_trans2 * m_trans1;
repaint();
}
void LtsHeightPlotWidget::Private::repaint()
{
if (!m_curSize.isValid())
return;
if (!m_heightList.count())
return;
QImage img(m_curSize, QImage::Format_ARGB32);
img.fill(Qt::transparent);
QPainter p(&img);
const QPainter::RenderHints hints = QPainter::HighQualityAntialiasing |
QPainter::SmoothPixmapTransform |
QPainter::TextAntialiasing |
QPainter::Antialiasing;
p.setRenderHints(hints);
p.setTransform(m_trans1);
p.setPen(QPen(m_fillBrush, 0.1));
p.setBrush(m_fillBrush);
p.drawPath(m_trans2.map(m_drawPoints));
p.setRenderHint(QPainter::Antialiasing, false);
p.setPen(m_markerPen);
for (int i = 0; i < m_marks.count(); ++i)
{
int posIdx = findDataPointIdx(m_marks.at(i));
if (posIdx < 0)
continue;
double len = getLength(m_data.at(posIdx).first, m_marks.at(i));
len += m_heightList.at(posIdx).first;
const double height = getDataHeight(len);
const QLineF l(len, m_minElevation, len, height);
p.drawLine(m_trans2.map(l));
}
p.setPen(m_axisPen);
p.setFont(m_textFont);
p.drawLine(m_trans2.map(QPointF(m_nullX, m_minElevation - m_scaleY)),
m_trans2.map(QPointF(m_nullX, m_maxElevation + m_scaleY)));
for (double i = m_minElevation; i <= m_maxElevation; i += m_scaleY)
{
const qreal y = m_trans2.map(QPointF(0, i)).y();
p.drawLine(QLineF(-2, y, 2, y));
}
for (double i = m_minElevation; i <= m_maxElevation; i += m_scaleY * 5)
{
const qreal y = m_trans2.map(QPointF(0, i)).y();
p.drawLine(QLineF(-4, y, 4, y));
}
QFontMetricsF fm(m_textFont);
for (double i = m_minElevation; i <= m_maxElevation; i += m_scaleY * 5)
{
if (qFuzzyCompare(i, m_nullY))
continue;
const qreal y = m_trans2.map(QPointF(m_nullX, i)).y();
const QPointF p1(-20, y);
const QString str = QString::number(i);
QRectF r = fm.boundingRect(str);
r.setWidth(fm.width(str));
r.moveTo(p1.x() - r.width() / 2., p1.y() - r.height() / 2.);
p.drawText(r, str, Qt::AlignHCenter | Qt::AlignVCenter);
}
p.drawLine(m_trans2.map(QPointF(-m_scaleX, m_nullY)),
m_trans2.map(QPointF(m_scaleX + m_length, m_nullY)));
for (double i = m_scaleX; i <= m_length; i += m_scaleX)
{
const QPointF point = m_trans2.map(QPointF(i, m_nullY));
p.drawLine(QLineF(point.x(), point.y() - 2, point.x(), point.y() + 2));
}
for (double i = 0; i <= m_length; i += m_scaleX * 5)
{
const QPointF point = m_trans2.map(QPointF(i, m_nullY));
p.drawLine(QLineF(point.x(), point.y() - 4, point.x(), point.y() + 4));
}
for (double i = 0; i <= m_length; i += m_scaleX * 5)
{
if (qFuzzyCompare(i, m_nullX))
continue;
const QPointF point = m_trans2.map(QPointF(i, m_nullY));
const QPointF p1(point.x(), point.y() + 15);
const QString str = QString::number(i);
QRectF r = fm.boundingRect(str);
r.setWidth(fm.width(str));
r.moveTo(p1.x() - r.width() / 2., p1.y() - r.height() / 2.);
p.drawText(r, str, Qt::AlignHCenter | Qt::AlignVCenter);
}
p.end();
m_pixmap = QPixmap::fromImage(img);
}
void LtsHeightPlotWidget::Private::paintLines(QPainter &p) const
{
if (m_heightList.count() > 0)
{
QPointF pos = m_mousePos;
if (pos.x() < 0)
pos.setX(0);
if (pos.x() > m_heightList.at(m_heightList.count() - 1).first)
pos.setX(m_heightList.at(m_heightList.count() - 1).first);
const double curHeight = getDataHeight(pos.x());
p.setPen(m_mousePosPen);
p.drawLine(m_transCombined.map(QLineF(m_nullX, curHeight, pos.x(), curHeight)));
p.drawLine(m_transCombined.map(QLineF(pos.x(), m_nullY, pos.x(), curHeight)));
if (!m_mouseLeftClickPos.isNull())
{
const double y = curHeight > pos.y() ? curHeight : pos.y();
p.drawLine(m_transCombined.map(QLineF(m_nullX, y, pos.x(), y)));
p.drawLine(m_transCombined.map(QLineF(pos.x(), m_nullY, pos.x(), y)));
p.setPen(m_viewLinePen);
const QPointF &c = m_mouseLeftClickPos;
p.drawLine(m_transCombined.map(QLineF(m_nullX, c.y(), c.x(), c.y())));
p.drawLine(m_transCombined.map(QLineF(c.x(), m_nullY, c.x(), c.y())));
const QLineF line(m_mouseLeftClickPos, QPointF(pos.x(), y));
p.drawLine(m_transCombined.map(line));
}
}
}
LtsHeightPlotWidget::LtsHeightPlotWidget(QWidget *parent)
: QWidget(parent)
, d(new Private)
{
setMinimumSize(300, 300);
resize(size());
setMouseTracking(true);
}
LtsHeightPlotWidget::~LtsHeightPlotWidget()
{
delete d;
}
void LtsHeightPlotWidget::clearView()
{
d->clearPixmap();
update();
}
void LtsHeightPlotWidget::setData(const QVector< QPair< QPointF, double > > &data)
{
d->setData(data);
update();
}
void LtsHeightPlotWidget::setMarks(const QVector<QPointF> &data)
{
d->setMarks(data);
}
void LtsHeightPlotWidget::setBackgroundBrush(const QBrush &brush)
{
QPalette pal = palette();
pal.setBrush(QPalette::Background, brush);
setPalette(pal);
}
void LtsHeightPlotWidget::setTextFont(const QFont &f)
{
d->m_textFont = f;
d->repaint();
}
void LtsHeightPlotWidget::setAxisPen(const QPen &pen)
{
d->m_axisPen = pen;
d->repaint();
}
void LtsHeightPlotWidget::setPositionPen(const QPen &pen)
{
d->m_mousePosPen = pen;
}
void LtsHeightPlotWidget::setViewLinePen(const QPen &pen)
{
d->m_viewLinePen = pen;
}
void LtsHeightPlotWidget::setContourBrush(const QBrush &brush)
{
d->m_fillBrush = brush;
d->repaint();
}
void LtsHeightPlotWidget::setMarkerPen(const QPen &pen)
{
d->m_markerPen = pen;
d->repaint();
}
void LtsHeightPlotWidget::resizeEvent(QResizeEvent *e)
{
d->resize(size());
QWidget::resizeEvent(e);
}
void LtsHeightPlotWidget::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
QPainter p(this);
const QPainter::RenderHints hints = QPainter::SmoothPixmapTransform |
QPainter::TextAntialiasing |
QPainter::Antialiasing;
p.setRenderHints(hints);
p.drawPixmap(0, 0, d->m_pixmap);
d->paintLines(p);
p.end();
}
void LtsHeightPlotWidget::mouseMoveEvent(QMouseEvent *e)
{
QWidget::mouseMoveEvent(e);
if (!d->m_heightList.count())
return;
const QPointF pos = d->m_transInverted.map(e->localPos());
emit mousePositionChanged(d->getDataPos(pos.x()), d->getDataHeight(pos.x()), pos.y());
d->m_mousePos = pos;
update();
}
void LtsHeightPlotWidget::mouseReleaseEvent(QMouseEvent *e)
{
QWidget::mouseReleaseEvent(e);
if (!d->m_heightList.count())
return;
if (e->button() == Qt::LeftButton)
{
const QPointF &pos = d->m_mousePos;
if (pos.x() < 0)
return;
if (pos.x() > d->m_heightList.at(d->m_heightList.count() - 1).first)
return;
const double curHeight = d->getDataHeight(pos.x());
d->m_mouseLeftClickPos = QPointF(pos.x(), curHeight > pos.y() ? curHeight : pos.y());
emit startLineOfSight(d->getDataPos(pos.x()));
}
else if (e->button() == Qt::RightButton)
{
d->m_mouseLeftClickPos = QPointF();
emit stopLineOfSight();
update();
}
}
+69
View File
@@ -0,0 +1,69 @@
#pragma once
#include <QWidget>
#include <QtCore/QVector>
#include <QtCore/QPointF>
#include <QtCore/QPair>
#include "lts_widgets_export.h"
class LTSWIDGETS_EXPORT LtsHeightPlotWidget final : public QWidget
{
Q_OBJECT
public:
explicit LtsHeightPlotWidget(QWidget *parent = nullptr);
virtual ~LtsHeightPlotWidget();
void clearView();
void setData(const QVector<QPair<QPointF, double> > &data);
void setMarks(const QVector<QPointF> &data);
void setBackgroundBrush(const QBrush &brush);
void setTextFont(const QFont &f);
void setAxisPen(const QPen &pen);
void setPositionPen(const QPen &pen);
void setViewLinePen(const QPen &pen);
void setContourBrush(const QBrush &brush);
void setMarkerPen(const QPen &pen);
Q_SIGNALS:
void mousePositionChanged(const QPointF &curPoint, double curHeight, double mouseHeight);
void startLineOfSight(const QPointF &startPoint);
void stopLineOfSight();
protected:
void resizeEvent(QResizeEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
class Private;
Private *const d;
};
+116
View File
@@ -0,0 +1,116 @@
#include "lts_image_editor.h"
#include <QPainter>
#include <QPaintEvent>
#include <QBrush>
#include <QPen>
#include <QRect>
#include <QEvent>
using namespace LtsWidgets;
LtsImageEditor::LtsImageEditor(QWidget *parent)
: QWidget(parent)
, m_isHovered(false)
, m_menuEnabled(true)
, m_bDrawOuterRect(true)
{}
void LtsImageEditor::setPixmap(const QPixmap &pixmap)
{
if (pixmap.isNull())
m_pixmap = QPixmap(QStringLiteral(":style/noimage.png"));
else
m_pixmap = pixmap;
update();
emit imageChanged();
}
void LtsImageEditor::enterEvent(QEvent *)
{
m_isHovered = true;
update();
}
void LtsImageEditor::leaveEvent(QEvent *)
{
m_isHovered = false;
update();
}
bool LtsImageEditor::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress && m_menuEnabled)
{
emit signalClicked();
event->accept();
m_isHovered = false;
update();
return true;
}
return QWidget::event(event);
}
void LtsImageEditor::paintEvent(QPaintEvent* event)
{
QPainter p(this);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
QBrush brush = QColor(QStringLiteral("white"));
if (!m_pixmap.isNull())
{
if (!(m_isHovered && m_menuEnabled))
{
const QSize s(size());
const QPixmap pixmap(m_pixmap.scaled(s, Qt::KeepAspectRatio, Qt::SmoothTransformation));
const int x = qRound((s.width() - pixmap.width()) / 2.);
const int y = qRound((s.height() - pixmap.height()) / 2.);
if (m_bDrawOuterRect)
{
p.setPen(QPen(QColor("gray"), 2));
p.drawRect(rect());
}
p.drawPixmap(x, y, pixmap);
event->accept();
return;
}
}
p.setPen(QPen(QColor("gray"), 2));
p.setBrush(brush);
p.drawRect(rect());
if (m_isHovered && m_menuEnabled)
{
p.setPen(QPen(QColor(QStringLiteral("gray")), (size().height() / 48 * 2)));
double xc = size().width()/2.012;
double yc = size().height()/2.012;
p.drawLine(QPointF(xc - (xc/2.01f), yc - (yc/3.01f)), QPointF(xc + (xc/2.02f), yc - (yc/3.02f)));
p.drawLine(QPointF(xc - (xc/2.01f), yc - 0.01f), QPointF(xc + (xc/2.02f), yc - 0));
p.drawLine(QPointF(xc - (xc/2.01f), yc + (yc/3.01f)), QPointF(xc + (xc/2.02f), yc + (yc/3.02f)));
}
event->accept();
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include "lts_widgets_export.h"
#include <QWidget>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsImageEditor : public QWidget
{
Q_OBJECT
Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)
Q_PROPERTY(bool menuEnabled READ isMenuEnabled WRITE setMenuEnabled)
public:
explicit LtsImageEditor(QWidget *parent = nullptr);
void setPixmap(const QPixmap &pixmap);
QPixmap pixmap() const { return m_pixmap; }
void setMenuEnabled(bool enabled = true) { m_menuEnabled = enabled; }
bool isMenuEnabled() const { return m_menuEnabled; }
void setDrawOuterRect(bool bDraw) { m_bDrawOuterRect = bDraw; }
bool drawOuterRect() const { return m_bDrawOuterRect; }
protected:
void paintEvent(QPaintEvent *event);
void enterEvent(QEvent *);
void leaveEvent(QEvent *);
bool event(QEvent *event);
private:
QPixmap m_pixmap;
bool m_isHovered;
bool m_menuEnabled;
bool m_bDrawOuterRect;
signals:
void signalClicked();
void imageChanged();
};
}
+81
View File
@@ -0,0 +1,81 @@
#include "lts_info_dialog.h"
#include "ui_lts_info_dialog.h"
#include <QPixmap>
#include <QFile>
#include <QDebug>
#ifndef LTS_VERSION_MAJOR
#define LTS_VERSION_MAJOR "undefined"
#endif
#ifndef LTS_VERSION_MINOR
#define LTS_VERSION_MINOR "undefined"
#endif
#ifndef LTS_VERSION_PATCH
#define LTS_VERSION_PATCH "undefined"
#endif
#ifndef LTS_VERSION_DATE
#define LTS_VERSION_DATE "undefined"
#endif
#ifndef JENKINS_BUILD_NUMBER
#define JENKINS_BUILD_NUMBER "unknown"
#endif
static const char ver_major[] = LTS_VERSION_MAJOR;
static const char ver_minor[] = LTS_VERSION_MINOR;
static const char ver_patch[] = LTS_VERSION_PATCH;
static const char ver_date[] = LTS_VERSION_DATE;
static const char ver_jenkins[] = JENKINS_BUILD_NUMBER;
namespace LtsWidgets
{
LtsInfoDialog::LtsInfoDialog(QWidget *parent)
: LtsFramelessDialog(parent)
, m_ui(new Ui::LtsInfoDialog)
{
m_ui->setupUi(this);
QFont f = font();
f.setBold(true);
m_ui->lblVersion->setFont(f);
m_ui->lblDate->setFont(f);
const QString versionString = QStringLiteral("%1.%2-%3 (rev: %4)")
.arg(QString::fromLatin1(ver_major),
QString::fromLatin1(ver_minor),
QString::fromLatin1(ver_jenkins),
QString::fromLatin1(ver_patch));
m_ui->lblVersion->setText(versionString);
m_ui->lblDate->setText(QString::fromLatin1(ver_date));
QString projectLogoFilename(QStringLiteral(":project/login_logo.png"));
if (!QFile(projectLogoFilename).exists())
projectLogoFilename = QStringLiteral(":/project/logo.png");
QPixmap pixmap(projectLogoFilename);
if (pixmap.isNull())
{
qWarning() << "LtsInfoDialog: project logo missing or is not an valid image " << projectLogoFilename;
}
else
{
int max = m_ui->lblProjectLogo->maximumHeight();
pixmap = pixmap.scaled(999, max * 0.85f, Qt::KeepAspectRatio, Qt::SmoothTransformation);
m_ui->lblProjectLogo->setPixmap(pixmap);
}
connect(m_ui->pbClose, &QPushButton::clicked, this, &LtsInfoDialog::close);
}
LtsInfoDialog::~LtsInfoDialog()
{
delete m_ui;
}
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include "lts_frameless_dialog.h"
#include "lts_widgets_export.h"
namespace Ui
{
class LtsInfoDialog;
}
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsInfoDialog : public LtsFramelessDialog
{
Q_OBJECT
public:
explicit LtsInfoDialog(QWidget *parent = nullptr);
~LtsInfoDialog();
private:
Ui::LtsInfoDialog *m_ui;
};
}
+135
View File
@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsInfoDialog</class>
<widget class="QWidget" name="LtsInfoDialog">
<property name="windowTitle">
<string>Operator Menu</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="label">
<property name="text">
<string>Rheinmetall Electronics GmbH</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>450</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>450</width>
<height>200</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>:/rde_komplett.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblProjectLogo">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="text">
<string notr="true">&lt;Project Logo&gt;</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Version:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblVersion">
<property name="text">
<string notr="true">?</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Date:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lblDate">
<property name="text">
<string notr="true">?</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item alignment="Qt::AlignRight">
<widget class="QPushButton" name="pbClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+148
View File
@@ -0,0 +1,148 @@
#include "lts_led_widget.h"
#include <QPainter>
#include <QPropertyAnimation>
#include <QResizeEvent>
namespace LtsWidgets
{
void LtsLedWidget::resizeEvent(QResizeEvent *event)
{
switch (m_aspectHint) {
case AspectHint::NoHint:
{
QWidget::resizeEvent(event);
break;
}
case AspectHint::HeightIsWidth:
setMinimumHeight(event->size().width());
setMaximumHeight(event->size().width());
setMinimumWidth(0);
setMaximumWidth(65000);
break;
case AspectHint::WidthIsHeight:
setMinimumHeight(0);
setMaximumHeight(65000);
setMinimumWidth(event->size().height());
setMaximumWidth(event->size().height());
break;
}
}
static constexpr double GRADIENT_KEY_LOWER = 0.3;
static constexpr double GRADIENT_KEY_UPPER = 0.9;
static constexpr int GRADIENT_VALUE_LOWER = 125;
static constexpr int GRADIENT_VALUE_UPPER = 165;
static constexpr double GRADIENT_CENTER_OFFSET = 5.0;
static constexpr double GRADIENT_FOCALPOINT_OFFSET = 2.7;
static constexpr double PERCENTAGE_OF_BORDER = 0.1;
static constexpr int DARK_FACTOR = 200;
LtsLedWidget::LtsLedWidget(QWidget *parent, const QColor &oncolor, const QColor &offcolor, bool useGradient, int animtime)
: QWidget(parent)
, m_status(true)
, m_oncolor(oncolor)
, m_offcolor(offcolor)
, m_currentcolor(oncolor)
, m_gradient(useGradient)
, m_animTime(animtime)
{
setObjectName(QString::fromUtf8("LtsLedWidget"));
}
void LtsLedWidget::paintEvent(QPaintEvent *pe)
{
Q_UNUSED(pe);
QPainter p;
p.begin(this);
p.setOpacity(QWidget::isEnabled() ? 1.00 : 0.5);
int minSize = height() > width() ? width() : height();
if (m_gradient)
{
QRadialGradient grad(QPointF(width(), height()) / GRADIENT_CENTER_OFFSET,
minSize,
QPointF(width(), height()) / GRADIENT_FOCALPOINT_OFFSET);
grad.setColorAt(GRADIENT_KEY_LOWER, m_currentcolor.lighter(GRADIENT_VALUE_LOWER));
grad.setColorAt(GRADIENT_KEY_UPPER, m_currentcolor.darker(GRADIENT_VALUE_UPPER));
p.setBrush(grad);
}
else
p.setBrush(QBrush(m_currentcolor, Qt::SolidPattern));
p.setRenderHint(QPainter::Antialiasing);
p.setPen(QPen(Qt::black, PERCENTAGE_OF_BORDER * minSize, Qt::SolidLine, Qt::SquareCap));
p.drawEllipse(QPointF(width(), height()) / 2.0,
width() / (2.0 * (1.00 + PERCENTAGE_OF_BORDER)),
height() / (2.0 * (1.00 + PERCENTAGE_OF_BORDER)));
p.end();
}
void LtsLedWidget::animate()
{
QPropertyAnimation *anim = new QPropertyAnimation(this, "currentcolor");
anim->setDuration(m_animTime);
anim->setEasingCurve(QEasingCurve::OutBack);
anim->setStartValue(m_currentcolor);
anim->setEndValue(m_status ? m_oncolor : m_offcolor == Qt::black ? m_oncolor.darker(DARK_FACTOR) : m_offcolor);
anim->start(QPropertyAnimation::DeleteWhenStopped);
}
void LtsLedWidget::setStatus(bool status)
{
if (m_status == status)
return;
m_status = status;
animate();
}
void LtsLedWidget::setUseGradient(bool useGradient)
{
if (m_gradient == useGradient)
return;
m_gradient = useGradient;
repaint();
}
void LtsLedWidget::setColor(const QColor &oncolor, const QColor &offcolor)
{
setOnColor(oncolor);
setOffColor(offcolor);
}
void LtsLedWidget::setOnColor(const QColor &oncolor)
{
if (m_oncolor == oncolor)
return;
m_oncolor = oncolor;
if (m_status)
animate();
}
void LtsLedWidget::setOffColor(const QColor &offcolor)
{
if (m_offcolor == offcolor)
return;
m_offcolor = offcolor;
if (!m_status)
animate();
}
void LtsLedWidget::setCurrentColor(const QColor &currentcolor)
{
if (m_currentcolor == currentcolor)
return;
m_currentcolor = currentcolor;
repaint();
}
}
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#include <QWidget>
#include "lts_widgets_export.h"
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsLedWidget : public QWidget
{
Q_OBJECT
public:
enum class AspectHint
{
WidthIsHeight,
NoHint,
HeightIsWidth
};
Q_ENUM(AspectHint)
Q_PROPERTY(QColor oncolor READ onColor WRITE setOnColor)
Q_PROPERTY(QColor offcolor READ offColor WRITE setOffColor)
Q_PROPERTY(bool status READ status WRITE setStatus)
Q_PROPERTY(bool usesGradient READ usesGradient WRITE setUseGradient)
Q_PROPERTY(int animTime READ animTime WRITE setAnimTime)
Q_PROPERTY(AspectHint aspectHint READ aspectHint WRITE setAspectHint)
Q_PROPERTY(QColor currentcolor READ currentColor WRITE setCurrentColor DESIGNABLE false)
explicit LtsLedWidget(QWidget *parent = nullptr, const QColor &oncolor = Qt::red, const QColor &offcolor = Qt::black, bool useGradient = true, int animtime = 0);
void paintEvent(QPaintEvent *pe);
void setAnimTime(int time) { m_animTime = time; }
int animTime() const { return m_animTime; }
bool status() const { return m_status; }
void setUseGradient(bool useGradient);
bool usesGradient() const { return m_gradient; }
void setOnColor(const QColor &oncolor);
QColor onColor() const { return m_oncolor; }
void setOffColor(const QColor &offcolor);
QColor offColor() const { return m_offcolor; }
void setColor(const QColor &oncolor, const QColor &offcolor = Qt::black);
QColor currentColor() const { return m_currentcolor; }
void resizeEvent(QResizeEvent *event);
AspectHint aspectHint() const { return m_aspectHint; }
public slots:
void setStatus(bool status);
void setAspectHint(AspectHint aspectHint)
{
m_aspectHint = aspectHint;
}
private:
void setCurrentColor(const QColor &currentcolor);
void animate();
bool m_status;
QColor m_oncolor;
QColor m_offcolor;
QColor m_currentcolor;
bool m_gradient;
int m_animTime;
AspectHint m_aspectHint = AspectHint::NoHint;
};
}
+133
View File
@@ -0,0 +1,133 @@
#include "lts_message_dialog.h"
#include "lts_message_dialog_helper.h"
#include <QCoreApplication>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QDebug>
namespace LtsWidgets
{
namespace LtsMessageDialog
{
Button showMessage(QWidget* parent,
const QString& message,
const QString &title,
const Behaviour behaviour,
const Buttons buttons,
const QHash<Button, QString> &buttonTexts)
{
static QAtomicInt s_used = 0;
if (s_used)
qDebug() << "LtsMessageDialog: showMessage called while showMessage is in its Event Loop - do not open more than one Dialog at once !!";
s_used = 1;
LtsMessageDialogHelper *dialog = new LtsMessageDialogHelper();
Button result = dialog->showMessage(parent, message, title, behaviour, buttons, buttonTexts);
dialog->deleteLater();
s_used = 0;
return result;
}
Button askApplyDiscardCancel(QWidget *parent)
{
const QString question = QCoreApplication::translate("LtsDialog",
"<br>"
"Apply - apply changes and close.<br>"
"Discard - discard changes and close.<br>"
"Cancel - do not close.");
const QString title = QCoreApplication::translate("LtsDialog", "Unapplied changes made. Apply the changes?");
return LtsMessageDialog::showMessage(parent,
question,
title,
Behaviour::Modal,
Button::Apply | Button::Discard | Button::Cancel);
}
}
LtsMessageDialogNew::LtsMessageDialogNew(QWidget *parent, const QString &message, const QString &title, const Behaviour behaviour, const Buttons buttons, const QHash<Button, QString> &buttonTexts, bool deleteOnClose)
{
m_dialog = new LtsFramelessDialog(parent, behaviour);
if (deleteOnClose)
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(m_dialog, &LtsFramelessDialog::destroyed,
this, &LtsMessageDialogNew::deleteLater);
QVBoxLayout *mainLayout = new QVBoxLayout(m_dialog);
QString text;
if (!title.isEmpty())
{
text = QStringLiteral("<b>%1</b><br><br>").arg(title);
}
text += message;
QLabel *messageLabel = new QLabel(text, m_dialog);
messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
mainLayout->addWidget(messageLabel);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->setMargin(0);
if (buttons.testFlag(Button::Ok))
connect(addButton(buttonTexts.value(Button::Ok, tr("Ok")), buttonLayout, m_dialog, Button::Ok, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::ok);
if (buttons.testFlag(Button::Yes))
connect(addButton(buttonTexts.value(Button::Yes, tr("Yes")), buttonLayout, m_dialog, Button::Yes, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::yes);
if (buttons.testFlag(Button::No))
connect(addButton(buttonTexts.value(Button::No, tr("No")), buttonLayout, m_dialog, Button::No, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::no);
if (buttons.testFlag(Button::Apply))
connect(addButton(buttonTexts.value(Button::Apply, tr("Apply")), buttonLayout, m_dialog, Button::Apply, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::apply);
if (buttons.testFlag(Button::Discard))
connect(addButton(buttonTexts.value(Button::Discard, tr("Discard")), buttonLayout, m_dialog, Button::Discard, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::discard);
if (buttons.testFlag(Button::Cancel))
connect(addButton(buttonTexts.value(Button::Cancel, tr("Cancel")), buttonLayout, m_dialog, Button::Cancel, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::cancel);
QWidget *buttonLayoutWidget = new QWidget;
buttonLayoutWidget->setLayout(buttonLayout);
mainLayout->addWidget(buttonLayoutWidget);
m_dialog->show();
m_dialog->raise();
}
QPushButton* LtsMessageDialogNew::addButton(const QString &text, QHBoxLayout *thatLayout, LtsFramelessDialog *dialog, const Button &button, QWidget *parent)
{
QPushButton* btn = new QPushButton(text, parent);
connect(btn, &QPushButton::clicked, dialog, &LtsFramelessDialog::accept);
thatLayout->addWidget(btn);
if (button == Button::Ok ||
button == Button::Cancel)
{
btn->setDefault(true);
}
return btn;
}
}
+86
View File
@@ -0,0 +1,86 @@
#pragma once
#include "lts_widgets_export.h"
#include "lts_frameless_dialog.h"
#include <QString>
#include <QHash>
class QWidget;
class QHBoxLayout;
namespace LtsWidgets
{
enum class Button
{
UNKNOWN = 0,
Ok = 1,
Yes = 2,
No = 4,
Cancel = 8,
Apply = 16,
Discard = 32,
};
Q_DECLARE_FLAGS(Buttons, Button)
inline uint qHash(LtsWidgets::Button b)
{
return ::qHash(static_cast<int>(b));
}
namespace LtsMessageDialog
{
LTSWIDGETS_EXPORT Button showMessage(QWidget* parent,
const QString &message,
const QString &title = QString(),
const Behaviour behaviour = Behaviour::Modal,
const Buttons buttons = Button::Ok,
const QHash<Button, QString> &buttonTexts = QHash<Button, QString>());
LTSWIDGETS_EXPORT Button askApplyDiscardCancel(QWidget *parent);
}
class LTSWIDGETS_EXPORT LtsMessageDialogNew : public QObject
{
Q_OBJECT
public:
explicit LtsMessageDialogNew(QWidget* parent,
const QString &message,
const QString &title = QString(),
const Behaviour behaviour = Behaviour::Modal,
const Buttons buttons = Button::Ok,
const QHash<Button, QString> &buttonTexts = QHash<Button, QString>(),
bool deleteOnClose = true );
private:
LtsFramelessDialog *m_dialog;
QPushButton *addButton(const QString &text, QHBoxLayout *thatLayout, LtsFramelessDialog *dialog, const Button &button, QWidget *parent);
signals:
void ok();
void yes();
void no();
void apply();
void discard();
void cancel();
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(LtsWidgets::Buttons)
+155
View File
@@ -0,0 +1,155 @@
#include "lts_message_dialog_helper.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QEventLoop>
namespace LtsWidgets
{
LtsMessageDialogHelper::LtsMessageDialogHelper(QObject *parent)
: QObject(parent)
, m_result(Button::Cancel)
, m_dialog(nullptr)
{}
Button LtsMessageDialogHelper::showMessage(QWidget *parent,
const QString &message,
const QString &title,
Behaviour behaviour,
Buttons buttons,
const QHash<Button, QString> &buttonTexts)
{
m_dialog = new LtsFramelessDialog(parent, behaviour);
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout *mainLayout = new QVBoxLayout(m_dialog);
QString text;
if (!title.isEmpty())
{
text = QStringLiteral("<b>%1</b><br><br>").arg(title);
}
text += message;
QLabel *messageLabel = new QLabel(text, m_dialog);
messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
mainLayout->addWidget(messageLabel);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->setMargin(0);
connect(m_dialog, &LtsFramelessDialog::rejected, this, &LtsMessageDialogHelper::slotCancel);
if (buttons.testFlag(Button::Ok))
connect(addButton(buttonTexts.value(Button::Ok, tr("Ok")), buttonLayout, m_dialog, Button::Ok, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotOkay);
if (buttons.testFlag(Button::Yes))
connect(addButton(buttonTexts.value(Button::Yes, tr("Yes")), buttonLayout, m_dialog, Button::Yes, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotYes);
if (buttons.testFlag(Button::No))
connect(addButton(buttonTexts.value(Button::No, tr("No")), buttonLayout, m_dialog, Button::No, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotNo);
if (buttons.testFlag(Button::Apply))
connect(addButton(buttonTexts.value(Button::Apply, tr("Apply")), buttonLayout, m_dialog, Button::Apply, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotApply);
if (buttons.testFlag(Button::Discard))
connect(addButton(buttonTexts.value(Button::Discard, tr("Discard")), buttonLayout, m_dialog, Button::Discard, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotDiscard);
if (buttons.testFlag(Button::Cancel))
connect(addButton(buttonTexts.value(Button::Cancel, tr("Cancel")), buttonLayout, m_dialog, Button::Cancel, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotCancel);
QWidget *buttonLayoutWidget = new QWidget;
buttonLayoutWidget->setLayout(buttonLayout);
mainLayout->addWidget(buttonLayoutWidget);
m_dialog->show();
m_dialog->raise();
QEventLoop loop;
connect(this, &LtsMessageDialogHelper::signalQuitEventLoop, &loop, &QEventLoop::quit, Qt::QueuedConnection);
loop.exec();
return m_result;
}
void LtsMessageDialogHelper::slotOkay()
{
m_dialog->hide();
m_result = Button::Ok;
emit signalQuitEventLoop();
}
void LtsMessageDialogHelper::slotYes()
{
m_dialog->hide();
m_result = Button::Yes;
emit signalQuitEventLoop();
}
void LtsMessageDialogHelper::slotNo()
{
m_dialog->hide();
m_result = Button::No;
emit signalQuitEventLoop();
}
void LtsMessageDialogHelper::slotApply()
{
m_dialog->hide();
m_result = Button::Apply;
emit signalQuitEventLoop();
}
void LtsMessageDialogHelper::slotDiscard()
{
m_dialog->hide();
m_result = Button::Discard;
emit signalQuitEventLoop();
}
void LtsMessageDialogHelper::slotCancel()
{
m_dialog->hide();
m_result = Button::Cancel;
emit signalQuitEventLoop();
}
QPushButton* LtsMessageDialogHelper::addButton(const QString &text, QHBoxLayout *thatLayout, LtsFramelessDialog *dialog, const Button &button, QWidget *parent)
{
QPushButton* btn = new QPushButton(text, parent);
connect(btn, &QPushButton::clicked, dialog, &LtsFramelessDialog::accept);
thatLayout->addWidget(btn);
if (button == Button::Ok ||
button == Button::Cancel)
{
btn->setDefault(true);
}
return btn;
}
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include "lts_frameless_dialog.h"
#include "lts_message_dialog.h"
#include <QHash>
#include <QObject>
#include <QString>
class QPushButton;
class QHBoxLayout;
namespace LtsWidgets
{
class LtsMessageDialogHelper : public QObject
{
Q_OBJECT
public:
explicit LtsMessageDialogHelper(QObject *parent = nullptr);
~LtsMessageDialogHelper() = default;
Button showMessage(QWidget *parent,
const QString &message,
const QString &title,
Behaviour behaviour,
LtsWidgets::Buttons buttons,
const QHash<Button, QString> &buttonTexts);
private:
QPushButton *addButton(const QString &text, QHBoxLayout *thatLayout, LtsFramelessDialog *dialog, const Button &button, QWidget *parent);
Button m_result;
LtsFramelessDialog *m_dialog;
private slots:
void slotOkay();
void slotYes();
void slotNo();
void slotCancel();
void slotApply();
void slotDiscard();
signals:
void signalQuitEventLoop();
};
}
+114
View File
@@ -0,0 +1,114 @@
#include "lts_msec_date_time_edit.h"
namespace LtsWidgets
{
LtsMSecDateTimeEdit::LtsMSecDateTimeEdit(QWidget *parent)
: QDateTimeEdit(parent)
{
setWrapping(true);
setDisplayFormat(QLatin1String("dd.MM.yy HH:mm:ss.zzz"));
connect(this, &LtsMSecDateTimeEdit::editingFinished, this, &LtsMSecDateTimeEdit::onEditingFinished);
}
LtsMSecDateTimeEdit::LtsMSecDateTimeEdit(const QDateTime &dt, QWidget *parent)
: QDateTimeEdit(dt, parent)
{
setWrapping(true);
setDisplayFormat(QLatin1String("dd.MM.yy HH:mm:ss.zzz"));
connect(this, &LtsMSecDateTimeEdit::editingFinished, this, &LtsMSecDateTimeEdit::onEditingFinished);
}
LtsMSecDateTimeEdit::LtsMSecDateTimeEdit(const QDate &d, QWidget *parent)
: QDateTimeEdit(d, parent)
{
setWrapping(true);
setDisplayFormat(QLatin1String("dd.MM.yy HH:mm:ss.zzz"));
connect(this, &LtsMSecDateTimeEdit::editingFinished, this, &LtsMSecDateTimeEdit::onEditingFinished);
}
LtsMSecDateTimeEdit::LtsMSecDateTimeEdit(const QTime &t, QWidget *parent)
: QDateTimeEdit(t, parent)
{
setWrapping(true);
setDisplayFormat(QLatin1String("dd.MM.yy HH:mm:ss.zzz"));
connect(this, &LtsMSecDateTimeEdit::editingFinished, this, &LtsMSecDateTimeEdit::onEditingFinished);
}
void LtsMSecDateTimeEdit::stepBy(int steps)
{
switch (currentSection()) {
case QDateTimeEdit::MonthSection:
QDateTimeEdit::setDateTime(dateTime().addMonths(steps));
break;
case QDateTimeEdit::YearSection:
QDateTimeEdit::setDateTime(dateTime().addYears(steps));
break;
case QDateTimeEdit::DaySection:
QDateTimeEdit::setDateTime(dateTime().addDays(steps));
break;
case QDateTimeEdit::HourSection:
QDateTimeEdit::setDateTime(dateTime().addSecs(steps * 3600));
break;
case QDateTimeEdit::MinuteSection:
QDateTimeEdit::setDateTime(dateTime().addSecs(steps * 60));
break;
case QDateTimeEdit::SecondSection:
QDateTimeEdit::setDateTime(dateTime().addSecs(steps));
break;
case QDateTimeEdit::MSecSection:
QDateTimeEdit::setDateTime(dateTime().addMSecs(steps * m_msecStepSize));
break;
case QDateTimeEdit::NoSection:
case QDateTimeEdit::AmPmSection:
case QDateTimeEdit::TimeSections_Mask:
case QDateTimeEdit::DateSections_Mask:
default:
break;
}
}
qint64 LtsMSecDateTimeEdit::msecsSinceEpoch() const
{
return dateTime().toMSecsSinceEpoch() - (m_timezoneHoursOffset * 3600 * 1000);
}
void LtsMSecDateTimeEdit::setTimezoneHoursOffset(int timezoneHoursOffset)
{
qint64 b4 = msecsSinceEpoch();
m_timezoneHoursOffset = timezoneHoursOffset;
setMsecsSinceEpoch(b4);
}
void LtsMSecDateTimeEdit::setDateTime(const QDateTime &dateTime)
{
setMsecsSinceEpoch(QDateTime::fromMSecsSinceEpoch(dateTime.toMSecsSinceEpoch(), Qt::TimeSpec::OffsetFromUTC, m_timezoneHoursOffset * 3600).toMSecsSinceEpoch());
}
void LtsMSecDateTimeEdit::setMsecsSinceEpoch(qint64 msecs)
{
QDateTimeEdit::setDateTime(QDateTime::fromMSecsSinceEpoch(msecs, Qt::TimeSpec::OffsetFromUTC, m_timezoneHoursOffset * 3600));
}
int LtsMSecDateTimeEdit::msecStepSize() const
{
return m_msecStepSize;
}
void LtsMSecDateTimeEdit::setMsecStepSize(int msecStepSize)
{
m_msecStepSize = msecStepSize;
}
void LtsMSecDateTimeEdit::onEditingFinished()
{
qint64 val = msecsSinceEpoch();
if (val % m_msecStepSize == 0)
return;
val = (val + (m_msecStepSize/2) ) / m_msecStepSize * m_msecStepSize;
setMsecsSinceEpoch(val);
}
}
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <QDateTimeEdit>
#include "lts_widgets_export.h"
namespace LtsWidgets {
class LTSWIDGETS_EXPORT LtsMSecDateTimeEdit : public QDateTimeEdit
{
Q_OBJECT
Q_PROPERTY(int msecStepSize READ msecStepSize WRITE setMsecStepSize)
public:
explicit LtsMSecDateTimeEdit(QWidget *parent = nullptr);
explicit LtsMSecDateTimeEdit(const QDateTime &dt, QWidget *parent = nullptr);
explicit LtsMSecDateTimeEdit(const QDate &d, QWidget *parent = nullptr);
explicit LtsMSecDateTimeEdit(const QTime &t, QWidget *parent = nullptr);
qint64 msecsSinceEpoch() const;
int timezoneHoursOffset() const { return m_timezoneHoursOffset; }
void stepBy(int steps) override;
int msecStepSize() const;
public slots:
void setDateTime(const QDateTime &dateTime);
void setMsecsSinceEpoch(qint64 msecs);
void setMsecStepSize(int msecStepSize);
void setTimezoneHoursOffset(int timezoneHoursOffset);
private slots:
void onEditingFinished();
private:
int m_msecStepSize = 10;
int m_timezoneHoursOffset = 0;
};
}
+313
View File
@@ -0,0 +1,313 @@
#include "lts_multi_range_spinbox.h"
#include <QEvent>
#include <QWheelEvent>
#include <cmath>
namespace LtsWidgets
{
LtsMultiRangeSpinBox::LtsMultiRangeSpinBox(QWidget *parent)
: QSpinBox(parent)
{
m_curVal = minimum();
}
QValidator::State LtsMultiRangeSpinBox::validate(QString &input, int &pos) const
{
return QValidator::Acceptable;
}
void LtsMultiRangeSpinBox::fixup(QString &str) const
{
}
QValidator::State LtsMultiRangeSpinBox::validateAll(QString &input, int &pos)
{
for(QPair<int,int> range : qAsConst(m_rangesList))
{
QIntValidator validator(range.first, range.second);
QValidator::State valState = validator.validate(input, pos);
if (valState == QValidator::Acceptable)
{
return valState;
}
}
return QValidator::Invalid;
}
QVector<QPair<int,int>> LtsWidgets::LtsMultiRangeSpinBox::sortRanges(const QVector<QPair<int, int> > &ranges)
{
QVector<QPair<int, int>> rangesEditable = ranges;
QVector<QPair<int, int>> result;
std::sort(rangesEditable.begin(), rangesEditable.end());
QVector<QPair<int, int>>::iterator it = rangesEditable.begin();
QPair<int,int> current = *(it)++;
while (it != rangesEditable.end())
{
if (current.second > it->first)
current.second = std::max(current.second, it->second);
else
{
result.push_back(current);
current = *(it);
}
++it;
}
result.push_back(current);
return result;
}
void LtsMultiRangeSpinBox::setRanges(const QVector<QPair<int, int>> &ranges)
{
if(ranges.empty())
return;
m_rangesList = sortRanges(ranges);
QSpinBox::setMaximum(m_rangesList.last().second);
QSpinBox::setMinimum(m_rangesList.first().first);
QStringList rangeStrings;
rangeStrings.reserve(m_rangesList.size());
for (const QPair<int,int> &range : qAsConst(m_rangesList))
rangeStrings << tr("%1-%2%3").arg(range.first).arg(range.second).arg(suffix());
setToolTip(tr("Ranges:\n%1").arg(rangeStrings.join(QStringLiteral(",\n"))));
}
void LtsMultiRangeSpinBox::setRange(int min, int max)
{
setRanges({{min,max}});
}
void LtsMultiRangeSpinBox::setMinimum(int min)
{
auto ranges = m_rangesList;
ranges.first().first = min;
setRanges(ranges);
}
void LtsMultiRangeSpinBox::setMaximum(int max)
{
auto ranges = m_rangesList;
ranges.last().second = max;
setRanges(ranges);
}
int LtsMultiRangeSpinBox::fixupValue(int value) const
{
int nearestValue = INT_MAX;
for(QPair<int,int> range : m_rangesList)
{
if(std::abs(range.first - value) < std::abs(nearestValue - value))
nearestValue = range.first;
if(std::abs(range.second - value) < std::abs(nearestValue - value))
nearestValue = range.second;
}
value = nearestValue;
int buffer = value;
int remainder = (value - minimum()) % singleStep();
if (2 * remainder > singleStep())
{
value += singleStep();
}
value -= remainder;
if(buffer + singleStep() > value + singleStep())
{
value+= singleStep();
}
if (value > maximum())
{
value -= singleStep();
}
return value;
}
int LtsMultiRangeSpinBox::fixupValue(int value, bool higher) const
{
int nearestValue = INT_MAX;
for(QPair<int,int> range : m_rangesList)
{
if(std::abs(range.first - value) < std::abs(nearestValue - value))
{
if(higher)
{
if(range.second < value)
continue;
} else
if(range.second > value)
continue;
nearestValue = range.first;
}
if(std::abs(range.second - value) < std::abs(nearestValue - value))
{
if(higher)
{
if(range.second < value)
continue;
} else
if(range.second > value)
continue;
nearestValue = range.second;
}
}
value = nearestValue;
int curVal = value;
int remainder = (value - minimum()) % singleStep();
if (2 * remainder > singleStep())
{
value += singleStep();
}
value -= remainder;
if(curVal + singleStep() > value + singleStep())
{
value+= singleStep();
}
if (value > maximum())
{
value -= singleStep();
}
return value;
}
void LtsMultiRangeSpinBox::focusOutEvent(QFocusEvent *event)
{
QSpinBox::focusOutEvent(event);
QString value = QString::number(this->value());
int length = value.length();
QValidator::State valState = validateAll(value, length);
if(valState == QValidator::State::Invalid)
{
this->setValue(fixupValue(value.toInt()));
}
}
void LtsMultiRangeSpinBox::wheelEvent(QWheelEvent *event)
{
QSpinBox::wheelEvent(event);
QString valueStr = QString::number(this->value());
int length = valueStr.length();
QValidator::State valState = validateAll(valueStr, length);
if(valState == QValidator::State::Invalid)
{
if(this->value() < m_curVal)
{
m_curVal = fixupValue(this->value(), false);
setValue(m_curVal);
}
else
{
m_curVal = fixupValue(this->value(), true);
setValue(m_curVal);
}
}
}
void LtsMultiRangeSpinBox::mousePressEvent(QMouseEvent *event)
{
QSpinBox::mousePressEvent(event);
QString valueStr = QString::number(this->value());
int length = valueStr.length();
QValidator::State valState = validateAll(valueStr, length);
if(valState == QValidator::State::Invalid)
{
if(this->value() < m_curVal)
{
m_curVal = fixupValue(this->value(), false);
setValue(m_curVal);
}
else
{
m_curVal = fixupValue(this->value(), true);
setValue(m_curVal);
}
}
}
void LtsMultiRangeSpinBox::keyPressEvent(QKeyEvent *event)
{
QSpinBox::keyPressEvent(event);
QString value = QString::number(this->value());
int length = value.length();
QValidator::State valState = validateAll(value, length);
if(valState == QValidator::State::Invalid)
{
setValue(fixupValue(value.toInt()));
}
}
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include "lts_widgets_export.h"
#include <QSet>
#include <QSpinBox>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsMultiRangeSpinBox : public QSpinBox
{
Q_OBJECT
public:
explicit LtsMultiRangeSpinBox(QWidget *parent = nullptr);
~LtsMultiRangeSpinBox() = default;
public slots:
void setRanges(const QVector<QPair<int, int>> &ranges);
void setRange(int min, int max);
void setMinimum(int min);
void setMaximum(int max);
protected:
QValidator::State validate(QString &input, int &pos) const override;
void fixup(QString &str) const override;
void focusOutEvent(QFocusEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
static QVector<QPair<int,int>> sortRanges(const QVector<QPair<int, int> > &ranges);
QValidator::State validateAll(QString &input, int &pos);
int fixupValue(int value) const;
int fixupValue(int value, bool higher) const;
private:
QVector<QPair<int, int>> m_rangesList;
int m_curVal = minimum();
QRegExp m_regex;
};
}
+198
View File
@@ -0,0 +1,198 @@
#include "lts_notification_box.h"
#include "ui_lts_notification_box.h"
#include <QPainter>
#include <QLinearGradient>
#include <QColor>
#include <QGraphicsDropShadowEffect>
#include <QStyleOption>
#include <QStyle>
#ifdef NOTIBOX_DEBUG
#include <QDebug>
#endif
namespace LtsWidgets
{
const int LtsNotificationBox::margin = 14;
LtsNotificationBox::LtsNotificationBox(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::NotiBox)
{
m_ui->setupUi(this);
m_ui->lblText->setText({});
connect(m_ui->lblText, &QLabel::linkActivated,
this, [this](const QString &link)
{
emit signalLinkClicked(link);
});
connect(m_ui->tbClose, &QToolButton::clicked,
this, &LtsNotificationBox::signalClose);
connect(m_ui->tbAck, &QToolButton::clicked,
this, &LtsNotificationBox::signalAck);
setObjectName(QStringLiteral("NotiBox"));
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
shadow->setOffset(0, 0);
shadow->setBlurRadius(margin*2);
shadow->setColor(QColor(25, 25, 25));
setGraphicsEffect(shadow);
}
void LtsNotificationBox::message(const QString &title, const QString &text, MessageType type)
{
static QString rgbBaseString(QStringLiteral("%1, %2, %3"));
static QString closeDefault(QStringLiteral("close.svg"));
static QString closeDark(QStringLiteral("close_dark.svg"));
static QString ackDefault(QStringLiteral("ack.svg"));
static QString ackDark(QStringLiteral("ack_dark.svg"));
static QString lightTextColor(QStringLiteral("fbfbfb"));
static QString darkTextColor(QStringLiteral("2c3642"));
static QColor errorStart(254, 45, 102);
static QColor errorEnd(255, 92, 61);
static QColor successStart(43, 167, 70);
static QColor successEnd(130, 180, 45);
static QColor infoStart(74, 74, 74);
static QColor infoEnd(43, 43, 43);
static QColor warningStart(253, 151, 4);
static QColor warningEnd(253, 202, 0);
QColor start;
QColor end;
QString close;
QString closeHover;
QString ack;
QString ackHover;
QString textColor;
switch (type)
{
case MessageType::Error:
{
start = errorStart;
end = errorEnd;
close = closeDefault;
closeHover = closeDark;
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/error.svg")));
break;
}
case MessageType::Success:
{
start = successStart;
end = successEnd;
close = closeDefault;
closeHover = closeDark;
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/success.svg")));
break;
}
case MessageType::Info:
{
start = infoStart;
end = infoEnd;
close = closeDefault;
closeHover = closeDark;
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/info.svg")));
break;
}
case MessageType::Warning:
{
start = warningStart;
end = warningEnd;
close = closeDark;
closeHover = closeDefault;
ack = ackDark;
ackHover = ackDefault;
textColor = darkTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/warning.svg")));
break;
}
}
QStringList css;
css << QStringLiteral("#NotiBox { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop: 0 rgb(%1), stop: 1 rgb(%2)); border: 1px solid rgb(%3); border-radius: 8px; margin: %4px }").
arg(rgbBaseString.arg(start.red()).arg(start.green()).arg(start.blue()),
rgbBaseString.arg(end.red()).arg(end.green()).arg(end.blue()),
rgbBaseString.arg(end.red()).arg(end.green()).arg(end.blue())).
arg(margin);
css << QStringLiteral("QToolButton#tbClose { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(close);
css << QStringLiteral("QToolButton#tbClose:hover { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(closeHover);
css << QStringLiteral("QToolButton#tbAck { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(ack);
css << QStringLiteral("QToolButton#tbAck:hover { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(ackHover);
#ifdef NOTIBOX_DEBUG
qWarning() << "css" << css;
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/close.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/close_dark.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/error.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/info.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/warning.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/success.svg"));
#endif
m_ui->lblImage->setStyleSheet(QString());
setStyleSheet(css.join(QStringLiteral(" ")));
m_ui->lblText->setText(QStringLiteral("<p><span style='font-size:14pt; font-weight:600; color:#%1;'>%2</span></p><p><span style='font-size:14pt; color:#%3;'>%4</span></p>").arg(textColor, title, textColor, text));
show();
}
void LtsNotificationBox::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
}
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include "lts_widgets_export.h"
#include <QWidget>
#include <QPainterPath>
class QPaintEvent;
class QResizeEvent;
namespace Ui
{
class NotiBox;
}
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsNotificationBox : public QWidget
{
Q_OBJECT
public:
enum class MessageType
{
Success,
Error,
Warning,
Info,
};
explicit LtsNotificationBox(QWidget *parent = nullptr);
void message(const QString &title, const QString &text, MessageType type = MessageType::Error);
signals:
void signalClose();
void signalAck();
void signalLinkClicked(const QString &link);
protected:
void paintEvent(QPaintEvent *) override;
private:
Ui::NotiBox *m_ui;
QPainterPath roundRectPath;
const static int margin;
};
}
+182
View File
@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NotiBox</class>
<widget class="QWidget" name="NotiBox">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>670</width>
<height>130</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>670</width>
<height>130</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>670</width>
<height>130</height>
</size>
</property>
<property name="windowTitle">
<string>Notification</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>:/rde_icon_256.png</normaloff>:/rde_icon_256.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0">
<property name="spacing">
<number>20</number>
</property>
<property name="leftMargin">
<number>40</number>
</property>
<property name="topMargin">
<number>18</number>
</property>
<property name="rightMargin">
<number>18</number>
</property>
<property name="bottomMargin">
<number>18</number>
</property>
<item>
<widget class="QLabel" name="lblImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; font-weight:600; color:#eeeeee;&quot;&gt;Error Message&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; color:#eeeeee;&quot;&gt;This is an error message. looooooooooooooooooooong text&lt;br/&gt;With 2 lines!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="openExternalLinks">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="tbAck">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="special" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClose">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="special" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+114
View File
@@ -0,0 +1,114 @@
#include "lts_operator_menu.h"
#include "ui_lts_operator_menu.h"
#include "lts_info_dialog.h"
#include <ngltranslator/ngltranslator.h>
#include <QPushButton>
#include <QProcess>
#include <QHostInfo>
namespace LtsWidgets
{
LtsOperatorMenu::LtsOperatorMenu(const QString &operatorName, const QString &workspaceId, bool debug, int screenCount, QWidget *parent)
: LtsFramelessDialog(parent)
, m_ui(new Ui::LtsOperatorMenu)
{
m_ui->setupUi(this);
m_ui->lbOperatorName->setText(operatorName);
m_ui->lbHostName->setText(QHostInfo::localHostName());
if (screenCount < 2)
m_ui->pbSwap->hide();
if (debug)
m_ui->lbWorkspaceId->setText(tr("Workspace: >>>%1<<<").arg(workspaceId));
else
m_ui->lbWorkspaceId->hide();
connect(m_ui->pbOperatorSettings, &QPushButton::clicked, this, &LtsOperatorMenu::signalShowOperatorSettings);
connect(m_ui->pbOperatorSettings, &QPushButton::clicked, this, &LtsOperatorMenu::close);
connect(m_ui->pbWindow, &QPushButton::clicked, this, &LtsOperatorMenu::onTerminalButtonClicked);
connect(m_ui->pbWindow, &QPushButton::clicked, this, &LtsOperatorMenu::close);
connect(m_ui->pbLogout, &QPushButton::clicked, this, &LtsOperatorMenu::signalLogout);
connect(m_ui->pbExit, &QPushButton::clicked, this, &LtsOperatorMenu::signalExit);
connect(m_ui->pbCancel, &QPushButton::clicked, this, &LtsOperatorMenu::close);
connect(m_ui->pbSwap, &QPushButton::clicked, this, &LtsOperatorMenu::signalSwap);
connect(m_ui->pbSwap, &QPushButton::clicked, this, &LtsOperatorMenu::close);
connect(m_ui->pbAbout, &QPushButton::clicked, this, &LtsOperatorMenu::slotShowInfoDialog);
connect(m_ui->pbAbout, &QPushButton::clicked, this, &LtsOperatorMenu::close);
if (NGL::translationLocale() == "de_DE")
m_ui->pbGer->setChecked(true);
else
m_ui->pbInt->setChecked(true);
connect(m_ui->pbGer, &QPushButton::clicked,
this, &LtsOperatorMenu::onLanguageChange);
connect(m_ui->pbInt, &QPushButton::clicked,
this, &LtsOperatorMenu::onLanguageChange);
#ifndef LTS_DEBUG
m_ui->debugWidget->hide();
#endif
}
LtsOperatorMenu::~LtsOperatorMenu()
{
delete m_ui;
}
void LtsOperatorMenu::slotShowInfoDialog()
{
LtsInfoDialog *infoDialog = new LtsInfoDialog();
infoDialog->setAttribute(Qt::WA_DeleteOnClose);
infoDialog->show();
}
void LtsOperatorMenu::onTerminalButtonClicked()
{
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString lang = QString::fromLatin1(NGL::translationLocale());
lang.append(QStringLiteral(".UTF-8"));
env.insert(QStringLiteral("LANG"), lang);
QProcess process;
process.setProcessEnvironment(env);
QStringList args;
args << QStringLiteral("--geometry") << QStringLiteral("800x800+200+100");
if (QApplication::queryKeyboardModifiers() == Qt::ControlModifier)
process.startDetached(QStringLiteral("xterm"), args);
else
process.startDetached(QStringLiteral("konsole"), args);
}
void LtsOperatorMenu::setTerminalButton(bool bVisible)
{
m_ui->pbWindow->setVisible(bVisible);
}
void LtsOperatorMenu::setOperatorSettingsButton(bool bVisible)
{
m_ui->pbOperatorSettings->setVisible(bVisible);
}
void LtsOperatorMenu::onLanguageChange()
{
if (m_ui->pbGer->isChecked())
NGL::setTranslationLocale(QByteArray("de_DE"));
if (m_ui->pbInt->isChecked())
NGL::setTranslationLocale(QByteArray("en_GB"));
}
}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include "lts_frameless_dialog.h"
#include "lts_widgets_export.h"
namespace Ui {
class LtsOperatorMenu;
}
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsOperatorMenu : public LtsFramelessDialog
{
Q_OBJECT
public:
explicit LtsOperatorMenu(const QString &operatorName, const QString &workspaceId, bool debug, int screenCount, QWidget *parent);
~LtsOperatorMenu();
void setTerminalButton(bool bVisible);
void setOperatorSettingsButton(bool bVisible);
private:
Ui::LtsOperatorMenu *m_ui;
signals:
void signalLogout();
void signalExit();
void signalShowOperatorSettings();
void signalSwap();
private slots:
void onTerminalButtonClicked();
void onLanguageChange();
void slotShowInfoDialog();
};
}
+247
View File
@@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsOperatorMenu</class>
<widget class="QWidget" name="LtsOperatorMenu">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>310</width>
<height>504</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Operator Menu</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lbOperatorName">
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="text">
<string notr="true">%OPERATORNAME%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbHostName">
<property name="text">
<string notr="true">%HOSTNAME%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbWorkspaceId">
<property name="text">
<string notr="true">Workspace: %WORKSPACEID%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbOperatorSettings">
<property name="text">
<string>Operator Settings</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbWindow">
<property name="text">
<string>Terminal Window</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbSwap">
<property name="text">
<string>Swap with another window</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbLogout">
<property name="text">
<string>Operator Logout</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbExit">
<property name="text">
<string>Exit Application</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pbAbout">
<property name="text">
<string>About</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="debugWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbDebug">
<property name="text">
<string>For Debug only</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pbGer">
<property name="toolTip">
<string>Deutsch - German</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources/lts_resources.qrc">
<normaloff>:/Germany-Flag.png</normaloff>:/Germany-Flag.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoExclusive">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbInt">
<property name="toolTip">
<string>English - Englisch (International)</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources/lts_resources.qrc">
<normaloff>:/Great-Britain-Flag.png</normaloff>:/Great-Britain-Flag.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoExclusive">
<bool>true</bool>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>18</width>
<height>29</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="resources/lts_resources.qrc"/>
</resources>
<connections/>
</ui>
+45
View File
@@ -0,0 +1,45 @@
#include "lts_overlay_loading.h"
#include "ui_lts_overlay_loading.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressBar>
#include <QPushButton>
namespace LtsWidgets
{
LtsOverlayLoading::LtsOverlayLoading(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::LtsOverlayLoading)
{
m_ui->setupUi(this);
setCancelButtonVisible(false);
connect(m_ui->pbCancel, &QPushButton::clicked,
this, [this](){ setCancelButtonEnabled(false); });
connect(m_ui->pbCancel, &QPushButton::clicked,
this, &LtsOverlayLoading::cancel);
}
void LtsOverlayLoading::setText(const QString &text)
{
m_ui->label->setText(text);
}
void LtsOverlayLoading::setCancelButtonVisible(bool visible)
{
m_ui->pbCancel->setVisible(visible);
}
void LtsOverlayLoading::setCancelButtonEnabled(bool enabled)
{
m_ui->pbCancel->setEnabled(enabled);
}
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include "lts_widgets_export.h"
#include <QWidget>
namespace Ui { class LtsOverlayLoading; }
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsOverlayLoading : public QWidget
{
Q_OBJECT
public:
explicit LtsOverlayLoading(QWidget *parent = nullptr);
void setText(const QString &text);
void setCancelButtonVisible(bool visible);
void setCancelButtonEnabled(bool enabled);
signals:
void cancel();
private:
Ui::LtsOverlayLoading *m_ui;
};
}
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsOverlayLoading</class>
<widget class="QWidget" name="LtsOverlayLoading">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>370</width>
<height>120</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>370</width>
<height>120</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>555</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="99999,0">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Loading ...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QProgressBar" name="pbarMain">
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbCancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="shortcut">
<string>Shift+C</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+339
View File
@@ -0,0 +1,339 @@
#include "lts_picture_view.h"
#include <QMouseEvent>
#include <QGraphicsPixmapItem>
#include <QGraphicsColorizeEffect>
#include <QRubberBand>
using namespace LtsWidgets;
LtsPictureView::LtsPictureView(QWidget *parent)
: QGraphicsView(parent)
, m_gsPicture(new QGraphicsScene(this))
, m_rubberband(new QRubberBand(QRubberBand::Rectangle, this))
, m_image(nullptr)
, m_origimage(nullptr)
{
m_mouseActive = false;
m_moveable = false;
m_aspectRatioEnabled = true;
m_s_inEdit = false;
m_aspectRatio = 1;
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
LtsPictureView::~LtsPictureView()
{
delete m_rubberband;
}
void LtsPictureView::setAspectRatio(double aspectRatio)
{
m_aspectRatio = aspectRatio;
newRubberBand();
}
void LtsPictureView::ratioClicked(bool enabled)
{
m_aspectRatioEnabled = enabled;
if (enabled)
newRubberBand();
}
void LtsPictureView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
if (m_rubberband->geometry().contains(event->pos()))
{
m_bandoffset = event->pos() - m_rubberband->pos();
m_moveable = true;
m_rubberband->show();
}
else
{
m_origin = event->pos();
m_curRectangle = QRect(m_origin.x(), m_origin.y(), 0, 0);
m_rubberband->setGeometry(m_curRectangle);
m_rubberband->show();
m_mouseActive = true;
}
}
else
{
hideRubberband();
newRubberBand();
m_mouseActive = false;
}
QGraphicsView::mousePressEvent(event);
}
void LtsPictureView::mouseMoveEvent(QMouseEvent *event)
{
if (m_moveable == true)
{
QPoint newCoord = event->pos() - m_bandoffset;
if (newCoord.x() < 0)
newCoord.setX(0);
if (newCoord.y() < 0)
newCoord.setY(0);
if (m_origimage->pixmap().width() < (newCoord.x() + m_rubberband->width()))
newCoord.setX(m_origimage->pixmap().width() - m_rubberband->width() + 1);
if (m_origimage->pixmap().height() < (newCoord.y() + m_rubberband->height()))
newCoord.setY(m_origimage->pixmap().height() - m_rubberband->height() + 1);
m_rubberband->move(newCoord);
QPoint move = m_rubberband->pos();
int left = move.x();
int top = move.y();
int width = m_rubberband->rect().width();
int height = m_rubberband->rect().height();
emit mouseMoved(QRect(left, top, width, height));
}
else
{
if (m_mouseActive)
{
QRect rect;
int xMax = event->pos().x();
int yMax = event->pos().y();
if (event->pos().x() > m_origimage->pixmap().width())
xMax = m_origimage->pixmap().width();
if (event->pos().x() < 0)
xMax = 0;
if (event->pos().y() > m_origimage->pixmap().height())
yMax = m_origimage->pixmap().height();
if (event->pos().y() < 0)
yMax = 0;
if (m_aspectRatioEnabled)
{
const int xMin = m_origin.x();
const int yMin = m_origin.y();
int xLengthAbs(std::abs(xMax - xMin));
int yLengthAbs(std::abs(yMax - yMin));
QPoint length;
if (xLengthAbs / m_aspectRatio > yLengthAbs * m_aspectRatio)
{
length.setX(xLengthAbs);
length.setY(length.x() / m_aspectRatio);
}
else
{
length.setY(yLengthAbs);
length.setX(length.y() * m_aspectRatio);
}
if (!(yMax - yMin < 0) && length.y() + m_origin.y() > m_origimage->pixmap().height())
{
length.setY(m_origimage->pixmap().height() - m_origin.y());
length.setX(length.y()* m_aspectRatio);
}
if (!(xMax - xMin < 0) && length.x() + m_origin.x() > m_origimage->pixmap().width())
{
length.setX(m_origimage->pixmap().width() - m_origin.x());
length.setY(length.x() / m_aspectRatio);
}
if (xMax - xMin < 0)
{
length.setX(length.x() * -1);
if (length.x() + m_origin.x() < 0)
{
length.setX(0 - m_origin.x());
length.setY((length.x() / m_aspectRatio) * -1);
}
}
if (yMax - yMin < 0)
{
length.setY(length.y() * -1);
if (length.y() + m_origin.y() < 0)
{
length.setY(0 - m_origin.y());
length.setX(length.y() * m_aspectRatio);
if (!(xMax - xMin < 0))
length.setX(length.x() * -1);
}
}
length = m_origin + length;
rect.setTopLeft(m_origin);
rect.setBottomRight(length);
}
else
{
rect.setTopLeft(m_origin);
rect.setBottomRight(QPoint(xMax, yMax));
}
m_curRectangle = rect.normalized();
m_rubberband->setGeometry(m_curRectangle);
emit mouseMoved(m_curRectangle);
}
}
QGraphicsView::mouseMoveEvent(event);
}
void LtsPictureView::mouseReleaseEvent(QMouseEvent *event)
{
m_moveable = false;
QGraphicsView::mouseReleaseEvent(event);
}
void LtsPictureView::hideRubberband()
{
m_rubberband->hide();
}
void LtsPictureView::newRubberBand()
{
delete m_rubberband;
m_rubberband = new QRubberBand(QRubberBand::Rectangle, this);
}
void LtsPictureView::setPicture(const QImage &image, const QPoint &pos, const bool flag)
{
if (m_image)
{
m_gsPicture->removeItem(m_image);
delete m_image;
}
if (flag)
{
if (m_origimage)
{
m_gsPicture->removeItem(m_origimage);
delete m_origimage;
}
QGraphicsOpacityEffect *opacity = new QGraphicsOpacityEffect;
opacity->setOpacity(0.2);
m_origimage = new QGraphicsPixmapItem(QPixmap::fromImage(image));
m_origimage->setGraphicsEffect(opacity);
m_gsPicture->addItem(m_origimage);
setMinimumSize(image.size());
setMaximumSize(image.size());
emit setLimits(m_origimage->pixmap().size(), true);
}
m_image = new QGraphicsPixmapItem(QPixmap::fromImage(image));
m_image->setPos(pos);
m_gsPicture->addItem(m_image);
setScene(m_gsPicture);
}
void LtsPictureView::leftChanged(int left)
{
if (m_s_inEdit || m_mouseActive)
return;
m_s_inEdit = true;
m_curRectangle.setLeft(left);
if(m_aspectRatioEnabled)
{
int newHeight = m_curRectangle.width() / m_aspectRatio;
if (m_origin.y() < m_curRectangle.bottom())
{
m_curRectangle.setHeight(newHeight);
}
else
{
int offset = m_curRectangle.height() - newHeight;
m_curRectangle.setTop(m_curRectangle.top() + offset);
}
}
m_rubberband->setGeometry(m_curRectangle);
emit mouseMoved(m_curRectangle);
m_s_inEdit = false;
}
void LtsPictureView::rightChanged(int right)
{
if (m_s_inEdit || m_mouseActive)
return;
m_s_inEdit = true;
m_curRectangle.setRight(right);
if(m_aspectRatioEnabled)
{
int newHeight = m_curRectangle.width() / m_aspectRatio;
if (m_origin.y() < m_curRectangle.bottom())
{
m_curRectangle.setHeight(newHeight);
}
else
{
int offset = m_curRectangle.height() - newHeight;
m_curRectangle.setTop(m_curRectangle.top() + offset);
}
}
m_rubberband->setGeometry(m_curRectangle);
emit mouseMoved(m_curRectangle);
m_s_inEdit = false;
}
void LtsPictureView::topChanged(int top)
{
if (m_s_inEdit || m_mouseActive)
return;
m_s_inEdit = true;
m_curRectangle.setTop(top);
if(m_aspectRatioEnabled)
{
int newWidth = m_curRectangle.height() * m_aspectRatio;
if (m_origin.x() <= m_curRectangle.left())
{
m_curRectangle.setWidth(newWidth);
}
else
{
int offset = m_curRectangle.width() - newWidth;
m_curRectangle.setLeft(m_curRectangle.left() + offset);
}
}
m_rubberband->setGeometry(m_curRectangle);
emit mouseMoved(m_curRectangle);
m_s_inEdit = false;
}
void LtsPictureView::bottomChanged(int bottom)
{
if (m_s_inEdit || m_mouseActive)
return;
m_s_inEdit = true;
m_curRectangle.setBottom(bottom);
if(m_aspectRatioEnabled)
{
int newWidth = m_curRectangle.height() * m_aspectRatio;
if (m_origin.x() <= m_curRectangle.left())
{
m_curRectangle.setWidth(newWidth);
}
else
{
int offset = m_curRectangle.width() - newWidth;
m_curRectangle.setLeft(m_curRectangle.left() + offset);
}
}
m_rubberband->setGeometry(m_curRectangle);
emit mouseMoved(m_curRectangle);
m_s_inEdit = false;
}
QGraphicsPixmapItem *LtsPictureView::getImage()
{
if (!m_image)
m_image = new QGraphicsPixmapItem;
return m_image;
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include "lts_widgets_export.h"
#include <QGraphicsView>
class QRubberBand;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsPictureView : public QGraphicsView
{
Q_OBJECT
public:
explicit LtsPictureView(QWidget *parent = nullptr);
~LtsPictureView();
void hideRubberband();
void newRubberBand();
void cutPicture();
QGraphicsPixmapItem *getImage();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
bool m_mouseActive;
bool m_moveable;
bool m_aspectRatioEnabled;
bool m_s_inEdit;
double m_aspectRatio;
QRect m_curRectangle;
QGraphicsScene *m_gsPicture;
QRubberBand *m_rubberband;
QGraphicsPixmapItem *m_image;
QGraphicsPixmapItem *m_origimage;
QPoint m_origin;
QPoint m_bandoffset;
public slots:
void setPicture(const QImage &image, const QPoint &pos, const bool flag);
void setAspectRatio(double aspectRatio);
void ratioClicked(bool enabled);
void leftChanged(int left);
void rightChanged(int right);
void topChanged(int top);
void bottomChanged(int bottom);
signals:
void mouseMoved(const QRect &);
void setLimits(const QSize &, bool);
};
}
+133
View File
@@ -0,0 +1,133 @@
#include "lts_profile_button.h"
#include <QPainter>
#include <QPainterPath>
#include <QPaintEvent>
#include <QBrush>
#include <QPen>
#include <QRect>
#include <QEvent>
using namespace LtsWidgets;
LtsProfileButton::LtsProfileButton(QWidget *parent)
: QWidget(parent)
, m_isHovered(false)
, m_menuEnabled(true)
{
QSizePolicy qsp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
qsp.setHeightForWidth(true);
setSizePolicy(qsp);
}
void LtsProfileButton::setPixmap(const QPixmap &pixmap)
{
if (pixmap.isNull())
m_pixmap = QPixmap(QStringLiteral("icon:no_pic.svg"));
else
m_pixmap = pixmap;
update();
}
void LtsProfileButton::enterEvent(QEvent *event)
{
m_isHovered = true;
update();
QWidget::enterEvent(event);
}
void LtsProfileButton::leaveEvent(QEvent *event)
{
m_isHovered = false;
update();
QWidget::leaveEvent(event);
}
bool LtsProfileButton::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress && m_menuEnabled)
{
emit signalClicked();
event->accept();
update();
return true;
}
return QWidget::event(event);
}
void LtsProfileButton::paintEvent(QPaintEvent* event)
{
QPainter p(this);
p.save();
int minSize;
QPointF center;
minSize = height() > width() ? width() : height();
center = QPointF(width() / 2.0, height() / 2.0);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
QPixmap pixmap(minSize, minSize);
pixmap.fill(Qt::white);
if (!m_pixmap.isNull())
{
if (!(m_isHovered && m_menuEnabled))
{
pixmap = m_pixmap.scaled(minSize, minSize, Qt::KeepAspectRatioByExpanding);
}
}
QPainterPath path;
path.addEllipse(center,
minSize / 2.0 - 4,
minSize / 2.0 - 4);
p.setClipPath(path);
p.drawPixmap(center - QPointF(minSize/2.0,minSize/2.0),pixmap);
p.setPen(QPen(QColor("gray"), 2));
p.drawEllipse(center,
minSize / 2.0 - 4,
minSize / 2.0 - 4);
if (m_isHovered && m_menuEnabled)
{
p.setPen(QPen(QColor(QStringLiteral("gray")), (minSize / 48 * 2)));
double xc = size().width()/2.012;
double yc = size().height()/2.012;
double diff = minSize/2.012;
p.drawLine(QPointF(xc - (diff/2.01f), yc - (diff/3.01f)), QPointF(xc + (diff/2.02f), yc - (diff/3.02f)));
p.drawLine(QPointF(xc - (diff/2.01f), yc - 0.01f), QPointF(xc + (diff/2.02f), yc - 0));
p.drawLine(QPointF(xc - (diff/2.01f), yc + (diff/3.01f)), QPointF(xc + (diff/2.02f), yc + (diff/3.02f)));
}
event->accept();
p.restore();
}
+55
View File
@@ -0,0 +1,55 @@
#pragma once
#include "lts_widgets_export.h"
#include <QWidget>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsProfileButton : public QWidget
{
Q_OBJECT
Q_PROPERTY( QPixmap pixMap READ pixmap WRITE setPixmap )
Q_PROPERTY( bool menuEnabled READ menuEnabled WRITE setMenuEnabled )
public:
explicit LtsProfileButton(QWidget *parent = nullptr);
void setPixmap(const QPixmap &pixmap);
const QPixmap &pixmap() const { return m_pixmap; }
void setMenuEnabled(bool enabled = true) { m_menuEnabled = enabled; }
bool menuEnabled() const { return m_menuEnabled; }
protected:
void paintEvent(QPaintEvent *event);
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
bool event(QEvent *event);
private:
QPixmap m_pixmap;
bool m_isHovered;
bool m_menuEnabled;
signals:
void signalClicked();
};
}
+147
View File
@@ -0,0 +1,147 @@
#include "lts_progress_dialog_helper.h"
#include "lts_frameless_dialog.h"
#include <QCoreApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressBar>
#include <QPushButton>
#include <QTimer>
namespace LtsWidgets
{
LtsProgressDialogHelper::LtsProgressDialogHelper(QWidget *parent)
: QObject(parent)
, m_waitDlg(nullptr)
, m_parentWidget(parent)
, m_textLabel(nullptr)
{}
LtsProgressDialogHelper::~LtsProgressDialogHelper()
{
delete m_waitDlg;
}
void LtsProgressDialogHelper::setCustomText(const QString &customText)
{
if (m_waitDlg == nullptr || m_textLabel == nullptr)
return;
if (customText.isEmpty())
m_textLabel->setText(tr("Waiting for server reply..."));
else
m_textLabel->setText(customText);
}
void LtsProgressDialogHelper::setParentWidget(QWidget *newParent)
{
m_parentWidget = newParent;
if (m_waitDlg)
{
m_waitDlg->setParent(newParent);
QTimer::singleShot(0, m_waitDlg.data(), &LtsFramelessDialog::onUpdateGeometry);
}
}
void LtsProgressDialogHelper::slotShowWaitForReplyWindow()
{
if (m_waitDlg)
m_waitDlg->deleteLater();
m_waitDlg = new LtsFramelessDialog(m_parentWidget, Behaviour::Modal);
QHBoxLayout *l = new QHBoxLayout(m_waitDlg);
QProgressBar *pb = new QProgressBar(m_waitDlg);
pb->setMaximum(0);
pb->setValue(-1);
l->addWidget(pb);
m_textLabel = new QLabel(m_waitDlg);
setCustomText();
l->addWidget(m_textLabel);
m_waitDlg->setLayout(l);
m_waitDlg->show();
m_waitDlg->raise();
}
void LtsProgressDialogHelper::slotStopWaitForReplyWindow(const ReplyResult &replyResult, const QString &replyString)
{
if (m_waitDlg == nullptr)
{
return;
}
m_waitDlg->deleteLater();
m_waitDlg = nullptr;
QString resultText = tr("Unknown result (%1)!").arg((int)replyResult);
switch (replyResult)
{
case ReplyResult::Close:
{
return;
}
case ReplyResult::Success:
{
resultText = tr("Operation was successful");
break;
}
case ReplyResult::Failure:
{
resultText = tr("Operation has failed!\nReason: '%1'").arg(replyString);
break;
}
case ReplyResult::TimeOut:
{
resultText = tr("Operation has timed out and could not be processed! Please try again later");
break;
}
}
m_waitDlg = new LtsFramelessDialog(m_parentWidget, Behaviour::Modal);
QVBoxLayout *newLayout = new QVBoxLayout(m_waitDlg);
newLayout->addWidget(new QLabel(resultText, m_waitDlg));
QPushButton *btn = new QPushButton(tr("OK"),m_waitDlg);
connect(btn, &QPushButton::clicked,
this, &LtsProgressDialogHelper::accept);
newLayout->addWidget(btn);
m_waitDlg->setLayout(newLayout);
m_waitDlg->show();
}
void LtsProgressDialogHelper::accept()
{
m_waitDlg->accept();
m_waitDlg->deleteLater();
m_waitDlg = nullptr;
emit accepted();
}
}
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include "lts_widgets_export.h"
#include <QObject>
#include <QPointer>
class QLabel;
class QWidget;
namespace LtsWidgets
{
class LtsFramelessDialog;
class LTSWIDGETS_EXPORT LtsProgressDialogHelper : public QObject
{
Q_OBJECT
public:
enum class ReplyResult
{
Close = 0,
Success,
Failure,
TimeOut,
};
explicit LtsProgressDialogHelper(QWidget *parent = nullptr);
~LtsProgressDialogHelper();
bool isShown() const { return !!m_waitDlg; }
void setCustomText(const QString &customText = QString());
void setParentWidget(QWidget *newParent);
public slots:
void slotShowWaitForReplyWindow();
void slotStopWaitForReplyWindow(const LtsWidgets::LtsProgressDialogHelper::ReplyResult &replyResult = ReplyResult::Close ,
const QString &replyString = QString());
private:
QPointer<LtsFramelessDialog> m_waitDlg;
QWidget *m_parentWidget;
QPointer<QLabel> m_textLabel;
signals:
void accepted();
private slots:
void accept();
};
}
+823
View File
@@ -0,0 +1,823 @@
#include "lts_range_slider.h"
#include <QDebug>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QStyleOptionSlider>
#include <QStylePainter>
#include <QStyle>
#include <QToolTip>
namespace LtsWidgets
{
class LtsRangeSliderPrivate
{
Q_DECLARE_PUBLIC(LtsRangeSlider)
protected:
LtsRangeSlider *const q_ptr;
public:
enum Handle
{
NoHandle = 0x0,
MinimumHandle = 0x1,
MaximumHandle = 0x2
};
Q_DECLARE_FLAGS(Handles, Handle)
explicit LtsRangeSliderPrivate(LtsRangeSlider &object);
void init();
Handle handleAtPos(const QPoint &pos, QRect &handleRect) const;
int pixelPosToRangeValue(int pos) const;
int pixelPosFromRangeValue(int val) const;
void drawMinimumSlider(QStylePainter *painter) const;
void drawMaximumSlider(QStylePainter *painter) const;
int m_minimumValue = 0;
int m_maximumValue = 100;
int m_minimumPosition = 0;
int m_maximumPosition = 100;
QStyle::SubControl m_minimumSliderSelected = QStyle::SC_None;
QStyle::SubControl m_maximumSliderSelected = QStyle::SC_None;
int m_subclassClickOffset = 0;
int m_subclassPosition = 0;
float m_subclassWidth = 0;
LtsRangeSliderPrivate::Handles m_selectedHandles = {};
bool m_symmetricMoves = false;
QString m_handleToolTip;
private:
Q_DISABLE_COPY(LtsRangeSliderPrivate)
};
LtsRangeSliderPrivate::LtsRangeSliderPrivate(LtsRangeSlider &object)
: q_ptr(&object)
{}
void LtsRangeSliderPrivate::init()
{
Q_Q(LtsRangeSlider);
m_minimumValue = q->minimum();
m_maximumValue = q->maximum();
m_minimumPosition = q->minimum();
m_maximumPosition = q->maximum();
q->connect(q, &LtsRangeSlider::rangeChanged, q, &LtsRangeSlider::onRangeChanged);
}
LtsRangeSliderPrivate::Handle LtsRangeSliderPrivate::handleAtPos(const QPoint &pos, QRect &handleRect)const
{
Q_Q(const LtsRangeSlider);
QStyleOptionSlider option;
q->initStyleOption(&option);
option.sliderPosition = m_minimumPosition;
option.sliderValue = m_minimumValue;
QStyle::SubControl minimumControl = q->style()->hitTestComplexControl(
QStyle::CC_Slider, &option, pos, q);
QRect minimumHandleRect = q->style()->subControlRect(
QStyle::CC_Slider, &option, QStyle::SC_SliderHandle, q);
option.sliderPosition = m_maximumPosition;
option.sliderValue = m_maximumValue;
QStyle::SubControl maximumControl = q->style()->hitTestComplexControl(QStyle::CC_Slider, &option, pos, q);
QRect maximumHandleRect = q->style()->subControlRect(QStyle::CC_Slider, &option, QStyle::SC_SliderHandle, q);
if (minimumControl == QStyle::SC_SliderHandle &&
maximumControl == QStyle::SC_SliderHandle)
{
int minDist = 0;
int maxDist = 0;
if (q->orientation() == Qt::Horizontal)
{
minDist = pos.x() - minimumHandleRect.left();
maxDist = maximumHandleRect.right() - pos.x();
}
else
{
minDist = minimumHandleRect.bottom() - pos.y();
maxDist = pos.y() - maximumHandleRect.top();
}
Q_ASSERT(minDist >= 0 && maxDist >= 0);
minimumControl = minDist < maxDist ? minimumControl : QStyle::SC_None;
}
if (maximumControl == QStyle::SC_SliderHandle)
{
handleRect = maximumHandleRect;
return MaximumHandle;
}
else if (minimumControl == QStyle::SC_SliderHandle)
{
handleRect = minimumHandleRect;
return MinimumHandle;
}
handleRect = minimumHandleRect.united(maximumHandleRect);
return NoHandle;
}
int LtsRangeSliderPrivate::pixelPosToRangeValue(int pos) const
{
Q_Q(const LtsRangeSlider);
QStyleOptionSlider option;
q->initStyleOption(&option);
QRect gr = q->style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderGroove,
q);
QRect sr = q->style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderHandle,
q);
int sliderMin, sliderMax, sliderLength;
if (option.orientation == Qt::Horizontal)
{
sliderLength = sr.width();
sliderMin = gr.x();
sliderMax = gr.right() - sliderLength + 1;
}
else
{
sliderLength = sr.height();
sliderMin = gr.y();
sliderMax = gr.bottom() - sliderLength + 1;
}
return QStyle::sliderValueFromPosition(q->minimum(),
q->maximum(),
pos - sliderMin,
sliderMax - sliderMin,
option.upsideDown);
}
int LtsRangeSliderPrivate::pixelPosFromRangeValue(int val) const
{
Q_Q(const LtsRangeSlider);
QStyleOptionSlider option;
q->initStyleOption(&option);
QRect gr = q->style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderGroove,
q);
QRect sr = q->style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderHandle,
q);
int sliderMin, sliderMax, sliderLength;
if (option.orientation == Qt::Horizontal)
{
sliderLength = sr.width();
sliderMin = gr.x();
sliderMax = gr.right() - sliderLength + 1;
}
else
{
sliderLength = sr.height();
sliderMin = gr.y();
sliderMax = gr.bottom() - sliderLength + 1;
}
return QStyle::sliderPositionFromValue(q->minimum(),
q->maximum(),
val,
sliderMax - sliderMin,
option.upsideDown) + sliderMin;
}
void LtsRangeSliderPrivate::drawMinimumSlider(QStylePainter *painter) const
{
Q_Q(const LtsRangeSlider);
QStyleOptionSlider option;
q->initMinimumSliderStyleOption(&option);
option.subControls = QStyle::SC_SliderHandle;
option.sliderValue = m_minimumValue;
option.sliderPosition = m_minimumPosition;
if (q->isMinimumSliderDown())
{
option.activeSubControls = QStyle::SC_SliderHandle;
option.state |= QStyle::State_Sunken;
}
#ifdef Q_OS_MAC
QRect clip = q->style()->subControlRect(QStyle::CC_Slider, &option,
QStyle::SC_SliderHandle, q);
painter->setClipRect(clip);
#endif
painter->drawComplexControl(QStyle::CC_Slider, option);
}
void LtsRangeSliderPrivate::drawMaximumSlider(QStylePainter *painter) const
{
Q_Q(const LtsRangeSlider);
QStyleOptionSlider option;
q->initMaximumSliderStyleOption(&option);
option.subControls = QStyle::SC_SliderHandle;
option.sliderValue = m_maximumValue;
option.sliderPosition = m_maximumPosition;
if (q->isMaximumSliderDown())
{
option.activeSubControls = QStyle::SC_SliderHandle;
option.state |= QStyle::State_Sunken;
}
#ifdef Q_OS_MAC
QRect clip = q->style()->subControlRect(QStyle::CC_Slider, &option,
QStyle::SC_SliderHandle, q);
painter->setClipRect(clip);
#endif
painter->drawComplexControl(QStyle::CC_Slider, option);
}
LtsRangeSlider::LtsRangeSlider(Qt::Orientation o,
QWidget *parent)
: QSlider(o, parent)
, d_ptr(new LtsRangeSliderPrivate(*this))
{
Q_D(LtsRangeSlider);
d->init();
}
LtsRangeSlider::LtsRangeSlider(LtsRangeSliderPrivate *impl, Qt::Orientation o,
QWidget *parent)
: QSlider(o, parent)
, d_ptr(impl)
{
Q_D(LtsRangeSlider);
d->init();
}
LtsRangeSlider::~LtsRangeSlider()
{
}
int LtsRangeSlider::minimumValue() const
{
Q_D(const LtsRangeSlider);
return d->m_minimumValue;
}
void LtsRangeSlider::setMinimumValue(int min)
{
Q_D(LtsRangeSlider);
setValues(min, qMax(d->m_maximumValue, min));
}
int LtsRangeSlider::maximumValue() const
{
Q_D(const LtsRangeSlider);
return d->m_maximumValue;
}
void LtsRangeSlider::setMaximumValue(int max)
{
Q_D(LtsRangeSlider);
setValues(qMin(d->m_minimumValue, max), max);
}
void LtsRangeSlider::setValues(int min, int max)
{
Q_D(LtsRangeSlider);
const int minValue = qBound(minimum(), qMin(min, max), maximum());
const int maxValue = qBound(minimum(), qMax(min, max), maximum());
bool emitMinValChanged = (minValue != d->m_minimumValue);
bool emitMaxValChanged = (maxValue != d->m_maximumValue);
d->m_minimumValue = minValue;
d->m_maximumValue = maxValue;
bool emitMinPosChanged = (minValue != d->m_minimumPosition);
bool emitMaxPosChanged = (maxValue != d->m_maximumPosition);
d->m_minimumPosition = minValue;
d->m_maximumPosition = maxValue;
if (isSliderDown())
{
if (emitMinPosChanged || emitMaxPosChanged)
emit positionsChanged(d->m_minimumPosition, d->m_maximumPosition);
if (emitMinPosChanged)
emit minimumPositionChanged(d->m_minimumPosition);
if (emitMaxPosChanged)
emit maximumPositionChanged(d->m_maximumPosition);
}
if (emitMinValChanged || emitMaxValChanged)
emit valuesChanged(d->m_minimumValue, d->m_maximumValue);
if (emitMinValChanged)
emit minimumValueChanged(d->m_minimumValue);
if (emitMaxValChanged)
emit maximumValueChanged(d->m_maximumValue);
if (emitMinPosChanged || emitMaxPosChanged ||
emitMinValChanged || emitMaxValChanged)
update();
}
int LtsRangeSlider::minimumPosition() const
{
Q_D(const LtsRangeSlider);
return d->m_minimumPosition;
}
int LtsRangeSlider::maximumPosition() const
{
Q_D(const LtsRangeSlider);
return d->m_maximumPosition;
}
void LtsRangeSlider::setMinimumPosition(int min)
{
Q_D(const LtsRangeSlider);
setPositions(min, qMax(min, d->m_maximumPosition));
}
void LtsRangeSlider::setMaximumPosition(int max)
{
Q_D(const LtsRangeSlider);
setPositions(qMin(d->m_minimumPosition, max), max);
}
void LtsRangeSlider::setPositions(int min, int max)
{
Q_D(LtsRangeSlider);
const int minPosition = qBound(minimum(), qMin(min, max), maximum());
const int maxPosition = qBound(minimum(), qMax(min, max), maximum());
bool emitMinPosChanged = (minPosition != d->m_minimumPosition);
bool emitMaxPosChanged = (maxPosition != d->m_maximumPosition);
if (!emitMinPosChanged && !emitMaxPosChanged)
return;
d->m_minimumPosition = minPosition;
d->m_maximumPosition = maxPosition;
if (!hasTracking())
update();
if (isSliderDown())
{
if (emitMinPosChanged)
emit minimumPositionChanged(d->m_minimumPosition);
if (emitMaxPosChanged)
emit maximumPositionChanged(d->m_maximumPosition);
if (emitMinPosChanged || emitMaxPosChanged)
emit positionsChanged(d->m_minimumPosition, d->m_maximumPosition);
}
if (hasTracking())
{
triggerAction(SliderMove);
setValues(d->m_minimumPosition, d->m_maximumPosition);
}
}
void LtsRangeSlider::setSymmetricMoves(bool symmetry)
{
Q_D(LtsRangeSlider);
d->m_symmetricMoves = symmetry;
}
bool LtsRangeSlider::symmetricMoves() const
{
Q_D(const LtsRangeSlider);
return d->m_symmetricMoves;
}
void LtsRangeSlider::onRangeChanged(int minimum, int maximum)
{
Q_UNUSED(minimum);
Q_UNUSED(maximum);
Q_D(LtsRangeSlider);
setValues(d->m_minimumValue, d->m_maximumValue);
}
void LtsRangeSlider::paintEvent(QPaintEvent *)
{
Q_D(LtsRangeSlider);
QStyleOptionSlider option;
initStyleOption(&option);
QStylePainter painter(this);
painter.setPen(Qt::lightGray);
if (option.orientation == Qt::Horizontal)
{
painter.drawLine(option.rect.left(), option.rect.top(), option.rect.left(), option.rect.bottom());
painter.drawRect(option.rect.left(), option.rect.center().y() - 1, option.rect.right() - option.rect.left(), 3);
painter.drawLine(option.rect.right(), option.rect.top(), option.rect.right(), option.rect.bottom());
}
else
{
painter.drawLine(option.rect.left(), option.rect.top(), option.rect.right(), option.rect.top());
painter.drawRect(option.rect.center().x() - 1, option.rect.top(), 3, option.rect.top() - option.rect.bottom());
painter.drawLine(option.rect.center().x(), option.rect.top(), option.rect.center().x(), option.rect.bottom());
painter.drawLine(option.rect.left(), option.rect.bottom(), option.rect.right(), option.rect.bottom());
}
option.subControls = QStyle::SC_SliderGroove;
option.sliderValue = minimum() - maximum();
option.sliderPosition = minimum() - maximum();
option.subControls &= ~QStyle::SC_SliderGroove;
painter.drawComplexControl(QStyle::CC_Slider, option);
option.subControls |= QStyle::SC_SliderGroove;
option.sliderPosition = d->m_minimumPosition;
const QRect lr = style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderHandle,
this);
option.sliderPosition = d->m_maximumPosition;
const QRect ur = style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderHandle,
this);
QRect sr = style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderGroove,
this);
QRect rangeBox;
if (option.orientation == Qt::Horizontal)
{
rangeBox = QRect(QPoint(qMin(lr.center().x(), ur.center().x()), sr.center().y() - 2),
QPoint(qMax(lr.center().x(), ur.center().x()), sr.center().y() + 1));
}
else
{
rangeBox = QRect(QPoint(sr.center().x() - 2, qMin(lr.center().y(), ur.center().y())),
QPoint(sr.center().x() + 1, qMax(lr.center().y(), ur.center().y())));
}
QRect groove = style()->subControlRect(QStyle::CC_Slider,
&option,
QStyle::SC_SliderGroove,
this);
groove.adjust(0, 0, -1, 0);
QColor highlight = palette().color(QPalette::Normal, QPalette::Highlight);
QLinearGradient gradient;
if (option.orientation == Qt::Horizontal)
gradient = QLinearGradient(groove.center().x(), groove.top(), groove.center().x(), groove.bottom());
else
gradient = QLinearGradient(groove.left(), groove.center().y(), groove.right(), groove.center().y());
gradient.setColorAt(0, highlight.darker(120));
gradient.setColorAt(1, highlight.lighter(160));
painter.setPen(QPen(highlight.darker(150), 0));
painter.setBrush(gradient);
painter.drawRect(rangeBox.intersected(groove));
if (isMinimumSliderDown())
{
painter.setClipRect(ur);
d->drawMaximumSlider(&painter);
painter.setClipRect(lr);
d->drawMinimumSlider(&painter);
}
else
{
painter.setClipRect(lr);
d->drawMinimumSlider(&painter);
painter.setClipRect(ur);
d->drawMaximumSlider(&painter);
}
}
void LtsRangeSlider::mousePressEvent(QMouseEvent *ev)
{
Q_D(LtsRangeSlider);
if (minimum() == maximum() || (ev->buttons() ^ ev->button()))
{
ev->ignore();
return;
}
int mepos = orientation() == Qt::Horizontal ? ev->pos().x() : ev->pos().y();
QStyleOptionSlider option;
initStyleOption(&option);
QRect handleRect;
LtsRangeSliderPrivate::Handle handle_ = d->handleAtPos(ev->pos(), handleRect);
if (handle_ != LtsRangeSliderPrivate::NoHandle)
{
if (ev->buttons() == Qt::RightButton)
{
d->m_subclassPosition = (d->m_minimumPosition + d->m_maximumPosition) / 2.;
d->m_subclassClickOffset = mepos - d->pixelPosFromRangeValue(d->m_subclassPosition);
d->m_subclassWidth = (d->m_maximumPosition - d->m_minimumPosition) / 2.;
setSliderDown(true);
if (!isMinimumSliderDown() || !isMaximumSliderDown())
{
d->m_selectedHandles = QFlags<LtsRangeSliderPrivate::Handle>(LtsRangeSliderPrivate::MinimumHandle) |
QFlags<LtsRangeSliderPrivate::Handle>(LtsRangeSliderPrivate::MaximumHandle);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &option, QStyle::SC_SliderGroove, this);
update(handleRect.united(sr));
}
ev->accept();
return;
}
d->m_subclassPosition = (handle_ == LtsRangeSliderPrivate::MinimumHandle) ? d->m_minimumPosition : d->m_maximumPosition;
d->m_subclassClickOffset = mepos - (orientation() == Qt::Horizontal ? handleRect.left() : handleRect.top());
setSliderDown(true);
if (d->m_selectedHandles != handle_)
{
d->m_selectedHandles = handle_;
update(handleRect);
}
ev->accept();
return;
}
QStyle::SubControl control = style()->hitTestComplexControl(QStyle::CC_Slider, &option, ev->pos(), this);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &option, QStyle::SC_SliderGroove, this);
int minCenter = (orientation() == Qt::Horizontal ? handleRect.left() : handleRect.top());
int maxCenter = (orientation() == Qt::Horizontal ? handleRect.right() : handleRect.bottom());
if (control == QStyle::SC_SliderGroove && mepos > minCenter && mepos < maxCenter)
{
d->m_subclassPosition = (d->m_minimumPosition + d->m_maximumPosition) / 2.;
d->m_subclassClickOffset = mepos - d->pixelPosFromRangeValue(d->m_subclassPosition);
d->m_subclassWidth = (d->m_maximumPosition - d->m_minimumPosition) / 2.;
setSliderDown(true);
if (!isMinimumSliderDown() || !isMaximumSliderDown())
{
d->m_selectedHandles = QFlags<LtsRangeSliderPrivate::Handle>(LtsRangeSliderPrivate::MinimumHandle) |
QFlags<LtsRangeSliderPrivate::Handle>(LtsRangeSliderPrivate::MaximumHandle);
update(handleRect.united(sr));
}
ev->accept();
return;
}
ev->ignore();
}
void LtsRangeSlider::mouseMoveEvent(QMouseEvent *ev)
{
Q_D(LtsRangeSlider);
if (!d->m_selectedHandles)
{
ev->ignore();
return;
}
int mepos = orientation() == Qt::Horizontal ? ev->pos().x() : ev->pos().y();
QStyleOptionSlider option;
initStyleOption(&option);
if (isMinimumSliderDown() && isMaximumSliderDown())
{
int newPosition = d->pixelPosToRangeValue(mepos);
int newMinPosition = newPosition - static_cast<int>(d->m_subclassWidth);
int newMaxPosition = newPosition + static_cast<int>(d->m_subclassWidth + .5);
if (newMinPosition < minimum())
{
newMinPosition = minimum();
newMaxPosition = newMinPosition + (d->m_maximumPosition - d->m_minimumPosition);
}
else if (newMaxPosition > maximum())
{
newMaxPosition = maximum();
newMinPosition = newMaxPosition - (d->m_maximumPosition - d->m_minimumPosition);
}
setPositions(newMinPosition, newMaxPosition);
ev->accept();
return;
}
const int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &option, this);
int newPosition = d->pixelPosToRangeValue(mepos - d->m_subclassClickOffset);
if (m >= 0)
{
const QRect r = rect().adjusted(-m, -m, m, m);
if (!r.contains(ev->pos()))
newPosition = d->m_subclassPosition;
}
if (isMinimumSliderDown() && !isMaximumSliderDown())
{
double newMinPos = qMin(newPosition, d->m_maximumPosition);
setPositions(newMinPos, d->m_maximumPosition + (d->m_symmetricMoves ? d->m_minimumPosition - newMinPos : 0));
}
else if (isMaximumSliderDown() && !isMinimumSliderDown())
{
double newMaxPos = qMax(d->m_minimumPosition, newPosition);
setPositions(d->m_minimumPosition - (d->m_symmetricMoves ? newMaxPos - d->m_maximumPosition : 0), newMaxPos);
}
ev->accept();
}
void LtsRangeSlider::mouseReleaseEvent(QMouseEvent *ev)
{
Q_D(LtsRangeSlider);
QSlider::mouseReleaseEvent(ev);
setSliderDown(false);
d->m_selectedHandles = {};
update();
}
bool LtsRangeSlider::isMinimumSliderDown() const
{
Q_D(const LtsRangeSlider);
return d->m_selectedHandles & LtsRangeSliderPrivate::MinimumHandle;
}
bool LtsRangeSlider::isMaximumSliderDown() const
{
Q_D(const LtsRangeSlider);
return d->m_selectedHandles & LtsRangeSliderPrivate::MaximumHandle;
}
void LtsRangeSlider::initMinimumSliderStyleOption(QStyleOptionSlider *option) const
{
initStyleOption(option);
}
void LtsRangeSlider::initMaximumSliderStyleOption(QStyleOptionSlider *option) const
{
initStyleOption(option);
}
QString LtsRangeSlider::handleToolTip()const
{
Q_D(const LtsRangeSlider);
return d->m_handleToolTip;
}
void LtsRangeSlider::setHandleToolTip(const QString &toolTip)
{
Q_D(LtsRangeSlider);
d->m_handleToolTip = toolTip;
}
bool LtsRangeSlider::event(QEvent *event)
{
Q_D(LtsRangeSlider);
switch (event->type())
{
case QEvent::ToolTip:
{
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
QStyleOptionSlider opt;
opt.sliderPosition = d->m_minimumPosition;
opt.sliderValue = d->m_minimumValue;
initStyleOption(&opt);
QStyle::SubControl hoveredControl = style()->hitTestComplexControl(QStyle::CC_Slider, &opt, helpEvent->pos(), this);
if (!d->m_handleToolTip.isEmpty() && hoveredControl == QStyle::SC_SliderHandle)
{
QToolTip::showText(helpEvent->globalPos(), d->m_handleToolTip.arg(minimumValue()));
event->accept();
return true;
}
opt.sliderPosition = d->m_maximumPosition;
opt.sliderValue = d->m_maximumValue;
initStyleOption(&opt);
hoveredControl = style()->hitTestComplexControl(QStyle::CC_Slider, &opt, helpEvent->pos(), this);
if (!d->m_handleToolTip.isEmpty() && hoveredControl == QStyle::SC_SliderHandle)
{
QToolTip::showText(helpEvent->globalPos(), d->m_handleToolTip.arg(maximumValue()));
event->accept();
return true;
}
}
default:
break;
}
return QSlider::event(event);
}
}
+194
View File
@@ -0,0 +1,194 @@
#pragma once
#include "lts_widgets_export.h"
#include <QSlider>
namespace LtsWidgets
{
class LtsRangeSliderPrivate;
class LTSWIDGETS_EXPORT LtsRangeSlider : public QSlider
{
Q_OBJECT
Q_PROPERTY(int minimumValue READ minimumValue WRITE setMinimumValue)
Q_PROPERTY(int maximumValue READ maximumValue WRITE setMaximumValue)
Q_PROPERTY(int minimumPosition READ minimumPosition WRITE setMinimumPosition)
Q_PROPERTY(int maximumPosition READ maximumPosition WRITE setMaximumPosition)
Q_PROPERTY(bool symmetricMoves READ symmetricMoves WRITE setSymmetricMoves)
Q_PROPERTY(QString handleToolTip READ handleToolTip WRITE setHandleToolTip)
public:
explicit LtsRangeSlider(Qt::Orientation o, QWidget *parent = nullptr);
explicit LtsRangeSlider(QWidget *parent = nullptr)
: LtsRangeSlider(Qt::Vertical, parent)
{}
~LtsRangeSlider();
int minimumValue() const;
int maximumValue() const;
int minimumPosition() const;
void setMinimumPosition(int min);
int maximumPosition() const;
void setMaximumPosition(int max);
void setPositions(int min, int max);
bool symmetricMoves() const;
void setSymmetricMoves(bool symmetry);
QString handleToolTip() const;
void setHandleToolTip(const QString &toolTip);
bool isMinimumSliderDown() const;
bool isMaximumSliderDown() const;
Q_SIGNALS:
void minimumValueChanged(int min);
void maximumValueChanged(int max);
void valuesChanged(int min, int max);
void minimumPositionChanged(int min);
void maximumPositionChanged(int max);
void positionsChanged(int min, int max);
public Q_SLOTS:
void setMinimumValue(int min);
void setMaximumValue(int max);
void setValues(int min, int max);
protected Q_SLOTS:
void onRangeChanged(int minimum, int maximum);
protected:
LtsRangeSlider(LtsRangeSliderPrivate *impl, Qt::Orientation o, QWidget *parent = nullptr);
void mousePressEvent(QMouseEvent *ev) override;
void mouseMoveEvent(QMouseEvent *ev) override;
void mouseReleaseEvent(QMouseEvent *ev) override;
void paintEvent(QPaintEvent *ev) override;
void initMinimumSliderStyleOption(QStyleOptionSlider *option) const;
void initMaximumSliderStyleOption(QStyleOptionSlider *option) const;
bool event(QEvent *event) override;
protected:
QScopedPointer<LtsRangeSliderPrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(LtsRangeSlider)
Q_DISABLE_COPY(LtsRangeSlider)
};
}
+212
View File
@@ -0,0 +1,212 @@
#include "lts_selection_popup.h"
#include "ui_lts_selection_popup.h"
#include "lts_base.h"
#include <QSortFilterProxyModel>
#include <QAbstractItemModel>
#include <QRadioButton>
#include <QScrollBar>
#ifdef NEVER
# include <QDebug>
#endif
namespace LtsWidgets
{
class RadioButton : public QRadioButton
{
Q_OBJECT
public:
explicit RadioButton(int row, const QString &text)
: QRadioButton(text)
, m_row(row)
{}
int row() const { return m_row; }
signals:
void doubleClickEvent();
private:
int m_row;
void mouseDoubleClickEvent(QMouseEvent *) override
{
emit doubleClickEvent();
}
};
LtsSelectionPopup::LtsSelectionPopup(QAbstractItemModel* model,
int currentIndex,
QWidget *parent)
: LtsFramelessDialog(parent, Behaviour::Popup)
, m_ui(new Ui::LtsSelectionPopup)
, m_currentIndex(currentIndex)
, m_firstIndex(currentIndex)
, m_filter(new QSortFilterProxyModel(this))
, m_valid(false)
{
m_ui->setupUi(this);
m_filter->setSourceModel(model);
m_filter->setFilterCaseSensitivity(Qt::CaseInsensitive);
slotFilterChanged();
#ifdef TABLET_MODE
m_ui->leSearch->setVisible(false);
m_ui->label->setVisible(false);
#endif
connect(m_ui->pbCancel, &QPushButton::clicked, this, &LtsSelectionPopup::reject);
connect(m_ui->pbSelect, &QPushButton::clicked, this, &LtsSelectionPopup::accept);
connect(m_ui->leSearch, &QLineEdit::textEdited,
this, &LtsSelectionPopup::slotFilterChanged);
#ifdef NEVER
connect(this, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::currentIndexChanged), this, [](int idx){
qCritical() << " LtsSelectionPopup: called: currentIndexChanged(int), idx=" << idx;
});
connect(this, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::activated), this, [](int idx){
qCritical() << " LtsSelectionPopup: called: activated(int), idx=" << idx;
});
#endif
}
LtsSelectionPopup::~LtsSelectionPopup()
{
delete m_ui;
}
void LtsSelectionPopup::slotFilterChanged()
{
m_filter->setFilterWildcard(m_ui->leSearch->text().count() ? m_ui->leSearch->text() : QStringLiteral("*") );
refresh();
}
void LtsSelectionPopup::refresh()
{
m_valid = false;
qDeleteAll(m_ui->itemLayoutWidget->findChildren<RadioButton*>());
QLayoutItem *tem = nullptr;
if (m_ui->itemLayoutWidget->layout()->count() > 0)
{
tem = m_ui->itemLayoutWidget->layout()->takeAt(0);
}
int count = m_filter->rowCount();
for (int i = 0; i < count; i++)
{
int realRow = m_filter->mapToSource(m_filter->index(i, 0)).row();
RadioButton *rbItem = new RadioButton(realRow, m_filter->data(m_filter->index(i, 0)).toString());
int disable = m_filter->data(m_filter->index(i, 0), Qt::UserRole-1).toInt();
if (disable == 1)
rbItem->setEnabled(false);
m_ui->itemLayoutWidget->layout()->addWidget(rbItem);
if (realRow == m_currentIndex)
{
rbItem->setChecked(true);
m_valid = true;
}
connect(rbItem, &RadioButton::doubleClickEvent,
this, &LtsSelectionPopup::accept);
connect(rbItem, &RadioButton::toggled,
this, [this](bool checked)
{
if (checked)
m_ui->pbSelect->setEnabled(true);
});
}
if (tem)
m_ui->itemLayoutWidget->layout()->addItem(tem);
if (count == 1)
m_valid = true;
m_ui->pbSelect->setEnabled(m_valid);
}
void LtsSelectionPopup::showEvent(QShowEvent *event)
{
LtsFramelessDialog::showEvent(event);
m_ui->leSearch->setFocus();
resize(sizeHint().width() + m_ui->scrollArea->horizontalScrollBar()->height() , sizeHint().height());
}
void LtsSelectionPopup::selectItem(int row, bool bCurrentIndexChanged, bool bActivated)
{
if (bCurrentIndexChanged)
emit currentIndexChanged(row);
if (bActivated)
emit activated(row);
m_ui->pbSelect->setEnabled(true);
LtsFramelessDialog::accept();
}
void LtsSelectionPopup::accept()
{
const QList<RadioButton *> items = m_ui->itemLayoutWidget->findChildren<RadioButton *>();
int count = items.count();
for (int i = 0; i < count; i++)
{
const RadioButton *rb = items.at(i);
if (rb->isChecked())
{
int realRow = m_filter->mapToSource(m_filter->index(i, 0)).row();
bool bCurrentIndexChanged = realRow != m_firstIndex;
bool bActivated = true;
selectItem(realRow, bCurrentIndexChanged, bActivated);
return;
}
}
if (count == 1)
{
const RadioButton *rb = items.at(0);
selectItem(rb->row(), true, true);
return;
}
}
}
#include "lts_selection_popup.moc"
+83
View File
@@ -0,0 +1,83 @@
#pragma once
#include "lts_frameless_dialog.h"
#include "lts_widgets_export.h"
namespace Ui
{
class LtsSelectionPopup;
}
class QAbstractItemModel;
class QSortFilterProxyModel;
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsSelectionPopup : public LtsFramelessDialog
{
Q_OBJECT
public:
LtsSelectionPopup(QAbstractItemModel *model,
int currentIndex,
QWidget *parent = nullptr);
~LtsSelectionPopup();
protected:
void showEvent(QShowEvent *event) override;
private:
Ui::LtsSelectionPopup *m_ui;
int m_currentIndex;
int m_firstIndex;
QSortFilterProxyModel *m_filter;
bool m_valid;
void refresh();
void selectItem(int row, bool bCurrentIndexChanged, bool bActivated);
signals:
void activated(int index);
void currentIndexChanged(int index);
public slots:
void accept() override;
void slotFilterChanged();
};
}
+232
View File
@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsSelectionPopup</class>
<widget class="QDialog" name="LtsSelectionPopup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>193</width>
<height>230</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="lbName">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Select an Item</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>3</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Plugins/Styles/Dark/resources/rme_dark_style.qrc">:/style/show.svg</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leSearch">
<property name="placeholderText">
<string>Search ...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<widget class="QWidget" name="itemLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>177</width>
<height>102</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>800</width>
<height>800</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinAndMaxSize</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>100</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>3</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pbSelect">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>pbSelect</tabstop>
<tabstop>pbCancel</tabstop>
<tabstop>leSearch</tabstop>
</tabstops>
<resources>
<include location="../../Plugins/Styles/Dark/resources/rme_dark_style.qrc"/>
</resources>
<connections/>
</ui>
+173
View File
@@ -0,0 +1,173 @@
#include "lts_spinbox.h"
#include <cmath>
namespace LtsWidgets
{
LtsSpinBox::LtsSpinBox(QWidget *parent)
: QSpinBox(parent)
{
}
QValidator::State LtsSpinBox::validate(QString &input, int &pos) const
{
QIntValidator validator;
for (auto range : m_validRanges)
{
validator.setBottom(range.first);
validator.setTop(range.second);
QValidator::State state = validator.validate(input, pos);
if (state == QValidator::Invalid ||
state == QValidator::Intermediate)
return state;
}
int value = input.toInt();
value -= minimum();
return (value % singleStep() == 0) ? QValidator::Acceptable : QValidator::Intermediate;
}
void LtsSpinBox::fixup(QString &str) const
{
QSpinBox::fixup(str);
if (singleStep() == 1)
return;
bool bOk;
int value = str.toInt(&bOk);
if (!bOk)
return;
int remainder = (value - minimum()) % singleStep();
if (2 * remainder > singleStep())
value += singleStep();
value -= remainder;
if (value > maximum())
value -= singleStep();
str = QString::number(value);
}
bool LtsSpinBox::setExclusionRanges(const QVector<QPair<int,int> > &exclusionRanges, bool preserveCurrentValues)
{
bool retVal = true;
auto newExclusions = exclusionRanges;
if (preserveCurrentValues)
newExclusions += m_exclusions;
for (auto &elem : newExclusions)
{
if (elem.first > elem.second)
{
int tmp = elem.first;
elem.first= elem.second;
elem.second = tmp;
}
}
std::sort(newExclusions.begin(), newExclusions.end(), [](const QPair<int,int> &a, const QPair<int,int> &b) { return a.first < b.first; });
for (int i=0; i<newExclusions.size()-1; ++i)
{
if (newExclusions[i].second >= newExclusions[i+1].first)
{
retVal = false;
break;
}
}
if (!retVal || newExclusions[0].first <= minimum() || newExclusions[newExclusions.size()-1].second >= maximum())
{
if (!preserveCurrentValues)
m_exclusions.clear();
return false;
}
m_exclusions = exclusionRanges;
m_validRanges.clear();
if (m_exclusions[0].first - 1 > minimum())
m_validRanges.append({minimum(), m_exclusions[0].first - 1});
for (int i=0; i<m_exclusions.size()-1; ++i)
{
if (m_exclusions[i].second + 1 < m_exclusions[i+1].first - 1)
m_validRanges.append({m_exclusions[i].second + 1, m_exclusions[i+1].first - 1});
}
if (m_exclusions[m_exclusions.size()-1].second + 1 < maximum())
m_validRanges.append({m_exclusions[0].first - 1, maximum()});
return true;
}
bool LtsSpinBox::addExclusionRange(int min, int max)
{
return setExclusionRanges({{min, max}}, true);
}
void LtsSpinBox::clearExclusionRanges()
{
m_exclusions.clear();
}
LtsDoubleSpinBox::LtsDoubleSpinBox(QWidget *parent)
: QDoubleSpinBox(parent)
{
}
QValidator::State LtsDoubleSpinBox::validate(QString &input, int &pos) const
{
QDoubleValidator validator;
validator.setBottom(minimum());
validator.setTop(maximum());
QValidator::State state = validator.validate(input, pos);
if (state == QValidator::Invalid ||
state == QValidator::Intermediate)
return state;
double value = input.toDouble();
value -= minimum();
return qFuzzyCompare(std::fmod(value, singleStep()), 0.0) ? QValidator::Acceptable : QValidator::Intermediate;
}
void LtsDoubleSpinBox::fixup(QString &str) const
{
QDoubleSpinBox::fixup(str);
if (qFuzzyCompare(singleStep(), pow(10, decimals())))
return;
bool bOk;
double value = str.toDouble(&bOk);
if (!bOk)
return;
double remainder = std::fmod(value - minimum(), singleStep());
if (2 * remainder > singleStep())
value += singleStep();
value -= remainder;
if (value > maximum())
value -= singleStep();
str = QString::number(value, 'f', decimals());
}
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include "lts_widgets_export.h"
#include <QSpinBox>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsSpinBox : public QSpinBox
{
Q_OBJECT
public:
explicit LtsSpinBox(QWidget *parent = nullptr);
~LtsSpinBox() = default;
public slots:
void setValue(int val) { QString valStr = QString::number(val); fixup(valStr); QSpinBox::setValue(valStr.toInt()); }
bool setExclusionRanges(const QVector<QPair<int,int> > &exclusionRanges, bool preserveCurrentValues = false);
bool addExclusionRange(int min, int max);
void clearExclusionRanges();
protected:
QValidator::State validate(QString &input, int &pos) const override;
void fixup(QString &str) const override;
private:
struct
{
bool operator()(const QPair<int,int> &a, const QPair<int,int> &b) const { return a.first < b.first; }
} customless;
QVector<QPair<int,int> > m_exclusions;
QVector<QPair<int,int> > m_validRanges;
};
class LTSWIDGETS_EXPORT LtsDoubleSpinBox : public QDoubleSpinBox
{
Q_OBJECT
public:
explicit LtsDoubleSpinBox(QWidget *parent = nullptr);
~LtsDoubleSpinBox() = default;
public slots:
void setValue(double val) { QString valStr = QString::number(val); fixup(valStr); QDoubleSpinBox::setValue(valStr.toDouble()); }
protected:
QValidator::State validate(QString &input, int &pos) const override;
void fixup(QString &str) const override;
};
}
+81
View File
@@ -0,0 +1,81 @@
#include "lts_splash.h"
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <QCoreApplication>
#include <QFile>
#include <QEvent>
namespace LtsWidgets
{
Splash::Splash()
: QSplashScreen()
, m_done(false)
{
static const auto splashFiles =
{
QStringLiteral(":/project/splash.png"),
QStringLiteral(":/project/splash.jpg"),
};
for (const QString &f : splashFiles)
{
if (!QFile::exists(f))
continue;
setPixmap(QPixmap(f));
break;
}
}
bool Splash::event(QEvent *e)
{
if (e->type() == QEvent::MouseButtonPress ||
e->type() == QEvent::MouseButtonRelease ||
e->type() == QEvent::MouseButtonDblClick)
{
e->ignore();
return false;
}
return QSplashScreen::event(e);
}
void Splash::setMessage(const QString &message)
{
showMessage(message, Qt::AlignRight | Qt::AlignBottom);
}
void Splash::done()
{
if (m_done)
return;
m_done = true;
hide();
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
}
static Splash *s_splashInstance = nullptr;
void Splash::cleanupSplashInstance()
{
delete s_splashInstance;
s_splashInstance = nullptr;
}
Splash *Splash::getInstance()
{
if (!s_splashInstance)
{
s_splashInstance = new Splash;
qAddPostRoutine(&Splash::cleanupSplashInstance);
}
return s_splashInstance;
}
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <LtsWidgets/lts_widgets_export.h>
#include <QSplashScreen>
#include <QObject>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT Splash : public QSplashScreen
{
Q_OBJECT
public:
static Splash* getInstance();
void done();
void setMessage(const QString &message);
private:
Splash();
static void cleanupSplashInstance();
bool event(QEvent *e) override;
bool m_done;
};
}
+57
View File
@@ -0,0 +1,57 @@
#include "lts_splitter.h"
#include "lts_splitter_handle.h"
namespace LtsWidgets
{
LtsSplitter::LtsSplitter(QWidget *parent)
: QSplitter(parent)
{
connect(this, &LtsSplitter::sizesChanged, this, &LtsSplitter::changeSizes);
}
LtsSplitter::~LtsSplitter()
{
}
QSplitterHandle *LtsSplitter::createHandle()
{
LtsSplitterHandle *hand = new LtsSplitterHandle(orientation(), this);
#ifdef TABLET_MODE
setHandleWidth(25);
#else
setHandleWidth(10);
#endif
return hand;
}
void LtsSplitter::collapseChild(const int index)
{
if (children().size() > index)
{
QWidget *widget = static_cast<QWidget*>(children().at(index));
if (widget)
{
QList<int> s = sizes();
s[index] = 0;
setSizes(s);
}
}
}
void LtsSplitter::animate(int handleId)
{
LtsSplitterHandle *handle = dynamic_cast<LtsSplitterHandle*>(this->handle(handleId));
handle->animate();
}
void LtsSplitter::changeSizes(const QList<int> &list)
{
QSplitter::setSizes(list);
}
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "lts_base.h"
#include "lts_widgets_export.h"
#include <QSplitter>
#include <QList>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsSplitter : public QSplitter
{
Q_OBJECT
Q_PROPERTY(QList<int> sizes READ getSizes WRITE setSizes NOTIFY sizesChanged)
public:
explicit LtsSplitter(QWidget *parent = nullptr);
~LtsSplitter();
QSplitterHandle *createHandle();
void collapseChild(const int index);
QList<int> getSizes() const { return sizes(); }
void animate(int handleId);
signals:
void sizesChanged(const QList<int> &newSizes);
public slots:
void changeSizes(const QList<int> &list);
};
}
+87
View File
@@ -0,0 +1,87 @@
#include "lts_splitter_handle.h"
#include <QPainter>
#include <QPaintEvent>
#include <QBrush>
#include <QEvent>
#include <QLinearGradient>
#include <QDebug>
namespace LtsWidgets
{
LtsSplitterHandle::LtsSplitterHandle(Qt::Orientation orientation, QSplitter *parent)
: QSplitterHandle(orientation, parent)
{
auto bgrole = backgroundRole();
QPalette p = palette();
m_endColor = p.color(bgrole);
m_colorAnimation = new QPropertyAnimation(this, "splittercolor");
m_colorAnimation->setDuration(1000);
m_colorAnimation->setStartValue(m_currentColor);
m_colorAnimation->setEndValue(m_endColor);
m_colorAnimation->setLoopCount(2);
connect(m_colorAnimation, &QPropertyAnimation::finished, this, [this]{
m_animate = false;
m_currentColor = m_endColor;
repaint();
});
}
LtsSplitterHandle::~LtsSplitterHandle()
{
}
void LtsSplitterHandle::paintEvent(QPaintEvent *event)
{
if(!m_animate)
{
QSplitterHandle::paintEvent(event);
return;
}
QPainter painter(this);
QLinearGradient gradient;
gradient.setColorAt(0, m_currentColor);
if(orientation() == Qt::Horizontal)
{
gradient.setStart(rect().left(), rect().height()/2);
gradient.setFinalStop(rect().height(), rect().height()/2);
}else
{
gradient.setStart(rect().width()/2, rect().top());
gradient.setFinalStop(rect().width()/2, rect().bottom()/2);
}
painter.fillRect(event->rect(), QBrush(gradient));
}
void LtsSplitterHandle::animate()
{
if (m_colorAnimation->state() == QPropertyAnimation::Running)
return;
m_currentColor = QColor(239,87,50);
m_animate = true;
m_colorAnimation->start();
}
QColor LtsSplitterHandle::splitterColor() const
{
return m_currentColor;
}
void LtsSplitterHandle::setCurrentColor(const QColor &currentcolor)
{
if (currentcolor == m_currentColor)
return;
m_currentColor = currentcolor;
repaint();
}
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include "lts_base.h"
#include "lts_widgets_export.h"
#include <QSplitterHandle>
#include <QList>
#include <QPropertyAnimation>
namespace LtsWidgets
{
class LTSWIDGETS_EXPORT LtsSplitterHandle : public QSplitterHandle
{
Q_OBJECT
Q_PROPERTY(QColor splittercolor READ splitterColor WRITE setCurrentColor DESIGNABLE false)
public:
explicit LtsSplitterHandle(Qt::Orientation orientation, QSplitter *parent = nullptr);
~LtsSplitterHandle();
void paintEvent(QPaintEvent *event) override;
void animate();
QColor splitterColor() const;
void setCurrentColor(const QColor &currentcolor);
private:
bool m_animate {false};
QColor m_endColor {Qt::black};
QColor m_currentColor{QColor(239,87,50)};
QPropertyAnimation *m_colorAnimation;
};
}
+120
View File
@@ -0,0 +1,120 @@
#include "lts_tab_bar.h"
#include "lts_dialog.h"
#include "lts_dialog_helper.h"
#include "lts_events.h"
#include "lts_tab_widget.h"
#include <TabBarTabStyle/tab_bar_tab_style.h>
#include <QCoreApplication>
#include <QMenu>
namespace LtsWidgets
{
LtsTabBar::LtsTabBar(bool isSecondary, QWidget *parent)
: QTabBar(parent)
, m_secondary(isSecondary)
{
setDocumentMode(true);
setTabsClosable(true);
connect(this, &LtsTabBar::currentChanged, this, &LtsTabBar::updateCloseButtonColors);
if (m_secondary)
{
connect(this, &LtsTabBar::customContextMenuRequested,
this, &LtsTabBar::onCustomContextMenuRequested);
setContextMenuPolicy(Qt::CustomContextMenu);
}
}
void LtsTabBar::_internal_closeTab()
{
QObject *object = sender();
int tabToClose = -1;
for (int i = 0; i < count(); i++)
{
if (tabButton(i, QTabBar::RightSide) == object)
{
tabToClose = i;
break;
}
}
if (tabToClose != -1)
emit tabCloseRequested(tabToClose);
}
void LtsTabBar::updateCloseButtonColors(int newIndex)
{
if (newIndex == -1)
newIndex = currentIndex();
for (int i = 0; i < count(); i++)
{
QWidget *w = tabButton(i, QTabBar::RightSide);
CloseButton *cb = qobject_cast<CloseButton *>(w);
if (!cb)
continue;
QColor text;
bool enabled = isTabEnabled(i);
bool selected = (i == newIndex);
bool secondary = m_secondary;
if (enabled)
{
if (selected)
text = (secondary) ? Styles::TabBarTabStyle::secondarySelected : Styles::TabBarTabStyle::primarySelected;
else
text = (secondary) ? Styles::TabBarTabStyle::secondaryNormal : Styles::TabBarTabStyle::primaryNormal;
}
else
text = (secondary) ? Styles::TabBarTabStyle::secondaryDisabled : Styles::TabBarTabStyle::primaryDisabled;
cb->setFontColor(text);
}
}
void LtsTabBar::onCustomContextMenuRequested(const QPoint pos)
{
if (!m_secondary)
return;
QMenu m;
QAction *a = new QAction(tr("Save as image"));
connect(a, &QAction::triggered, this, [this, pos]() { LtsTabBar::onSaveCurrentWidgetAsImage(pos); });
m.addAction(a);
m.exec(mapToGlobal(pos));
}
void LtsTabBar::onSaveCurrentWidgetAsImage(const QPoint pos)
{
int curTab = tabAt(pos);
if (curTab < 0)
curTab = currentIndex();
if (curTab < 0)
return;
LtsTabWidget *tw = qobject_cast<LtsTabWidget*>(parentWidget());
QWidget *w = tw ? tw->widget(curTab) : nullptr;
if (!w)
return;
LtsDialogHelper *helper = qobject_cast<LtsDialogHelper*>(w);
if (helper)
w = helper->getDialog();
SaveImageEvent *ev = new SaveImageEvent(w, w->grab());
ev->setAccepted(false);
QCoreApplication::postEvent(qApp, ev);
}
}
Loaded 100 of 668 files, more files were not shown because too many files have changed in this diff. Show more