Continues migration with DDS, Common
This commit is contained in:
1 parent
9b15cee841
commit
fa48db111e
668 files changed
+111841
-2
No files matched your search
Executable
+210
@@ -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()
|
||||
Executable
+208
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
}
|
||||
Executable
+246
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Executable
+71
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Executable
+49
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+274
@@ -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)
|
||||
Executable
+645
@@ -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"><html><head/><body><p>PROJECT_LOGO</p></body></html></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>
|
||||
+1828
File diff suppressed because it is too large.
Load diff
+346
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+95
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
Executable
+118
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+59
@@ -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;
|
||||
};
|
||||
}
|
||||
Executable
+1785
File diff suppressed because it is too large.
Load diff
Executable
+213
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+43
@@ -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;
|
||||
};
|
||||
}
|
||||
+1792
File diff suppressed because it is too large.
Load diff
+206
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
Executable
+810
@@ -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"
|
||||
Executable
+473
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
Executable
+172
@@ -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"
|
||||
Executable
+51
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+70
@@ -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>
|
||||
Executable
+489
@@ -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"
|
||||
|
||||
Executable
+246
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+31
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
Executable
+60
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+36
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+58
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Executable
+94
@@ -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
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+46
@@ -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
@@ -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
@@ -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 };
|
||||
};
|
||||
Executable
+128
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+61
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
Executable
+116
@@ -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();
|
||||
}
|
||||
Executable
+60
@@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+81
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+28
@@ -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;
|
||||
};
|
||||
}
|
||||
Executable
+135
@@ -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"><Project Logo></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>
|
||||
Executable
+148
@@ -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 ¤tcolor)
|
||||
{
|
||||
if (m_currentcolor == currentcolor)
|
||||
return;
|
||||
m_currentcolor = currentcolor;
|
||||
repaint();
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+117
@@ -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 ¤tcolor);
|
||||
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+133
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Executable
+86
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+50
@@ -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
@@ -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"><html><head/><body><p><span style=" font-size:14pt; font-weight:600; color:#eeeeee;">Error Message</span></p><p><span style=" font-size:14pt; color:#eeeeee;">This is an error message. looooooooooooooooooooong text<br/>With 2 lines!</span></p></body></html></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>
|
||||
Executable
+114
@@ -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"));
|
||||
}
|
||||
}
|
||||
Executable
+42
@@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+247
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+34
@@ -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;
|
||||
};
|
||||
}
|
||||
Executable
+76
@@ -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>&Cancel</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Shift+C</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+339
@@ -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;
|
||||
}
|
||||
Executable
+60
@@ -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);
|
||||
};
|
||||
}
|
||||
Executable
+133
@@ -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();
|
||||
}
|
||||
Executable
+55
@@ -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
@@ -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
@@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+823
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+194
@@ -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
@@ -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"
|
||||
Executable
+83
@@ -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();
|
||||
|
||||
};
|
||||
}
|
||||
Executable
+232
@@ -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>
|
||||
Executable
+173
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+60
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+81
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+28
@@ -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;
|
||||
};
|
||||
}
|
||||
Executable
+57
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+37
@@ -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
@@ -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 ¤tcolor)
|
||||
{
|
||||
if (currentcolor == m_currentColor)
|
||||
return;
|
||||
m_currentColor = currentcolor;
|
||||
repaint();
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+39
@@ -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 ¤tcolor);
|
||||
|
||||
private:
|
||||
bool m_animate {false};
|
||||
QColor m_endColor {Qt::black};
|
||||
QColor m_currentColor{QColor(239,87,50)};
|
||||
QPropertyAnimation *m_colorAnimation;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+120
@@ -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
Reference in new issue
Block a user