452 строки
15 KiB
C++

/*
Copyright (c) 2024 SWD Embedded Systems, Ltd. <http://www.kpda.ru>
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef MAPWIDGET_H
#define MAPWIDGET_H
#include <QDebug>
#include <QGestureEvent>
#include <QGridLayout>
#include <QLabel>
#include <QMessageBox>
#include <QPanGesture>
#include <QPinchGesture>
#include <QPointer>
#include <QPushButton>
#include <QSwipeGesture>
#include <gis/gishelper.h>
#include <gis/gisrender.h>
#include "distancemeter.h"
#include "objectinfo.h"
#include "userdialog.h"
#define DEBUG_TOUCH
#define MAPWIDGET_PREFIX const_cast<char*>("[MapWidget] ")
class MapWidget : public QWidget,
public SMCallbacks,
public DBCallbacks
{
Q_OBJECT
public:
friend class MapTabWidget;
explicit MapWidget( gis_core_connection_t *connection, int idx,
QWidget *parent = 0 );
~MapWidget();
void initialize();
void databufferValidityChangedCallback( bool isValid )
{
if ( !isValid )
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_INFO, MAPWIDGET_PREFIX,
"Databuffer is invalid [%s()]", __FUNCTION__ );
else
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_INFO, MAPWIDGET_PREFIX,
"Databuffer is valid [%s()]", __FUNCTION__ );
}
void errorCallback( int err_code )
{
switch ( err_code )
{
case ETIME:
{
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_INFO, MAPWIDGET_PREFIX,
"Too long drawing [%s()]", __FUNCTION__ );
break;
}
default:
break;
}
}
void surfaceCompleteCallback( int32_t surface_z_idx )
{
Q_UNUSED( surface_z_idx );
update();
}
void mapLayerCompleteCallback( int32_t rsc_key, int32_t layer_number )
{
Q_UNUSED( rsc_key );
Q_UNUSED( layer_number );
update();
}
bool mapLayerRequiredCallback( int32_t classifier_key, int32_t layer_number )
{
for ( size_t idx = 0; idx < classifiers.size(); idx++ )
{
ClassifierInfo &info = classifiers[idx];
if ( info.idx == classifier_key )
{
for ( size_t layer_idx = 0; layer_idx < classifiers[idx].layers.size(); layer_idx++ )
{
if ( layer_number == classifiers[idx].layers[layer_idx].layerNumber )
return info.layers[layer_idx].layerIsActive;
}
}
}
return true;
}
bool mapClassRequiredCallback( int32_t classifier_key, gis_core_class_code_t class_code )
{
Q_UNUSED( classifier_key );
Q_UNUSED( class_code );
return true;
}
void updateProjectionParameters();
void updateScreenParameters();
void setIndex( int index );
int getIndex();
gis_render_sm_context_t getSurfacemanagerContext();
float brightness = 0;
float contrast = 0;
uint32_t invalidRasterHeightColor;
double maxRasterHeight;
double minRasterHeight;
bool isAliasingEnabled;
bool isConstScalingEnabled;
bool centerOnScaling;
bool rescaleByWheel;
bool autoRasterHeightLimits;
bool rasterDiscretePalette;
bool rasterInvalidHeightMode;
QVector <uint32_t> colorMap;
QVector <LayerInfo> layer_list;
std::vector <ClassifierInfo> classifiers;
std::vector <MapInfo> maps;
QLabel *positionLabel;
uint32_t wgt_width;
uint32_t wgt_height;
private:
int index;
gis_map_projection_t proj_params;
gis_data_engine_context_t data_engine_ctx;
gis_render_sm_context_t sm_ctx;
gis_core_connection_t *connection;
uint32_t offscreen_ext_px;
float blit_region_rate;
double_point_t geo_center;
double_point_t pinned_position;
uint32_t pinned_scale;
uint32_t map_widget_scale;
bool allocInRam;
int smMode;
int minimal_size;
QVector<int> scale_values;
int buttonBorderOffset;
int objectSearchSideSizePx;
int iconSideSizePx;
int minimumWidgetHeight;
int minimumWidgetWidth;
int maximumWidgetHeight;
int maximumWidgetWidth;
bool pin;
bool dont_save_to_config;
bool initialized;
int idx_scale;
uint32_t scale_value;
int32_point_t viewport_pos;
QPoint last_position;
bool update_scaling_center;
QLabel *scaleLabel;
QPushButton *increaseButton;
QPushButton *decreaseButton;
QPushButton *closeButton;
QPushButton *meterButton;
QPushButton *savePinButton;
QPushButton *showPinButton;
bool userFormBlockingFlag;
gis_userobject_t obj;
QPointer <UserDialog> userForm;
QPointer <DistanceMeter> distance_meter;
QPointer <ObjectInfo> objInfo;
int loadSettings();
void saveSettings();
void setScaleValue( uint32_t value )
{
scale_value = value;
emit scaleValueChanged( scale_value );
}
bool event(QEvent *event);
void fillClassifierInfo();
bool gestureEvent( QGestureEvent *event );
void mousePressEvent( QMouseEvent *event );
void mouseReleaseEvent( QMouseEvent *event );
void mouseMoveEvent( QMouseEvent *event );
void mouseDoubleClickEvent(QMouseEvent *event);
virtual void paintEvent(QPaintEvent * event);
void resizeEvent( QResizeEvent *event );
void closeEvent( QCloseEvent *event );
void panTriggered( QPanGesture *gesture );
void pinchTriggered( QPinchGesture *gesture );
void swipeTriggered( QSwipeGesture *gesture );
void syncHeightLimits();
void wheelEvent(QWheelEvent *event);
#ifdef DEBUG_TOUCH
void grabGestures(const QList<Qt::GestureType> &gestures);
qreal scaleFactor;
qreal currentStepScaleFactor;
#endif
bool hasChildWidgets;
public slots:
void setTabBlockingFlag( bool blocked )
{
hasChildWidgets = blocked;
emit hasLockingWidgets( hasChildWidgets );
}
void fillLayerTypeList();
void showMeter();
void savePin();
void showPin();
void showUserForm();
void updateDatabufferDescriptor();
void showObjectInfo( QPoint px_click );
void showObjectInfoWindow( gis_object_t current_object );
void sync();
void updateMapDrawing();
void setDiscretePalette( bool enabled );
void setRasterInvalidHeightMode( bool show );
void setCenterOnScaling( bool enabled ) { centerOnScaling = enabled; }
void setRescaleByWheel( bool enabled ) { rescaleByWheel = enabled; }
void setAutoRasterHeightLimits( bool enabled )
{
autoRasterHeightLimits = enabled;
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
gis_mdp_set_raster_height_mode( dp, autoRasterHeightLimits );
if ( autoRasterHeightLimits )
{
minRasterHeight = gis_mdp_get_raster_lower_height_limit( dp );
maxRasterHeight = gis_mdp_get_raster_upper_height_limit( dp );
}
}
void setInvalidHeightMode( bool enabled ) { rasterInvalidHeightMode = enabled; }
void setConstScalingMode( bool enabled );
void setAliasingMode( bool enable );
void setRasterHeightLimits( double new_min, double new_max );
void setMapWidgetCenterAtPoint( double_point_t object_center );
void updateBrightnessContrast( float br, float cn );
void updateLayerOrder( int index, gis_render_sm_layer_type_t type );
void updateDataSourcesForLayer( gis_render_sm_layer_type_t layer_type,
int num_of_data_sources,
gis_core_map_data_source_t *data_sources );
private slots:
void increaseScale();
void decreaseScale();
void updatePositionLabel( QPoint );
void updateScaleLabel( uint32_t );
void setRasterPalette();
signals:
void hasLockingWidgets( bool );
void eraseList();
void getNewMeterPoint( QPoint );
void getNewUserObjPoint( QPoint );
void getMouseRelease( QPoint );
void positionLabelChanged( int, QString );
void scaleValueChanged( uint32_t );
void showList();
void shutdownButtonPressed();
void sizeChanged();
void widgetIsReady();
};
class MapTabWidget : public QTabWidget
{
Q_OBJECT
public:
explicit MapTabWidget( QWidget *parent = 0 ) : QTabWidget( parent ),
lock_tab_idx( -1 ),
is_tab_locked( false )
{
setTabsClosable( true );
connect( this->tabBar(), SIGNAL( tabCloseRequested( int ) ),
this, SLOT( closeTab( int ) ) );
}
MapWidget* currentMapWidget() { return static_cast<MapWidget*>( currentWidget() ); }
void addMapWidget( gis_core_connection_t *connection )
{
MapWidget *mw = nullptr;
try
{
mw = new MapWidget( connection, count(), this );
}
catch( const std::bad_alloc & )
{
qDebug () << "Failed to allocate memory for MapWidget";
exit( 1 );
}
connect( mw, SIGNAL( positionLabelChanged( int, QString ) ),
this, SLOT( updateTabText( int, QString ) ) );
connect( mw, SIGNAL( hasLockingWidgets( bool ) ),
this, SLOT( setCurrentTabLocked( bool ) ) );
addTab( mw, "-" );
mw->initialize();
if ( count() == 1 )
{
emit firstTabAdded(0);
}
}
bool checkLock( int tab_idx )
{
Q_UNUSED( tab_idx );
if ( is_tab_locked )
setCurrentIndex( lock_tab_idx );
return is_tab_locked;
}
protected:
void tabInserted(int index)
{
emit tabInsert(index);
}
private:
int lock_tab_idx;
bool is_tab_locked;
signals:
void tabInsert(int index);
void firstTabAdded(int);
public slots:
void closeEvent( QCloseEvent *event )
{
for( int i = 0; i < this->count(); ++i )
{
MapWidget *map_w = qobject_cast<MapWidget *>( this->widget( i ) );
map_w->userForm->close();
map_w->distance_meter->close();
map_w->objInfo->close();
}
}
void closeTab( int index )
{
QWidget *map_widget = this->widget( index );
removeTab( index );
map_widget->close();
for( int i = index; i < this->count(); ++i )
{
qobject_cast<MapWidget *>(this->widget( i ))->setIndex( i );
}
}
void setCurrentTabLocked( bool locked )
{
if ( locked ) {
lock_tab_idx = currentIndex();
is_tab_locked = true;
} else {
is_tab_locked = false;
}
}
void refreshMapData()
{
for ( int i = 0; i < count(); ++i )
{
qobject_cast<MapWidget*>( widget(i) )->updateDatabufferDescriptor();
}
}
void setAliasingMode( bool enabled ) { currentMapWidget()->setAliasingMode( enabled ); }
void setCenterAtCursor( bool enabled ) { currentMapWidget()->setCenterOnScaling( enabled ); }
void setRescaleByWheel( bool enabled ) { currentMapWidget()->setRescaleByWheel( enabled ); }
void setConstScalingMode( bool enabled ) { currentMapWidget()->setConstScalingMode( enabled ); }
void setDiscretePaletteEnabled( bool enabled ) { currentMapWidget()->setDiscretePalette( enabled ); }
void setRasterAutoHeightMode( bool enabled )
{
currentMapWidget()->setAutoRasterHeightLimits( enabled );
}
void setRasterInvalidHeightMode( bool enabled ) { currentMapWidget()->setRasterInvalidHeightMode( enabled ); }
void showMeter() { currentMapWidget()->showMeter(); }
void showProjectionDialog() { currentMapWidget()->updateProjectionParameters(); }
void showScreenParametersDialog() { currentMapWidget()->updateScreenParameters(); }
void showUserForm() { currentMapWidget()->showUserForm(); }
void syncCurrentTab() { currentMapWidget()->sync(); }
void updateCurrentTabMap() { currentMapWidget()->updateMapDrawing(); }
void updateBrightnessContrast( float br, float cn ) { currentMapWidget()->updateBrightnessContrast( br, cn ); }
void updateLayerOrder( int idx, gis_render_sm_layer_type_t type ) { currentMapWidget()->updateLayerOrder( idx, type ); }
void updateTabText( int idx, QString str ) { setTabText( idx, str ); }
void updateDataSourcesForLayer( gis_render_sm_layer_type_t layer_type,
int num_of_data_sources,
gis_core_map_data_source_t *data_sources )
{
currentMapWidget()->updateDataSourcesForLayer( layer_type, num_of_data_sources, data_sources );
}
};
#endif