Картографический пакет для ЗОСРВ Нейтрино
12
.gitmodules
поставляемый
Обычный файл
@ -0,0 +1,12 @@
|
||||
[submodule "src/lib/gdal"]
|
||||
path = src/lib/gdal
|
||||
url = https://git.kpda.ru/gis/gdal.git
|
||||
[submodule "src/lib/openjpeg"]
|
||||
path = src/lib/openjpeg
|
||||
url = https://git.kpda.ru/gis/openjpeg.git
|
||||
[submodule "src/lib/geos"]
|
||||
path = src/lib/geos
|
||||
url = https://git.kpda.ru/gis/geos.git
|
||||
[submodule "src/lib/proj"]
|
||||
path = src/lib/proj
|
||||
url = https://git.kpda.ru/gis/proj.git
|
26
CMakeLists.txt
Исполняемый файл
@ -0,0 +1,26 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( GIS )
|
||||
|
||||
add_subdirectory( src )
|
19
LICENSE
Обычный файл
@ -0,0 +1,19 @@
|
||||
MIT License
|
||||
|
||||
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.
|
157
README.md
Обычный файл
@ -0,0 +1,157 @@
|
||||
<h1 align="center">ПК ЦКИ (Программый Комплекс поддержки ЦКИ)</h1>
|
||||
<div align="center">
|
||||
<p><img src="doc/readme_content/animated_gis_logo_no_loop.gif" alt="ПК ЦКИ" align="top"></p>
|
||||
<p>
|
||||
<img src="https://img.shields.io/badge/c-%2300599C.svg?style=for-the-badge&logo=c&logoColor=white" alt="C">
|
||||
<img src="https://img.shields.io/badge/c++-%2300599C.svg?style=for-the-badge&logo=c%2B%2B&logoColor=white" alt="C++">
|
||||
<img src="https://img.shields.io/badge/CMake-%23008FBA.svg?style=for-the-badge&logo=cmake&logoColor=white" alt="CMake">
|
||||
</p>
|
||||
<img src="https://img.shields.io/badge/PVS_stat_analyzer-Enabled-green%20" alt="PVS_stat_analyzer-Enabled">
|
||||
<img src="https://img.shields.io/badge/GCOV_code_coverage-Enabled-green%20" alt="GCOV_code_coverage-Enabled">
|
||||
</div>
|
||||
|
||||
<h1></h1>
|
||||
|
||||
<p>Картографический пакет ПК ЦКИ предназначен для обработки и визуализации цифровой картографической информации в защищенной операционной системе реального времени «Нейтрино».</p>
|
||||
<p>ПК ЦКИ оптимизирован для работы на широком спектре оборудования, включая аппаратные платформы на базе российских процессоров, и применяется в качестве базового ПО при построении ГИС различного назначения для мобильных, бортовых и стационарных систем и комплексов.</p>Подробнее о продукте можно прочитать <a href="https://kpda.ru/products/gis/">здесь</a>.
|
||||
|
||||
<h1></h1>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Поддерживаемые платформы</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p><img src="https://img.shields.io/badge/x86-blue" alt="x86"> </p>
|
||||
<p><img src="https://img.shields.io/badge/ARM_v7-blue" alt="ARM_v7"> </p>
|
||||
<p><img src="https://img.shields.io/badge/PowerPC_BE_%2F_BE_SPE-blue" alt="PowerPC"> </p>
|
||||
<p><img src="https://img.shields.io/badge/%D0%AD%D0%BB%D1%8C%D0%B1%D1%80%D1%83%D1%81-blue" alt="Эльбрус"> </p>
|
||||
<p><img src="https://img.shields.io/badge/MIPS-blue" alt="MIPS"> </p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td width="1000px" align="center">
|
||||
<img src="doc/readme_content/supported_formats.png" alt="Поддерживаемые форматы" width="750px">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
# Обзор
|
||||
|
||||
## Содержание
|
||||
|
||||
- [Компоненты](#компоненты)
|
||||
- [Зависимости](#зависимости)
|
||||
- [Сборка](#сборка)
|
||||
- [Запуск](#запуск)
|
||||
|
||||
## Компоненты
|
||||
|
||||
- [doc](doc) - справка по формату GCM, и др.
|
||||
- [src](src) - исходные компоненты проекта
|
||||
- [apps](src/apps) - демонстрационные и тестовые приложения
|
||||
- [lib](src/lib) - исходники используемых библиотек
|
||||
- [services](src/services) - компоненты ядра, драйверов для работы с серверами и имитаторов серверов
|
||||
- [gis-core](src/services/core) - ядро картографического пакета
|
||||
- [drivers](src/services/drivers) - исходники драйверов форматов картографической информации
|
||||
- [utils](src/utils) - конвертеры карт и дополнительные утилиты для работы
|
||||
|
||||
Подробную информацию по конкретному компоненту (приложению, утилите, драйверу и т. д.) можно найти в файлах `README.md`, находящихся в директории этого компонента.
|
||||
|
||||
## Зависимости
|
||||
|
||||
<div align="center">
|
||||
<img src="doc/readme_content/GIS.drawio.svg" alt="Зависимости" width="1000px">
|
||||
</div>
|
||||
|
||||
## Сборка
|
||||
|
||||
*ПК ЦКИ поддерживается на ЗОСРВ "Нейтрино" версий 2024 и 2021.*
|
||||
|
||||
**Для комплекта разработчика 2021 необходимо дополнительно подключить sqlite3:**
|
||||
|
||||
1. Установить sqlite3 на свое устройство. Например, для Debian/Ubuntu ввести следующую команду:
|
||||
|
||||
<code>sudo apt update && sudo apt install sqlite3</code>
|
||||
|
||||
2. Собрать <a href="https://git.kpda.ru/gis/sqlite">sqlite3</a> под требуемую аппаратную платформу, установив библиотеки в указанную вами папку.
|
||||
|
||||
- Например, для armle-v7:
|
||||
|
||||
<code>make CPULIST=arm VARIANTLIST=le.v7 INSTALL_ROOT_nto=my_sqlite_install_dir install && make clean</code>
|
||||
|
||||
- Для x86:
|
||||
|
||||
<code>make CPULIST=x86 INSTALL_ROOT_nto=my_sqlite_install_dir install && make clean</code>
|
||||
|
||||
3. Полученные библиотеки необходимо поместить на целевое устройство с ОС "Нейтрино" версии 2021 в папку `/opt/gis/lib`.
|
||||
|
||||
4. Установить переменные окружения, используя ранее выбранную папку установки:
|
||||
|
||||
<code>export SQLite3_INCLUDE_DIR=my_sqlite_install_dir/armle-v7/usr/include/sqlite</code>
|
||||
|
||||
<code>export SQLite3_LIBRARY=my_sqlite_install_dir/armle-v7/usr/lib/libsqlite3.so.8</code>
|
||||
|
||||
**Сборка ПК ЦКИ для 2021 и 2024:**
|
||||
|
||||
1. Перейти в выбранную для сборки папку:
|
||||
|
||||
<code>mkdir my_gis_build && cd my_gis_build</code>
|
||||
|
||||
2. Настроить cmake:
|
||||
|
||||
<code>cmake --toolchain=$KPDA_HOST/mk/cmake/toolchain-nto-armle-v7.cmake *path-from-my_gis_build-folder*/kpda-gis</code>
|
||||
|
||||
3. Собрать проект:
|
||||
|
||||
<code>cmake --build . -jn</code>, где n - количество потоков.
|
||||
|
||||
4. Установить в выбранную папку:
|
||||
|
||||
<code>cmake --install . --prefix my_gis_install_dir</code>
|
||||
|
||||
*Примечание: при развертывании на целевое устройство *`my_gis_install_dir`* должно быть присвоено значение *`/opt/gis`*.*
|
||||
|
||||
## Запуск
|
||||
|
||||
**Пример запуска приложения gis-monitor**
|
||||
|
||||
1. Установить необходимые переменные окружения
|
||||
|
||||
<code>export PATH=/opt/gis/bin:/opt/gis/sbin:$PATH</code>
|
||||
<code>export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/gis/lib</code>
|
||||
|
||||
2. Дополнительные настройки
|
||||
<table>
|
||||
<tr>
|
||||
<td>Изменение языка</td>
|
||||
<td><code>export ABLANG=ru_RU</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Уровень отладочного вывода (Error - 1, Warning - 2, Info - 3)</td>
|
||||
<td><code>export GIS_DEBUG_LEVEL=3</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Установка размера кэша в байтах</td>
|
||||
<td><code>export GIS_CORE_DATABUFFER_SIZE_LIMIT=960000000</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
3. Добавить файлы цифровой картографической информации в директорию, соответствующую исходному формату ЦКИ, в <a href="http://gis.help.kpda.ru/help/topic/ru.kpda.doc.gis/html/dev_guide/articles/gis-environment.html?resultof=%22%47%49%53%5f%43%4f%52%45%5f%4d%41%50%5f%43%41%43%48%45%22%20">$GIS_CORE_MAP_CACHE</a> (по умолчанию /opt/gis/data/maps/cache).
|
||||
|
||||
4. Запуск ядра и приложения
|
||||
|
||||
При запуске ядра c опцией `-d` передается название драйвера требуемого формата. Подробнее об имеющихся драйверах можно прочитать [тут](http://gis.help.kpda.ru/help/topic/ru.kpda.doc.gis/html/utilities/reference-book/gis-core.html?cp=0_2_1_0_0).
|
||||
|
||||
Пример запуска с драйвером для формата SXF:
|
||||
|
||||
<code>gis-core -dsxf-local,sync=hard</code> [справка](http://gis.help.kpda.ru/help/topic/ru.kpda.doc.gis/html/utilities/reference-book/gis-core.html?cp=0_2_1_0_0)
|
||||
|
||||
Запуск демонстрационного приложения gis-monitor:
|
||||
|
||||
<code>gis-monitor -x50 -y50</code> [справка](http://gis.help.kpda.ru/help/topic/ru.kpda.doc.gis/html/utilities/reference-book/gis-monitor.html?cp=0_2_0_0_0)
|
Двоичные данные
doc/GCM-format-description.pdf
Обычный файл
4
doc/readme_content/GIS.drawio.svg
Обычный файл
После Ширина: | Высота: | Размер: 101 KiB |
Двоичные данные
doc/readme_content/animated_gis_logo_no_loop.gif
Обычный файл
После Ширина: | Высота: | Размер: 297 KiB |
Двоичные данные
doc/readme_content/supported_formats.png
Обычный файл
После Ширина: | Высота: | Размер: 82 KiB |
29
src/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,29 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( src )
|
||||
|
||||
add_subdirectory( apps )
|
||||
add_subdirectory( lib )
|
||||
add_subdirectory( services )
|
||||
add_subdirectory( utils )
|
44
src/apps/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,44 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( apps )
|
||||
|
||||
if ( DEFINED GIS_ENABLE_GCOV )
|
||||
set( CMAKE_C_FLAGS "-O0 -Wall -fprofile-arcs -ftest-coverage" )
|
||||
set( CMAKE_CXX_FLAGS "-O0 -Wall -fprofile-arcs -ftest-coverage" )
|
||||
set( CMAKE_C_OUTPUT_EXTENSION_REPLACE ON )
|
||||
set( CMAKE_CXX_OUTPUT_EXTENSION_REPLACE ON )
|
||||
endif()
|
||||
|
||||
add_subdirectory( gis-filter-generator )
|
||||
add_subdirectory( gis-map-linker )
|
||||
add_subdirectory( gis-map-viewer )
|
||||
add_subdirectory( gis-monitor )
|
||||
add_subdirectory( gis-raster-preview )
|
||||
add_subdirectory( gis-rb-viewer )
|
||||
|
||||
if ( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/gis-client-render )
|
||||
add_subdirectory( gis-client-render )
|
||||
endif()
|
||||
|
||||
|
76
src/apps/gis-filter-generator/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,76 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( gis-filter-generator LANGUAGES CXX )
|
||||
|
||||
set( CMAKE_AUTOMOC ON )
|
||||
set( CMAKE_AUTOUIC ON )
|
||||
set( CMAKE_AUTORCC ON )
|
||||
|
||||
add_compile_options( -std=gnu++11 )
|
||||
add_compile_options( -Wno-ignored-attributes )
|
||||
add_compile_options( -Wno-deprecated-declarations )
|
||||
|
||||
find_package( Qt5
|
||||
COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
REQUIRED )
|
||||
|
||||
file( GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
images.qrc
|
||||
translations.qrc )
|
||||
|
||||
add_executable( gis-filter-generator ${SOURCES} )
|
||||
|
||||
add_custom_command( OUTPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-filter-generator_ru.qm
|
||||
COMMAND
|
||||
$ENV{KPDA_HOST}/usr/lib/Qt/bin/lrelease -silent ${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts )
|
||||
|
||||
add_custom_target( generate_translations_filter_generator
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-filter-generator_ru.qm )
|
||||
|
||||
target_include_directories( gis-filter-generator
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/kd-tree/public
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/private
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/config_parser )
|
||||
|
||||
add_dependencies( gis-filter-generator generate_translations_filter_generator )
|
||||
|
||||
target_link_libraries( gis-filter-generator
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
gishelper )
|
||||
|
||||
|
||||
install( TARGETS gis-filter-generator DESTINATION bin )
|
107
src/apps/gis-filter-generator/main.cpp
Обычный файл
@ -0,0 +1,107 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTranslator>
|
||||
|
||||
#include <libgen.h>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
int wgt_x = 0,
|
||||
wgt_y = 0,
|
||||
wgt_width = 400,
|
||||
wgt_height = 500;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt = 0;
|
||||
extern char *optarg;
|
||||
|
||||
while ( (opt = getopt( argc, argv,"w::h::x::y::" )) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'w':
|
||||
wgt_width = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'h':
|
||||
wgt_height = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'x':
|
||||
wgt_x = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'y':
|
||||
wgt_y = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case '?':
|
||||
printf( "Error: unknown option\n" );
|
||||
exit(1);
|
||||
};
|
||||
};
|
||||
|
||||
char logname[GIS_MAX_NAME_LENGTH];
|
||||
|
||||
char *executable_path = strdup( argv[0] );
|
||||
|
||||
if ( executable_path == NULL )
|
||||
{
|
||||
printf( "Error: missed executable path (argv[0])!\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char *executable_name = basename( executable_path );
|
||||
|
||||
if ( executable_name == NULL || strlen( executable_name ) > GIS_MAX_NAME_LENGTH - 5 )
|
||||
{
|
||||
printf( "Error: missed executable name (argv[0]) or it's too big \n" );
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( logname, "%s.log", executable_name );
|
||||
gis_helper_debug_mode_setmask( GIS_DEBUG_MODE_STD | GIS_DEBUG_MODE_FD );
|
||||
gis_helper_debug_file_setname( logname );
|
||||
}
|
||||
|
||||
CleanExit cleanExit;
|
||||
|
||||
QApplication a(argc, argv);
|
||||
|
||||
const char *lang = getenv( "ABLANG" );
|
||||
QString locale = "en_EN";
|
||||
|
||||
if ( lang )
|
||||
{
|
||||
locale = QString( lang );
|
||||
}
|
||||
|
||||
QTranslator myTranslator;
|
||||
myTranslator.load( ":/translations/gis-filter-generator_" + locale );
|
||||
a.installTranslator(&myTranslator);
|
||||
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
|
320
src/apps/gis-filter-generator/mainwindow.cpp
Обычный файл
@ -0,0 +1,320 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QTextCodec>
|
||||
#include <QComboBox>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <class_filter_cfg_parser_api.h>
|
||||
#include <gis_types_internal.h>
|
||||
|
||||
extern int wgt_x,
|
||||
wgt_y,
|
||||
wgt_width,
|
||||
wgt_height;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent)
|
||||
{
|
||||
style_creator = new MapStyleCreator();
|
||||
|
||||
resize( wgt_width, wgt_height );
|
||||
move( wgt_x, wgt_y );
|
||||
|
||||
setWindowTitle( tr("Class filter") );
|
||||
|
||||
QWidget *mainWidget = new QWidget;
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
|
||||
mainWidget->setLayout( mainLayout );
|
||||
setCentralWidget( mainWidget );
|
||||
|
||||
QString gcmFolder = QString( gis_helper_env_get_maps_cache_directory() ) + "/gcm/";
|
||||
|
||||
fillClassifiersList( gcmFolder );
|
||||
|
||||
for ( int idx = 0; idx < classifierList.size(); idx++ )
|
||||
{
|
||||
QVector<gis_core_class_code_t> filter_table;
|
||||
|
||||
std::vector<gis_core_class_code_t> class_codes;
|
||||
|
||||
if ( filter_config_get_classes_list( classifierList[idx].toStdString(), class_codes ) == 0 )
|
||||
{
|
||||
if ( !class_codes.empty() )
|
||||
filter_table = filter_table.fromStdVector( class_codes );
|
||||
}
|
||||
|
||||
gis_core_map_data_source_t ds = getDataSourceType( classifierList[idx] );
|
||||
QString filepath( classifierList[idx] );
|
||||
classifierStates << ClassifierState( ds, filepath, filter_table, style_creator );
|
||||
}
|
||||
|
||||
classifierCurrIdx = 0;
|
||||
|
||||
QVBoxLayout *openFileLayout = new QVBoxLayout;
|
||||
QGroupBox *classifierFileGrpBx = new QGroupBox(tr("Open file"));
|
||||
classifierFileGrpBx->setLayout( openFileLayout );
|
||||
|
||||
QComboBox *classifierListComboBx = new QComboBox;
|
||||
classifierListComboBx->addItem( tr("< Choose classifier file >") );
|
||||
classifierListComboBx->addItems( classifierList );
|
||||
connect( classifierListComboBx, SIGNAL(currentIndexChanged(int)), this, SLOT(rscListIdxChanged(int)) );
|
||||
openFileLayout->addWidget( classifierListComboBx );
|
||||
|
||||
mainLayout->addWidget( classifierFileGrpBx );
|
||||
|
||||
classListTreeWgt = new QTreeWidget;
|
||||
mainLayout->addWidget( classListTreeWgt );
|
||||
classListTreeWgt->setColumnCount( 4 );
|
||||
classListTreeWgt->setHeaderLabels( QStringList() << "#" << tr("Enable") << tr("Class code") << tr("Acronym") );
|
||||
|
||||
QWidget *btnsBoxWgt = new QWidget;
|
||||
QHBoxLayout *btnsBoxLayout = new QHBoxLayout;
|
||||
btnsBoxWgt->setLayout( btnsBoxLayout );
|
||||
mainLayout->addWidget( btnsBoxWgt );
|
||||
|
||||
QPushButton *updateButton = new QPushButton;
|
||||
updateButton->setText( tr("Generate / Update") );
|
||||
connect( updateButton, SIGNAL( clicked( bool ) ), this, SLOT( updateBtnClicked( bool ) ) );
|
||||
btnsBoxLayout->addWidget( updateButton );
|
||||
|
||||
QPushButton *selectAllBtn = new QPushButton;
|
||||
selectAllBtn->setText( tr("Select All") );
|
||||
connect( selectAllBtn, SIGNAL( clicked( bool ) ), this, SLOT( selectAllBtnClicked( bool ) ) );
|
||||
btnsBoxLayout->addWidget( selectAllBtn );
|
||||
|
||||
QPushButton *deselectAllBtn = new QPushButton;
|
||||
deselectAllBtn->setText( tr("Deselect All") );
|
||||
connect( deselectAllBtn, SIGNAL( clicked( bool ) ), this, SLOT( deselectAllBtnClicked( bool ) ) );
|
||||
btnsBoxLayout->addWidget( deselectAllBtn );
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void MainWindow::selectAllBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED(clicked);
|
||||
|
||||
QVector<ClassEntry> &classEntries = classifierStates[classifierCurrIdx].m_classEntries;
|
||||
for ( auto &entry : classEntries )
|
||||
entry.m_enabled = true;
|
||||
|
||||
fillTreeWidget();
|
||||
}
|
||||
|
||||
void MainWindow::deselectAllBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED(clicked);
|
||||
|
||||
QVector<ClassEntry> &classEntries = classifierStates[classifierCurrIdx].m_classEntries;
|
||||
for ( auto &entry : classEntries )
|
||||
entry.m_enabled = false;
|
||||
|
||||
fillTreeWidget();
|
||||
}
|
||||
|
||||
void MainWindow::updateBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED(clicked);
|
||||
qDebug() << "Update class filter";
|
||||
|
||||
std::map<std::string,Config::ClassFilterConfigParser::configData*> filter_data_map;
|
||||
|
||||
for ( int idx = 0; idx < classifierStates.size(); idx++ )
|
||||
{
|
||||
ClassifierState &rscState = classifierStates[idx];
|
||||
QVector<ClassEntry> &classEntries = rscState.m_classEntries;
|
||||
|
||||
QString rscFname = rscState.m_filename;
|
||||
auto *data = new Config::ClassFilterConfigParser::configData();
|
||||
|
||||
for ( auto &entry : classEntries )
|
||||
{
|
||||
if ( entry.m_enabled )
|
||||
{
|
||||
data->class_code_vector.push_back( entry.m_code );
|
||||
}
|
||||
}
|
||||
|
||||
filter_data_map.emplace( rscFname.toStdString(), data );
|
||||
}
|
||||
|
||||
filter_config_write_new( filter_data_map );
|
||||
qDebug() << "Completed!";
|
||||
}
|
||||
|
||||
void MainWindow::rscListIdxChanged( int index )
|
||||
{
|
||||
if ( index != 0 )
|
||||
{
|
||||
classifierCurrIdx = index-1;
|
||||
fillTreeWidget();
|
||||
}
|
||||
else
|
||||
{
|
||||
classListTreeWgt->clear();
|
||||
}
|
||||
}
|
||||
|
||||
#define TREE_WIDGET_COLUMN_IDX 0
|
||||
#define TREE_WIDGET_COLUMN_INCLUDE_CHK 1
|
||||
#define TREE_WIDGET_COLUMN_CLASS_CODE 2
|
||||
#define TREE_WIDGET_COLUMN_ACRONYM 3
|
||||
|
||||
void MainWindow::treeItemChangedSlot( QTreeWidgetItem * item, int column )
|
||||
{
|
||||
int itemIdx = item->text( TREE_WIDGET_COLUMN_IDX ).toInt();
|
||||
|
||||
if ( column == TREE_WIDGET_COLUMN_INCLUDE_CHK )
|
||||
{
|
||||
QVector<ClassEntry> &classEntries = classifierStates[classifierCurrIdx].m_classEntries;
|
||||
classEntries[itemIdx].m_enabled = (item->checkState( TREE_WIDGET_COLUMN_INCLUDE_CHK ) == Qt::Checked);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::fillTreeWidget()
|
||||
{
|
||||
classListTreeWgt->clear();
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 7, 0))
|
||||
classListTreeWgt->header()->setResizeMode( QHeaderView::ResizeToContents );
|
||||
#else
|
||||
classListTreeWgt->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
|
||||
#endif
|
||||
|
||||
connect( classListTreeWgt, SIGNAL( itemChanged(QTreeWidgetItem *, int) ),
|
||||
this, SLOT( treeItemChangedSlot(QTreeWidgetItem *, int) ) );
|
||||
|
||||
QVector<ClassEntry> &classEntries = classifierStates[classifierCurrIdx].m_classEntries;
|
||||
|
||||
for ( auto &entry : classEntries )
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem( classListTreeWgt );
|
||||
|
||||
item->setFlags( item->flags() | Qt::ItemIsUserCheckable );
|
||||
item->setText( TREE_WIDGET_COLUMN_IDX, QString::number(entry.m_id) );
|
||||
|
||||
if ( entry.m_enabled )
|
||||
{
|
||||
item->setCheckState( TREE_WIDGET_COLUMN_INCLUDE_CHK, Qt::Checked );
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setCheckState( TREE_WIDGET_COLUMN_INCLUDE_CHK, Qt::Unchecked );
|
||||
}
|
||||
|
||||
item->setText( TREE_WIDGET_COLUMN_CLASS_CODE, QString::number(entry.m_code, 16) );
|
||||
item->setText( TREE_WIDGET_COLUMN_ACRONYM, entry.m_acronym );
|
||||
|
||||
classListTreeWgt->addTopLevelItem( item );
|
||||
}
|
||||
}
|
||||
|
||||
ClassifierState::ClassifierState( gis_core_map_data_source_t data_source,
|
||||
QString &filepath,
|
||||
QVector<gis_core_class_code_t> &filter_table,
|
||||
MapStyleCreator *style_creator )
|
||||
{
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
||||
|
||||
m_classEntries.clear();
|
||||
|
||||
this->m_filepath = filepath;
|
||||
this->m_filename = QFileInfo( m_filepath ).fileName();
|
||||
|
||||
this->m_ds = data_source;
|
||||
gis_map_style_t type = gis_helper_get_map_style_by_data_source( m_ds );
|
||||
|
||||
this->m_style = style_creator->createObject( type, m_filepath.toStdString().c_str(), true );
|
||||
|
||||
std::vector <gis_core_class_info_t> codes = m_style->get_class_code_list_with_acronyms();
|
||||
size_t class_count = codes.size();
|
||||
|
||||
for ( auto i_class = 0; i_class < class_count; ++i_class )
|
||||
{
|
||||
bool foundInFilter = false;
|
||||
|
||||
if ( filter_table.size() != 0 )
|
||||
{
|
||||
for ( const auto& filter_code : filter_table )
|
||||
{
|
||||
if ( codes.at( i_class ).class_data.code == filter_code )
|
||||
{
|
||||
foundInFilter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foundInFilter = true;
|
||||
}
|
||||
|
||||
m_classEntries << ClassEntry( codes[i_class].class_data.code, foundInFilter, i_class,
|
||||
codec->toUnicode( codes[i_class].acronym ) );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::fillClassifiersList( QString& gcmFolder )
|
||||
{
|
||||
std::vector <QStringList> ext_list;
|
||||
ext_list.resize( GIS_CORE_DRIVER_COUNT );
|
||||
ext_list[GIS_CORE_DRIVERS_S57_LOCAL] = QStringList() << "S-52 format";
|
||||
ext_list[GIS_CORE_DRIVERS_SXF_LOCAL] = QStringList() << "*.rsc*" << "*.RSC*";
|
||||
ext_list[GIS_CORE_DRIVERS_SHP_LOCAL] = QStringList() << "*.sld*" << "*.SLD*";
|
||||
|
||||
classifierList.clear();
|
||||
classifierList << ext_list[GIS_CORE_DRIVERS_S57_LOCAL];
|
||||
classifierList << QDir(gcmFolder).entryList( ext_list[GIS_CORE_DRIVERS_SXF_LOCAL], QDir::Files );
|
||||
classifierList << QDir(gcmFolder).entryList( ext_list[GIS_CORE_DRIVERS_SHP_LOCAL], QDir::Files );
|
||||
}
|
||||
|
||||
gis_core_map_data_source_t MainWindow::getDataSourceType( QString classifierName )
|
||||
{
|
||||
if ( classifierName == "S-52 format" )
|
||||
{
|
||||
return GIS_CORE_MAP_DATA_SOURCE_S57;
|
||||
}
|
||||
|
||||
if ( classifierName.contains( ".rsc", Qt::CaseInsensitive ) )
|
||||
{
|
||||
return GIS_CORE_MAP_DATA_SOURCE_SXF;
|
||||
}
|
||||
|
||||
if ( classifierName.contains( ".sld", Qt::CaseInsensitive ) )
|
||||
{
|
||||
return GIS_CORE_MAP_DATA_SOURCE_SHP;
|
||||
}
|
||||
|
||||
return GIS_CORE_MAP_DATA_SOURCE_NONE;
|
||||
|
||||
}
|
135
src/apps/gis-filter-generator/mainwindow.h
Обычный файл
@ -0,0 +1,135 @@
|
||||
/*
|
||||
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 MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gis_types.h>
|
||||
|
||||
#include <gishelper_service.h>
|
||||
#include <gis_mapstyle.h>
|
||||
|
||||
|
||||
struct CleanExit
|
||||
{
|
||||
CleanExit()
|
||||
{
|
||||
signal(SIGINT, &CleanExit::exitQt);
|
||||
signal(SIGTERM, &CleanExit::exitQt);
|
||||
}
|
||||
|
||||
static void exitQt( int sig )
|
||||
{
|
||||
Q_UNUSED(sig);
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class ClassEntry
|
||||
{
|
||||
public:
|
||||
ClassEntry( gis_core_class_code_t code, bool enabled, uint32_t id, QString acronym )
|
||||
{
|
||||
m_code = code;
|
||||
m_enabled = enabled;
|
||||
m_id = id;
|
||||
m_acronym = std::move( acronym );
|
||||
}
|
||||
|
||||
ClassEntry()
|
||||
{
|
||||
m_code = GIS_CLASS_CODE_UNDEFINED;
|
||||
m_enabled = false;
|
||||
m_id = 0;
|
||||
m_acronym = "";
|
||||
}
|
||||
|
||||
gis_core_class_code_t m_code;
|
||||
bool m_enabled;
|
||||
uint32_t m_id;
|
||||
QString m_acronym;
|
||||
};
|
||||
|
||||
class ClassifierState
|
||||
{
|
||||
public:
|
||||
ClassifierState( gis_core_map_data_source_t ds,
|
||||
QString &filepath,
|
||||
QVector<gis_core_class_code_t> &filter_table,
|
||||
MapStyleCreator *style_creator );
|
||||
|
||||
ClassifierState()
|
||||
{
|
||||
m_ds = GIS_CORE_MAP_DATA_SOURCE_NONE;
|
||||
m_filename = "";
|
||||
m_filepath = "";
|
||||
m_style = nullptr;
|
||||
}
|
||||
|
||||
QVector<ClassEntry> m_classEntries;
|
||||
|
||||
gis_core_map_data_source_t m_ds;
|
||||
QString m_filename;
|
||||
|
||||
private:
|
||||
MapStyle *m_style;
|
||||
QString m_filepath;
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
MapStyleCreator *style_creator;
|
||||
QVector<ClassifierState> classifierStates;
|
||||
QStringList classifierList;
|
||||
QTreeWidget *classListTreeWgt;
|
||||
int classifierCurrIdx;
|
||||
|
||||
void fillTreeWidget();
|
||||
gis_core_map_data_source_t getDataSourceType( QString classifierName );
|
||||
void fillClassifiersList(QString &gcmFolder);
|
||||
|
||||
private slots:
|
||||
void deselectAllBtnClicked(bool clicked);
|
||||
void rscListIdxChanged(int index);
|
||||
void selectAllBtnClicked(bool clicked);
|
||||
void treeItemChangedSlot(QTreeWidgetItem *item, int column);
|
||||
void updateBtnClicked(bool clicked);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
6
src/apps/gis-filter-generator/translations.qrc
Обычный файл
@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>translations/gis-filter-generator_ru.ts</file>
|
||||
<file>translations/gis-filter-generator_ru.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.0" language="ru_RU">
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<source>< Choose classifier file ></source>
|
||||
<translation>< Выберите классификатор ></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open file</source>
|
||||
<translation>Открыть</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class filter</source>
|
||||
<translation>Фильтр классов</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Acronym</source>
|
||||
<translation>Акроним</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class code</source>
|
||||
<translation>Код класса</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable</source>
|
||||
<translation>Включить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Generate / Update</source>
|
||||
<translation>Создать / Обновить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select All</source>
|
||||
<translation>Выбрать все</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Deselect All</source>
|
||||
<translation>Снять выделение</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
78
src/apps/gis-map-linker/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,78 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( gis-map-linker LANGUAGES CXX )
|
||||
|
||||
set( CMAKE_AUTOMOC ON )
|
||||
set( CMAKE_AUTOUIC ON )
|
||||
set( CMAKE_AUTORCC ON )
|
||||
|
||||
add_compile_options( -std=gnu++11 )
|
||||
add_compile_options( -Wno-ignored-attributes )
|
||||
add_compile_options( -Wno-deprecated-declarations )
|
||||
|
||||
find_package( Qt5
|
||||
COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
REQUIRED )
|
||||
|
||||
file( GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
images.qrc
|
||||
translations.qrc )
|
||||
|
||||
add_executable( gis-map-linker ${SOURCES} )
|
||||
|
||||
add_custom_command( OUTPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-map-linker_ru.qm
|
||||
COMMAND
|
||||
$ENV{KPDA_HOST}/usr/lib/Qt/bin/lrelease -silent ${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts )
|
||||
|
||||
add_custom_target( generate_translations_map_linker
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-map-linker_ru.qm )
|
||||
|
||||
target_include_directories( gis-map-linker
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/public
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gisrender/api/public
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/formats/gcm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/private )
|
||||
|
||||
add_dependencies( gis-map-linker generate_translations_map_linker )
|
||||
|
||||
target_link_libraries( gis-map-linker
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
gishelper
|
||||
gisrender )
|
||||
|
||||
|
||||
install( TARGETS gis-map-linker DESTINATION bin )
|
82
src/apps/gis-map-linker/main.cpp
Обычный файл
@ -0,0 +1,82 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <QTranslator>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
int wgt_x = 0,
|
||||
wgt_y = 0,
|
||||
wgt_width = 600,
|
||||
wgt_height = 500;
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
int opt = 0;
|
||||
extern char * optarg;
|
||||
while ( (opt = getopt( argc, argv,"w::h::x::y::" ) ) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'w':
|
||||
wgt_width = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'h':
|
||||
wgt_height = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'x':
|
||||
wgt_x = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'y':
|
||||
wgt_y = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case '?':
|
||||
printf( "Error: unknown option\n" );
|
||||
exit(1);
|
||||
};
|
||||
};
|
||||
|
||||
gis_helper_debug_mode_setmask( GIS_DEBUG_MODE_STD | GIS_DEBUG_MODE_FD );
|
||||
gis_helper_debug_file_setname( "gis-map-linker.log" );
|
||||
|
||||
CleanExit cleanExit;
|
||||
|
||||
QApplication a( argc, argv );
|
||||
|
||||
const char *lang = getenv( "ABLANG" );
|
||||
QString locale = "en_EN";
|
||||
|
||||
if ( lang )
|
||||
{
|
||||
locale = QString( lang );
|
||||
}
|
||||
|
||||
QTranslator myTranslator;
|
||||
myTranslator.load( ":/translations/gis-map-linker_" + locale );
|
||||
a.installTranslator(&myTranslator);
|
||||
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
|
782
src/apps/gis-map-linker/mainwindow.cpp
Обычный файл
@ -0,0 +1,782 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <sys/syspage.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <gis/gisrender.h>
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gis_core_cfg_parser.h>
|
||||
|
||||
#include <gcm_format.h>
|
||||
#include <gis_types_internal.h>
|
||||
#include <projection.h>
|
||||
|
||||
#define GCM_SUFFIX "gcm"
|
||||
|
||||
#define COLUMN_IDX 0
|
||||
#define COLUMN_IS_MAP_CONVERTED 1
|
||||
#define COLUMN_MAP_NAME 2
|
||||
#define COLUMN_STYLE_NAME 3
|
||||
#define COLUMN_MAP_SCALE 4
|
||||
#define COLUMN_MAP_DATA_SOURCE 5
|
||||
#define COLUMN_COUNT 6
|
||||
|
||||
|
||||
extern int wgt_x,
|
||||
wgt_y,
|
||||
wgt_width,
|
||||
wgt_height;
|
||||
|
||||
int MainWindow::CHECKBOX_SIZE = 15;
|
||||
QString S57MapComboBox::UNUSED_DIR_NAME = ".unused";
|
||||
|
||||
MainWindow::MainWindow( QWidget *parent ) :
|
||||
QMainWindow( parent ),
|
||||
map_uidx( 0 ),
|
||||
style_uidx( 2 ),
|
||||
classFilterProcess( nullptr ),
|
||||
processing_idx( 0 ),
|
||||
deltaProgress( 0 ),
|
||||
taskCount( 0 )
|
||||
{
|
||||
resize( wgt_width, wgt_height );
|
||||
move( wgt_x, wgt_y );
|
||||
|
||||
setWindowTitle( tr("Map Configurator") );
|
||||
|
||||
QWidget *mainWidget = new QWidget;
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
|
||||
mainWidget->setLayout( mainLayout );
|
||||
setCentralWidget( mainWidget );
|
||||
|
||||
mapsCachePath = QString( gis_helper_env_get_maps_cache_directory() );
|
||||
|
||||
gis_core_link_init( &connection );
|
||||
int result = gis_core_link_connect( &connection, SHID_NULL );
|
||||
|
||||
if ( result != EOK && result != EALREADY )
|
||||
{
|
||||
qDebug() << QString( "GIS Core connection failed" );
|
||||
exit( EINVAL );
|
||||
}
|
||||
|
||||
mapTreeListWgt = new QTreeWidget;
|
||||
|
||||
QString style_mapTreeListWgt( "QAbstractItemView::indicator{"
|
||||
"width: px;"
|
||||
"height: px;"
|
||||
"subcontrol-position: left; }" );
|
||||
|
||||
style_mapTreeListWgt.replace( "width: ", "width: " + QString::number( CHECKBOX_SIZE ) );
|
||||
style_mapTreeListWgt.replace( "height: ", "height: " + QString::number( CHECKBOX_SIZE ) );
|
||||
|
||||
mapTreeListWgt->setStyleSheet( style_mapTreeListWgt );
|
||||
|
||||
mainLayout->addWidget( mapTreeListWgt );
|
||||
|
||||
offProjBtn = new QPushButton( QString( tr("Configuration") ) );
|
||||
offProjEnChk = new QCheckBox( QString( tr("Enabled") ) );
|
||||
|
||||
QString style_offProjEnChk( "QCheckBox::indicator{"
|
||||
"width: px;"
|
||||
"height: px;"
|
||||
"subcontrol-position: left; }" );
|
||||
|
||||
style_offProjEnChk.replace( "width: ", "width: " + QString::number( MainWindow::CHECKBOX_SIZE ) );
|
||||
style_offProjEnChk.replace( "height: ", "height: " + QString::number( MainWindow::CHECKBOX_SIZE ) );
|
||||
|
||||
offProjEnChk->setStyleSheet( style_offProjEnChk );
|
||||
|
||||
connect( offProjEnChk, SIGNAL( stateChanged(int) ), this, SLOT( offProjCheckBoxStateChangedSlot(int) ) );
|
||||
offProjEnChk->setChecked( false );
|
||||
offProjCheckBoxStateChangedSlot( 0 );
|
||||
connect( offProjBtn, SIGNAL( clicked( bool ) ), this, SLOT( offProjConfigBtnClickedSlot( bool ) ) );
|
||||
|
||||
QGroupBox *projectionGrpWgt = new QGroupBox(tr("Offline projection"));
|
||||
QHBoxLayout *projectionGrpLayout = new QHBoxLayout;
|
||||
|
||||
projectionGrpLayout->addWidget( offProjEnChk );
|
||||
projectionGrpLayout->addWidget( offProjBtn );
|
||||
projectionGrpWgt->setLayout( projectionGrpLayout );
|
||||
mainLayout->addWidget( projectionGrpWgt );
|
||||
|
||||
|
||||
applyButton = new QPushButton;
|
||||
applyButton->setText( tr("Apply") );
|
||||
connect( applyButton, SIGNAL( clicked( bool ) ),
|
||||
this, SLOT( applyBtnClicked( bool ) ) );
|
||||
|
||||
recacheAllBtn = new QPushButton;
|
||||
recacheAllBtn->setText( tr("Recache") );
|
||||
connect( recacheAllBtn, SIGNAL( clicked( bool ) ),
|
||||
this, SLOT( recacheAllBtnClicked( bool ) ) );
|
||||
|
||||
filterConfigBtn = new QPushButton;
|
||||
filterConfigBtn->setText( tr("Filter Config") );
|
||||
connect( filterConfigBtn, SIGNAL( clicked( bool ) ),
|
||||
this, SLOT( filterConfigBtnClicked( bool ) ) );
|
||||
|
||||
conversionBar = new QProgressBar;
|
||||
conversionBar->setValue( 0 );
|
||||
|
||||
controlWgt = new QWidget;
|
||||
controlLayout = new QHBoxLayout;
|
||||
|
||||
controlWgt->setLayout( controlLayout );
|
||||
controlLayout->addWidget( applyButton );
|
||||
controlLayout->addWidget( recacheAllBtn );
|
||||
controlLayout->addWidget( filterConfigBtn );
|
||||
|
||||
mainLayout->addWidget( controlWgt );
|
||||
mainLayout->addWidget( conversionBar );
|
||||
|
||||
char opt_val[GIS_MAX_PATH_LENGTH];
|
||||
QString extension;
|
||||
|
||||
MapFormatStrings s57_format;
|
||||
s57_format.dataSource = GIS_CORE_MAP_DATA_SOURCE_S57;
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_S57_CFG_SECTION, DRIVER_CFG_CONVERTER_PATH, &opt_val );
|
||||
s57_format.converterName = QString( opt_val );
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_S57_CFG_SECTION, DRIVER_CFG_MAP_FOLDER, &opt_val );
|
||||
s57_format.cacheFolder = mapsCachePath + QString( opt_val ) + "/";
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_S57_CFG_SECTION, DRIVER_CFG_FMT_EXTENSION, &opt_val );
|
||||
|
||||
extension = QString( opt_val );
|
||||
|
||||
s57_format.src_extension = QString( "*." + extension );
|
||||
s57_format.suffix = "." + extension + ".local.gcm";
|
||||
|
||||
MapFormatStrings sxf_format;
|
||||
sxf_format.dataSource = GIS_CORE_MAP_DATA_SOURCE_SXF;
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_SXF_CFG_SECTION, DRIVER_CFG_CONVERTER_PATH, &opt_val );
|
||||
sxf_format.converterName = QString( opt_val );
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_SXF_CFG_SECTION, DRIVER_CFG_MAP_FOLDER, &opt_val );
|
||||
sxf_format.cacheFolder = mapsCachePath + QString( opt_val ) + "/";
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_SXF_CFG_SECTION, DRIVER_CFG_FMT_EXTENSION, &opt_val );
|
||||
|
||||
extension = QString( opt_val );
|
||||
|
||||
sxf_format.src_extension = QString( "*." + extension );
|
||||
sxf_format.suffix = "." + extension + ".local.gcm";
|
||||
|
||||
MapFormatStrings shp_format;
|
||||
shp_format.dataSource = GIS_CORE_MAP_DATA_SOURCE_SHP;
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_SHP_CFG_SECTION, DRIVER_CFG_CONVERTER_PATH, &opt_val );
|
||||
shp_format.converterName = QString( opt_val );
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_SHP_CFG_SECTION, DRIVER_CFG_MAP_FOLDER, &opt_val );
|
||||
shp_format.cacheFolder = mapsCachePath + QString( opt_val ) + "/";
|
||||
|
||||
gis_core_config_get_driver_value( DRIVER_SHP_CFG_SECTION, DRIVER_CFG_FMT_EXTENSION, &opt_val );
|
||||
|
||||
extension = QString( opt_val );
|
||||
|
||||
shp_format.src_extension = QString( "*." + extension );
|
||||
shp_format.suffix = "." + extension + ".local.gcm";
|
||||
|
||||
format_string[GIS_CORE_MAP_DATA_SOURCE_S57] = s57_format;
|
||||
format_string[GIS_CORE_MAP_DATA_SOURCE_SXF] = sxf_format;
|
||||
format_string[GIS_CORE_MAP_DATA_SOURCE_SHP] = shp_format;
|
||||
|
||||
updateFilesList();
|
||||
updateExternalState();
|
||||
|
||||
addWidgetView();
|
||||
|
||||
gis_map_projection_init( &proj_params );
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if ( classFilterProcess )
|
||||
{
|
||||
disconnect( classFilterProcess, SIGNAL( finished(int,QProcess::ExitStatus) ),
|
||||
this, SLOT(classFilterExitCodeParser(int,QProcess::ExitStatus)) );
|
||||
|
||||
if ( ( classFilterProcess->state() == QProcess::Running ) ||
|
||||
( classFilterProcess->state() == QProcess::Starting) )
|
||||
{
|
||||
classFilterProcess->terminate();
|
||||
classFilterProcess->waitForFinished();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete mapTreeListWgt;
|
||||
}
|
||||
|
||||
void MainWindow::updateFilesList()
|
||||
{
|
||||
QString gcmFolder = mapsCachePath + GCM_SUFFIX + "/";
|
||||
|
||||
MapFormatStrings &s57_format = format_string[GIS_CORE_MAP_DATA_SOURCE_S57];
|
||||
MapFormatStrings &sxf_format = format_string[GIS_CORE_MAP_DATA_SOURCE_SXF];
|
||||
MapFormatStrings &shp_format = format_string[GIS_CORE_MAP_DATA_SOURCE_SHP];
|
||||
|
||||
mapStyleGCMList.clear();
|
||||
mapStyleGCMList << "Default";
|
||||
mapStyleGCMList << QDir( gcmFolder ).entryList( { "*.rsc.gcm", "*.sld.gcm" }, QDir::Files );
|
||||
|
||||
map_list.clear();
|
||||
map_uidx = 0;
|
||||
|
||||
MapEntry map_src;
|
||||
QStringList s57_maps = QDir( s57_format.cacheFolder ).entryList(
|
||||
QStringList( s57_format.src_extension ), QDir::Files );
|
||||
|
||||
for ( QString name : s57_maps )
|
||||
{
|
||||
map_src.dataSource = GIS_CORE_MAP_DATA_SOURCE_S57;
|
||||
map_src.isConverted = false;
|
||||
map_src.name = name;
|
||||
map_src.scale = 0;
|
||||
map_src.style_uidx = 0;
|
||||
map_list[map_uidx++] = map_src;
|
||||
}
|
||||
|
||||
QStringList sxf_maps = QDir( sxf_format.cacheFolder ).entryList(
|
||||
QStringList( sxf_format.src_extension ), QDir::Files );
|
||||
|
||||
for ( QString name : sxf_maps )
|
||||
{
|
||||
map_src.dataSource = GIS_CORE_MAP_DATA_SOURCE_SXF;
|
||||
map_src.isConverted = false;
|
||||
map_src.name = name;
|
||||
map_src.scale = 0;
|
||||
map_src.style_uidx = 0;
|
||||
map_list[map_uidx++] = map_src;
|
||||
}
|
||||
|
||||
QStringList shp_maps = QDir( shp_format.cacheFolder ).entryList(
|
||||
QStringList( shp_format.src_extension ), QDir::Dirs );
|
||||
|
||||
for ( QString name : shp_maps )
|
||||
{
|
||||
map_src.dataSource = GIS_CORE_MAP_DATA_SOURCE_SHP;
|
||||
map_src.isConverted = false;
|
||||
map_src.name = name;
|
||||
map_src.scale = 0;
|
||||
map_src.style_uidx = 0;
|
||||
map_list[map_uidx++] = map_src;
|
||||
}
|
||||
|
||||
mapGCMList.clear();
|
||||
mapGCMList << QDir( gcmFolder ).entryList( QStringList( ("*" + s57_format.suffix) ), QDir::Files );
|
||||
mapGCMList << QDir( gcmFolder ).entryList( QStringList( ("*" + sxf_format.suffix) ), QDir::Files );
|
||||
mapGCMList << QDir( gcmFolder ).entryList( QStringList( ("*" + shp_format.suffix) ), QDir::Files );
|
||||
}
|
||||
|
||||
void MainWindow::updateExternalState()
|
||||
{
|
||||
for ( int gcm_idx = 0; gcm_idx < mapGCMList.size(); gcm_idx++ )
|
||||
{
|
||||
QString gcm_fpath = QString( mapsCachePath + GCM_SUFFIX + "/" + mapGCMList[gcm_idx] );
|
||||
|
||||
gcm_map_header_t header;
|
||||
gcm_read_file_header( gcm_fpath.toStdString().c_str(), &header );
|
||||
|
||||
for ( MapEntry &map : map_list )
|
||||
{
|
||||
if ( map.name.contains( header.src_filename ) )
|
||||
{
|
||||
map.isConverted = true;
|
||||
map.gcm_name = mapGCMList[gcm_idx];
|
||||
if ( map.dataSource == GIS_CORE_MAP_DATA_SOURCE_SXF ||
|
||||
map.dataSource == GIS_CORE_MAP_DATA_SOURCE_SHP )
|
||||
{
|
||||
map.style_uidx = mapStyleGCMList.indexOf( QRegExp( QString( header.style_filename ) ) );
|
||||
}
|
||||
|
||||
map.dataSource = (gis_core_map_data_source_t)header.data_source;
|
||||
map.scale = header.map_scale_denominator;
|
||||
map.update = header.src_version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::offProjCheckBoxStateChangedSlot( int state )
|
||||
{
|
||||
offProjBtn->setEnabled( state );
|
||||
}
|
||||
|
||||
void MainWindow::offProjConfigBtnClickedSlot( bool state )
|
||||
{
|
||||
Q_UNUSED( state );
|
||||
gis_gui_get_projection_parameters( &proj_params, this );
|
||||
}
|
||||
|
||||
void MainWindow::mapStyleChangedSlot()
|
||||
{
|
||||
QComboBox *map_style_combobox = qobject_cast<QComboBox*>( sender() );
|
||||
QTreeWidgetItem *item = NULL;
|
||||
|
||||
for ( int idx = 0; idx < mapTreeListWgt->topLevelItemCount(); ++idx )
|
||||
{
|
||||
item = mapTreeListWgt->topLevelItem( idx );
|
||||
|
||||
if ( map_style_combobox == qobject_cast<QComboBox*>( mapTreeListWgt->itemWidget( item, COLUMN_STYLE_NAME ) ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( item == NULL )
|
||||
return;
|
||||
|
||||
item->setCheckState( COLUMN_IS_MAP_CONVERTED, Qt::Checked );
|
||||
}
|
||||
|
||||
void MainWindow::addWidgetView()
|
||||
{
|
||||
mapTreeListWgt->setColumnCount( COLUMN_COUNT );
|
||||
|
||||
mapTreeListWgt->setHeaderLabels(
|
||||
QStringList() << "#" << " " << tr("Map") << tr("Map style") << tr("Scale") << tr("Type") );
|
||||
|
||||
mapTreeListWgt->setColumnWidth( COLUMN_IDX, 50 );
|
||||
mapTreeListWgt->setColumnWidth( COLUMN_IS_MAP_CONVERTED, 50 );
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 7, 0))
|
||||
mapTreeListWgt->header()->setResizeMode( QHeaderView::ResizeToContents );
|
||||
#else
|
||||
mapTreeListWgt->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
|
||||
#endif
|
||||
|
||||
for ( int i = 0; i < map_uidx; ++i )
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem( mapTreeListWgt );
|
||||
item->setText( COLUMN_IDX, QString::number(i) );
|
||||
MapEntry &map = map_list[i];
|
||||
|
||||
if ( map.dataSource == GIS_CORE_MAP_DATA_SOURCE_S57 )
|
||||
{
|
||||
MapFormatStrings &s57_format = format_string[GIS_CORE_MAP_DATA_SOURCE_S57];
|
||||
|
||||
QString map_name_filter = map.name;
|
||||
map_name_filter.replace( ".000", ".*" );
|
||||
|
||||
QRegularExpression files_ext_filter_rx( "\\A.*\\.{1}[0-9][0-9][0-9]" );
|
||||
|
||||
QString working_dir = s57_format.cacheFolder;
|
||||
QString hidden_dir = s57_format.cacheFolder + S57MapComboBox::UNUSED_DIR_NAME;
|
||||
|
||||
QStringList s57_map_name_files = QDir( working_dir ).entryList( { map_name_filter }, QDir::Files );
|
||||
|
||||
QStringList s57_map_files = s57_map_name_files.filter( files_ext_filter_rx );
|
||||
|
||||
QStringList s57_map_update_files_hidden = QDir( hidden_dir ).entryList( { map_name_filter }, QDir::Files );
|
||||
|
||||
if ( s57_map_files.size() > 1 || s57_map_update_files_hidden.size() > 0 )
|
||||
{
|
||||
|
||||
S57MapComboBox *interactive_map_name = new S57MapComboBox( working_dir,
|
||||
s57_map_files,
|
||||
s57_map_update_files_hidden );
|
||||
|
||||
mapTreeListWgt->setItemWidget( item, COLUMN_MAP_NAME, interactive_map_name );
|
||||
}
|
||||
else
|
||||
item->setText( COLUMN_MAP_NAME, map.name );
|
||||
}
|
||||
else
|
||||
item->setText( COLUMN_MAP_NAME, map.name );
|
||||
|
||||
item->setText( COLUMN_MAP_SCALE, QString::number(map.scale) );
|
||||
item->setText( COLUMN_MAP_DATA_SOURCE, gis_helper_get_core_data_source_name( map.dataSource ) );
|
||||
|
||||
QComboBox *map_style_combobox = new QComboBox;
|
||||
|
||||
map_style_combobox->addItems( mapStyleGCMList );
|
||||
map_style_combobox->setCurrentIndex( map.style_uidx );
|
||||
|
||||
if ( map.dataSource == GIS_CORE_MAP_DATA_SOURCE_S57 )
|
||||
map_style_combobox->setEnabled( false );
|
||||
|
||||
connect( map_style_combobox, SIGNAL( currentIndexChanged(int) ),
|
||||
this, SLOT( mapStyleChangedSlot() ) );
|
||||
|
||||
mapTreeListWgt->setItemWidget( item, COLUMN_STYLE_NAME, map_style_combobox );
|
||||
|
||||
item->setFlags( item->flags() | Qt::ItemIsUserCheckable );
|
||||
|
||||
if ( map.isConverted )
|
||||
item->setCheckState( COLUMN_IS_MAP_CONVERTED, Qt::Checked );
|
||||
else
|
||||
item->setCheckState( COLUMN_IS_MAP_CONVERTED, Qt::Unchecked );
|
||||
|
||||
mapTreeListWgt->addTopLevelItem( item );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateWidgetView()
|
||||
{
|
||||
for ( int i = 0; i < map_uidx; ++i )
|
||||
{
|
||||
QTreeWidgetItem *item = mapTreeListWgt->topLevelItem( i );
|
||||
MapEntry &map = map_list[i];
|
||||
|
||||
item->setCheckState( COLUMN_IS_MAP_CONVERTED, map.isConverted ? Qt::Checked : Qt::Unchecked );
|
||||
|
||||
QComboBox *map_style_combobox = qobject_cast<QComboBox*>( mapTreeListWgt->itemWidget( item, COLUMN_STYLE_NAME ) );
|
||||
|
||||
map_style_combobox->clear();
|
||||
map_style_combobox->addItems( mapStyleGCMList );
|
||||
map_style_combobox->setCurrentIndex( map.style_uidx );
|
||||
|
||||
item->setText( COLUMN_MAP_SCALE, QString::number( map.scale ) );
|
||||
item->setText( COLUMN_MAP_DATA_SOURCE, gis_helper_get_core_data_source_name( map.dataSource ) );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::taskExecutedSlot( void )
|
||||
{
|
||||
++processing_idx;
|
||||
conversionBar->setValue( processing_idx * deltaProgress );
|
||||
|
||||
if ( processing_idx >= taskCount )
|
||||
{
|
||||
conversionBar->setValue( 100 );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::executeTasks( QVector<ConversionTask> &tasks )
|
||||
{
|
||||
if ( tasks.size() == 0 )
|
||||
{
|
||||
qDebug() << "No tasks";
|
||||
}
|
||||
else
|
||||
{
|
||||
deltaProgress = 100.0 / (tasks.size() + 1);
|
||||
processing_idx = 0;
|
||||
taskCount = tasks.size();
|
||||
|
||||
conversionBar->setValue( 0 );
|
||||
|
||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
||||
threadPool->setMaxThreadCount( _syspage_ptr->num_cpu );
|
||||
|
||||
qDebug() << "Processing through" << _syspage_ptr->num_cpu << "threads";
|
||||
|
||||
foreach ( ConversionTask task, tasks )
|
||||
{
|
||||
static uint64_t g_taskId = 0;
|
||||
|
||||
qDebug() << "Task #" << g_taskId << " " << gis_helper_get_core_data_source_name( task.m_dataSource );
|
||||
|
||||
switch( task.m_type )
|
||||
{
|
||||
case ConversionTask::TASK_CONVERT:
|
||||
{
|
||||
const char *gis_root = gis_helper_env_get_gis_root_directory();
|
||||
|
||||
QString program = QString( gis_root ) + "/" + format_string[task.m_dataSource].converterName;
|
||||
|
||||
QStringList arguments;
|
||||
|
||||
arguments << "-m" << task.m_srcMapFilepath;
|
||||
if ( !task.m_styleFilepath.isEmpty() )
|
||||
arguments << "-r" << task.m_styleFilepath;
|
||||
arguments << "-o" << task.m_gcmFilepath;
|
||||
arguments << "-f";
|
||||
|
||||
if ( offProjEnChk->checkState() == Qt::Checked )
|
||||
{
|
||||
char buffer[GIS_MAX_PATH_LENGTH];
|
||||
gishelper_math_encode_proj_string( &proj_params, buffer );
|
||||
arguments << "-c" << QString::fromLatin1( buffer );
|
||||
}
|
||||
|
||||
qDebug() << "Program" << program << "Convert" << arguments;
|
||||
|
||||
ConversionTaskWork *work = new ConversionTaskWork( program, arguments, g_taskId );
|
||||
|
||||
connect( work, SIGNAL( taskExecutedSignal( void ) ), this, SLOT( taskExecutedSlot( void ) ) );
|
||||
|
||||
threadPool->start( work );
|
||||
break;
|
||||
}
|
||||
case ConversionTask::TASK_REMOVE:
|
||||
{
|
||||
qDebug() << "Remove" << task.m_gcmFilepath;
|
||||
|
||||
QFile gcmFile( task.m_gcmFilepath );
|
||||
gcmFile.remove();
|
||||
|
||||
taskExecutedSlot();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
taskExecutedSlot();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++g_taskId;
|
||||
}
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( threadPool->waitForDone( 100 ) )
|
||||
break;
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
qDebug() << "Done!";
|
||||
|
||||
gis_core_request_update_cache( &connection, GIS_CORE_DRIVERS_ALL, GIS_CORE_UPDATE_CACHE_MODE_SOFT_UPDATE );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::filterConfigBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED( clicked );
|
||||
|
||||
QString program = QString( gis_helper_env_get_gis_root_directory() ) +
|
||||
"/" + QString( GIS_EXEC_PATH_FILTER_GENERATOR );
|
||||
|
||||
classFilterProcess = new QProcess( this );
|
||||
connect( classFilterProcess, SIGNAL( finished( int,QProcess::ExitStatus ) ),
|
||||
this, SLOT(classFilterExitCodeParser( int,QProcess::ExitStatus ) ) );
|
||||
classFilterProcess->setProcessChannelMode( QProcess::ForwardedChannels );
|
||||
|
||||
QPoint pos = this->mapToGlobal( QPoint( 0,0 ) );
|
||||
classFilterProcess->start( program, { "-x" + QString::number( pos.x() ),
|
||||
"-y" + QString::number( pos.y() ) } );
|
||||
}
|
||||
|
||||
void MainWindow::classFilterExitCodeParser( int exitCode, QProcess::ExitStatus status )
|
||||
{
|
||||
Q_UNUSED( status );
|
||||
qDebug() << "Result: " << QString::number( exitCode );
|
||||
if ( exitCode > 0 )
|
||||
recacheAllBtnClicked( false );
|
||||
}
|
||||
|
||||
void MainWindow::recacheAllBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED( clicked );
|
||||
QVector<ConversionTask> tasks;
|
||||
|
||||
for ( int i = 0; i < map_uidx; i++ )
|
||||
{
|
||||
QTreeWidgetItem *item = mapTreeListWgt->topLevelItem( i );
|
||||
MapEntry &map = map_list[i];
|
||||
|
||||
auto ds = map.dataSource;
|
||||
|
||||
bool need_to_convert = item->checkState( COLUMN_IS_MAP_CONVERTED ) == Qt::Checked;
|
||||
|
||||
QString styleName = ( (QComboBox *)mapTreeListWgt->itemWidget( item, COLUMN_STYLE_NAME ) )->currentText();
|
||||
|
||||
int style_idx = mapStyleGCMList.indexOf( styleName );
|
||||
|
||||
QString map_path = format_string[ds].cacheFolder + "/" + map.name;
|
||||
|
||||
QString classificator_path;
|
||||
if ( style_idx != 0 )
|
||||
classificator_path = mapsCachePath + GCM_SUFFIX + "/" + mapStyleGCMList[style_idx];
|
||||
|
||||
QString gcm_map_path = mapsCachePath + GCM_SUFFIX +
|
||||
"/" + ( map.gcm_name.isEmpty() ? map.name + ".local.gcm" : map.gcm_name );
|
||||
|
||||
ConversionTask task_remove( map_path, classificator_path, gcm_map_path, ConversionTask::TASK_REMOVE, ds );
|
||||
ConversionTask task_convert( map_path, classificator_path, gcm_map_path, ConversionTask::TASK_CONVERT, ds );
|
||||
|
||||
if ( need_to_convert )
|
||||
{
|
||||
tasks << task_remove;
|
||||
tasks << task_convert;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( map.isConverted )
|
||||
{
|
||||
tasks << task_remove;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
executeTasks( tasks );
|
||||
|
||||
updateFilesList();
|
||||
updateExternalState();
|
||||
updateWidgetView();
|
||||
}
|
||||
|
||||
void MainWindow::applyBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED( clicked );
|
||||
QVector<ConversionTask> tasks;
|
||||
|
||||
for ( int i = 0; i < map_uidx; i++ )
|
||||
{
|
||||
QTreeWidgetItem *item = mapTreeListWgt->topLevelItem( i );
|
||||
MapEntry &map = map_list[i];
|
||||
|
||||
bool need_to_convert = item->checkState( COLUMN_IS_MAP_CONVERTED ) == Qt::Checked;
|
||||
|
||||
int styleIndex = ( (QComboBox *)mapTreeListWgt->itemWidget( item, COLUMN_STYLE_NAME ) )->currentIndex();
|
||||
|
||||
gis_core_map_data_source_t ds = map.dataSource;
|
||||
|
||||
QString srcMapPath = format_string[ds].cacheFolder + "/" + map.name;
|
||||
QString stylePathStr;
|
||||
|
||||
if ( styleIndex != 0 )
|
||||
stylePathStr = mapsCachePath + GCM_SUFFIX + "/" + mapStyleGCMList[styleIndex];
|
||||
|
||||
QString outPath = mapsCachePath + GCM_SUFFIX +
|
||||
"/" + ( map.gcm_name.isEmpty() ? ( map.name + ".local.gcm" ) : map.gcm_name );
|
||||
|
||||
int type = ConversionTask::TASK_NONE;
|
||||
|
||||
if ( need_to_convert )
|
||||
{
|
||||
if ( styleIndex != map.style_uidx )
|
||||
{
|
||||
type = ConversionTask::TASK_CONVERT;
|
||||
}
|
||||
|
||||
if ( map.dataSource == GIS_CORE_MAP_DATA_SOURCE_S57 )
|
||||
{
|
||||
S57MapComboBox *map_updates_cb = qobject_cast<S57MapComboBox*>(
|
||||
mapTreeListWgt->itemWidget( item, COLUMN_MAP_NAME ) );
|
||||
|
||||
if ( map_updates_cb )
|
||||
{
|
||||
QString update_filename = map_updates_cb->currentText();
|
||||
QString extension = update_filename.remove( 0, update_filename.lastIndexOf( '.' ) + 1 );
|
||||
|
||||
if ( extension != map.update )
|
||||
{
|
||||
type = ConversionTask::TASK_CONVERT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( map.isConverted )
|
||||
{
|
||||
type = ConversionTask::TASK_REMOVE;
|
||||
}
|
||||
}
|
||||
ConversionTask task( srcMapPath, stylePathStr, outPath, type, ds );
|
||||
tasks << task;
|
||||
}
|
||||
|
||||
executeTasks( tasks );
|
||||
|
||||
qDebug() << "apply";
|
||||
updateFilesList();
|
||||
qDebug() << "updateFilesList() \t- done";
|
||||
|
||||
updateExternalState();
|
||||
qDebug() << "updateExternalState() \t- done";
|
||||
|
||||
updateWidgetView();
|
||||
qDebug() << "updateWidgetView() \t- done";
|
||||
|
||||
}
|
||||
|
||||
|
||||
S57MapComboBox::S57MapComboBox( QString s57_cache_folder,
|
||||
QStringList map_files_list,
|
||||
QStringList update_files_list_hidden,
|
||||
QWidget *parent ) :
|
||||
QComboBox( parent ),
|
||||
m_working_dir( s57_cache_folder ),
|
||||
m_hidden_files_list( update_files_list_hidden )
|
||||
{
|
||||
m_unused_upd_files_dir = new QDir( m_working_dir + S57MapComboBox::UNUSED_DIR_NAME );
|
||||
|
||||
if ( !m_unused_upd_files_dir->exists() )
|
||||
m_unused_upd_files_dir->mkdir( m_working_dir );
|
||||
|
||||
if ( !m_unused_upd_files_dir->exists() )
|
||||
{
|
||||
qDebug() << "S57MapUpdateFilesDialog: Failed to create dir: " <<
|
||||
m_unused_upd_files_dir->absolutePath();
|
||||
return;
|
||||
}
|
||||
|
||||
m_all_files_list.append( map_files_list );
|
||||
m_all_files_list.append( update_files_list_hidden );
|
||||
|
||||
m_all_files_list.sort();
|
||||
|
||||
addItems( m_all_files_list );
|
||||
|
||||
connect( this, SIGNAL( currentIndexChanged( int ) ),
|
||||
this, SLOT( updateFileMove( int ) ) );
|
||||
|
||||
setCurrentIndex( findText( map_files_list.back() ) );
|
||||
}
|
||||
|
||||
S57MapComboBox::~S57MapComboBox()
|
||||
{
|
||||
delete m_unused_upd_files_dir;
|
||||
}
|
||||
|
||||
void S57MapComboBox::updateFileMove( int curr_idx )
|
||||
{
|
||||
for ( int idx = 1; idx < this->count(); ++idx )
|
||||
{
|
||||
QString filename = this->itemText( idx );
|
||||
QString filepath = m_working_dir + "/" + filename;
|
||||
QString hidden_filepath = m_unused_upd_files_dir->absolutePath() + "/" + filename;
|
||||
|
||||
if ( idx <= curr_idx && m_hidden_files_list.contains( filename ) )
|
||||
{
|
||||
QFile( hidden_filepath ).rename( filepath );
|
||||
m_hidden_files_list.removeAll( filename );
|
||||
}
|
||||
else if ( idx > curr_idx && !m_hidden_files_list.contains( filename ) )
|
||||
{
|
||||
QFile( filepath ).rename( hidden_filepath );
|
||||
m_hidden_files_list.append( filename );
|
||||
}
|
||||
}
|
||||
}
|
293
src/apps/gis-map-linker/mainwindow.h
Обычный файл
@ -0,0 +1,293 @@
|
||||
/*
|
||||
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 MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
#include <QPointer>
|
||||
#include <QProcess>
|
||||
#include <QMouseEvent>
|
||||
#include <QThreadPool>
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCoreApplication>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMainWindow>
|
||||
#include <QProgressBar>
|
||||
#include <QPushButton>
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
|
||||
#define SXF_LINKER_PREFIX "[sxf_linker] "
|
||||
|
||||
struct CleanExit
|
||||
{
|
||||
CleanExit()
|
||||
{
|
||||
signal(SIGINT, &CleanExit::exitQt);
|
||||
signal(SIGTERM, &CleanExit::exitQt);
|
||||
}
|
||||
|
||||
static void exitQt( int sig )
|
||||
{
|
||||
Q_UNUSED(sig);
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
};
|
||||
|
||||
struct MapState
|
||||
{
|
||||
int gcmIdx;
|
||||
bool isConverted;
|
||||
int styleIndex;
|
||||
uint32_t scale;
|
||||
gis_core_map_data_source_t dataSource;
|
||||
};
|
||||
|
||||
struct MapFormatStrings
|
||||
{
|
||||
gis_core_map_data_source_t dataSource;
|
||||
QString converterName;
|
||||
QString cacheFolder;
|
||||
QString suffix;
|
||||
QString src_extension;
|
||||
|
||||
};
|
||||
|
||||
struct MapEntry
|
||||
{
|
||||
bool isConverted;
|
||||
QString name;
|
||||
QString gcm_name;
|
||||
QString update;
|
||||
int style_uidx;
|
||||
uint32_t scale;
|
||||
gis_core_map_data_source_t dataSource;
|
||||
};
|
||||
|
||||
struct StyleEntry
|
||||
{
|
||||
QString name;
|
||||
};
|
||||
|
||||
|
||||
struct ConversionTask
|
||||
{
|
||||
public:
|
||||
ConversionTask()
|
||||
{
|
||||
m_srcMapFilepath = "";
|
||||
m_styleFilepath = "";
|
||||
m_gcmFilepath = "";
|
||||
m_dataSource = GIS_CORE_MAP_DATA_SOURCE_NONE;
|
||||
m_type = TASK_NONE;
|
||||
}
|
||||
|
||||
ConversionTask( QString map_path,
|
||||
QString classificator_path,
|
||||
QString gcm_map_path,
|
||||
int type,
|
||||
gis_core_map_data_source_t dataSource ):
|
||||
m_srcMapFilepath( map_path ),
|
||||
m_styleFilepath( classificator_path ),
|
||||
m_gcmFilepath( gcm_map_path ),
|
||||
m_type( type ),
|
||||
m_dataSource( dataSource )
|
||||
{}
|
||||
|
||||
ConversionTask( const ConversionTask &task )
|
||||
{
|
||||
Copy( task );
|
||||
}
|
||||
|
||||
ConversionTask &operator =( const ConversionTask &task )
|
||||
{
|
||||
Copy( task );
|
||||
return *this;
|
||||
}
|
||||
|
||||
QString m_srcMapFilepath;
|
||||
QString m_styleFilepath;
|
||||
QString m_gcmFilepath;
|
||||
gis_core_map_data_source_t m_dataSource;
|
||||
|
||||
enum {
|
||||
TASK_NONE,
|
||||
TASK_CONVERT,
|
||||
TASK_REMOVE
|
||||
};
|
||||
int m_type;
|
||||
|
||||
private:
|
||||
void Copy( const ConversionTask &task )
|
||||
{
|
||||
m_srcMapFilepath = task.m_srcMapFilepath;
|
||||
m_styleFilepath = task.m_styleFilepath;
|
||||
m_gcmFilepath = task.m_gcmFilepath;
|
||||
m_dataSource = task.m_dataSource;
|
||||
m_type = task.m_type;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ConversionTaskWork : public QObject, public QRunnable
|
||||
{
|
||||
QString m_prog;
|
||||
QStringList m_args;
|
||||
uint64_t m_id;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConversionTaskWork( QString prog, QStringList args, uint64_t taskId, QObject *parent = nullptr ) :
|
||||
QObject( parent ), m_prog( prog ), m_args( args ), m_id( taskId )
|
||||
{}
|
||||
|
||||
void run()
|
||||
{
|
||||
QProcess *myProcess = new QProcess();
|
||||
myProcess->setProcessChannelMode( QProcess::SeparateChannels );
|
||||
int ret = myProcess->execute( m_prog, m_args );
|
||||
|
||||
delete myProcess;
|
||||
|
||||
qDebug() << "Result #" << m_id << ": " << QString::number( ret );
|
||||
|
||||
emit taskExecutedSignal();
|
||||
}
|
||||
|
||||
signals:
|
||||
void taskExecutedSignal( void );
|
||||
};
|
||||
|
||||
|
||||
class S57MapComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
S57MapComboBox( QString s57_cache_folder,
|
||||
QStringList map_files_list,
|
||||
QStringList update_files_list_hidden,
|
||||
QWidget *parent = 0 );
|
||||
|
||||
~S57MapComboBox();
|
||||
|
||||
static QString UNUSED_DIR_NAME;
|
||||
|
||||
private:
|
||||
QDir *m_unused_upd_files_dir;
|
||||
|
||||
QString m_working_dir;
|
||||
QStringList m_all_files_list;
|
||||
QStringList m_hidden_files_list;
|
||||
|
||||
private slots:
|
||||
void updateFileMove( int sender_box_state );
|
||||
};
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow( QWidget *parent = 0 );
|
||||
~MainWindow();
|
||||
|
||||
static int CHECKBOX_SIZE;
|
||||
|
||||
public slots:
|
||||
void taskExecutedSlot();
|
||||
|
||||
private:
|
||||
|
||||
QMap<gis_core_map_data_source_t, MapFormatStrings> format_string;
|
||||
|
||||
int map_uidx;
|
||||
int style_uidx;
|
||||
QMap<int, MapEntry> map_list;
|
||||
QMap<int, StyleEntry> style_list;
|
||||
|
||||
QString mapsCachePath;
|
||||
gis_core_connection_t connection;
|
||||
gis_map_projection_t proj_params;
|
||||
|
||||
QProcess *classFilterProcess;
|
||||
|
||||
QPushButton *offProjBtn;
|
||||
QCheckBox *offProjEnChk;
|
||||
|
||||
QStringList mapStyleGCMList;
|
||||
QStringList mapGCMList;
|
||||
|
||||
QPushButton *applyButton;
|
||||
QPushButton *recacheAllBtn;
|
||||
QPushButton *filterConfigBtn;
|
||||
|
||||
QProgressBar *conversionBar;
|
||||
QWidget *controlWgt;
|
||||
QHBoxLayout *controlLayout;
|
||||
|
||||
QTreeWidget *mapTreeListWgt;
|
||||
|
||||
int processing_idx;
|
||||
double deltaProgress;
|
||||
int taskCount;
|
||||
|
||||
protected:
|
||||
|
||||
void addWidgetView();
|
||||
void updateWidgetView();
|
||||
|
||||
void updateFilesList();
|
||||
void updateExternalState();
|
||||
|
||||
void executeTasks(QVector<ConversionTask> &tasks);
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
void offProjConfigBtnClickedSlot(bool state);
|
||||
void offProjCheckBoxStateChangedSlot(int state);
|
||||
|
||||
void filterConfigBtnClicked(bool clicked);
|
||||
|
||||
void recacheAllBtnClicked(bool clicked);
|
||||
|
||||
void mapStyleChangedSlot();
|
||||
|
||||
void applyBtnClicked( bool clicked );
|
||||
|
||||
void classFilterExitCodeParser(int,QProcess::ExitStatus);
|
||||
};
|
||||
|
||||
#endif
|
6
src/apps/gis-map-linker/translations.qrc
Обычный файл
@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>translations/gis-map-linker_ru.ts</file>
|
||||
<file>translations/gis-map-linker_ru.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
51
src/apps/gis-map-linker/translations/gis-map-linker_ru.ts
Обычный файл
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="ru_RU">
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<source>Configuration</source>
|
||||
<translation>Настройка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabled</source>
|
||||
<translation>Задействовать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Offline projection</source>
|
||||
<translation>Офлайн проецирование</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Apply</source>
|
||||
<translation>Применить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Recache</source>
|
||||
<translation>Обновить кэш</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Filter Config</source>
|
||||
<translation>Настройка фильтра</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Scale</source>
|
||||
<translation>Масштаб</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map</source>
|
||||
<translation>Карта</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map style</source>
|
||||
<translation>Классификатор</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Type</source>
|
||||
<translation>Тип</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map Configurator</source>
|
||||
<translation>Редактор связей карт и стилей</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
87
src/apps/gis-map-viewer/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,87 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( gis-map-viewer LANGUAGES CXX )
|
||||
|
||||
set( CMAKE_AUTOMOC ON )
|
||||
set( CMAKE_AUTOUIC ON )
|
||||
set( CMAKE_AUTORCC ON )
|
||||
|
||||
add_compile_options( -std=gnu++11 )
|
||||
add_compile_options( -Wno-ignored-attributes )
|
||||
add_compile_options( -Wno-deprecated-declarations )
|
||||
|
||||
if( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm" )
|
||||
add_compile_options( -Wno-psabi )
|
||||
endif()
|
||||
|
||||
find_package( Qt5
|
||||
COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
REQUIRED )
|
||||
|
||||
file( GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/configuration/*.conf
|
||||
userdialog.ui
|
||||
resources.qrc
|
||||
translations.qrc )
|
||||
|
||||
add_executable( gis-map-viewer ${SOURCES} )
|
||||
|
||||
add_custom_command( OUTPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-map-viewer_ru.qm
|
||||
COMMAND
|
||||
$ENV{KPDA_HOST}/usr/lib/Qt/bin/lrelease -silent ${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts )
|
||||
|
||||
add_custom_target( generate_translations_map_viewer
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-map-viewer_ru.qm )
|
||||
|
||||
target_include_directories( gis-map-viewer
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/public
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gisrender/api/public
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/surfacemanager/public
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
||||
|
||||
add_dependencies( gis-map-viewer generate_translations_map_viewer )
|
||||
|
||||
target_link_libraries( gis-map-viewer
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
gishelper
|
||||
gisrender
|
||||
surfacemanager )
|
||||
|
||||
|
||||
install( TARGETS gis-map-viewer
|
||||
RUNTIME DESTINATION bin )
|
||||
install( FILES configuration/gis-map-viewer.conf DESTINATION data/config )
|
16
src/apps/gis-map-viewer/README.md
Обычный файл
@ -0,0 +1,16 @@
|
||||
|
||||
Утилита для просмотра визуальной картографической информации.
|
||||
|
||||
Описание:
|
||||
Предназначена для отображения картографической информации и демонстрации возможностей API КПО ГИС . Программа позволяет управлять типами отображаемой информации, параметрами отображения и взаимодействовать с картографическим ядром.
|
||||
|
||||
Структура:
|
||||
* distancemeter.(cpp/h) Виджет, предоставляющий интерфейс измерений длин и площадей.
|
||||
* heightscale.(cpp/h) Визуализация растровой палитры.
|
||||
* layerwindow.(cpp/h) Интерфейс управления слоями движка рендеринга.
|
||||
* mainwindow.(cpp/h) Главное окно программы просмотра картографической информации.
|
||||
* mapstylelayerwindow.(cpp/h) Интерфейс управления слоями карты.
|
||||
* mapwidget.(cpp/h) Виджет, предоставляющий интерфейс для работы с картографическим пакетом.
|
||||
* objectinfo.(cpp/h) Виджет, отображающий сведения о выбранном объекте.
|
||||
* userdialog.(cpp/h) Интерфейс создания пользовательских объектов.
|
||||
* viewparameters.(cpp/h) Виджет, предоставляющий интерфейс настройки яркости и контрастности отображения.
|
Двоичные данные
src/apps/gis-map-viewer/asserts/view.png
Обычный файл
После Ширина: | Высота: | Размер: 406 KiB |
34
src/apps/gis-map-viewer/configuration/gis-map-viewer.conf
Обычный файл
@ -0,0 +1,34 @@
|
||||
[InterfaceParameters]
|
||||
buttonBorderOffset=16
|
||||
iconSideSizePx=32
|
||||
maxHeight=2106
|
||||
maxWidth=1910
|
||||
minHeight=400
|
||||
minWidth=400
|
||||
objectSearchSideSizePx=100
|
||||
|
||||
[MainWindow]
|
||||
window_x=0
|
||||
window_y=0
|
||||
width=800
|
||||
height=644
|
||||
lastOpenedTabIndex=0
|
||||
oneMapMode=true
|
||||
sharedMemoryUserId=777
|
||||
|
||||
[MapDisplayParameters]
|
||||
brightness=0
|
||||
contrast=0
|
||||
invalidRasterHeightColor=0x00FF0000
|
||||
maximumRasterHeightMeters=1666
|
||||
minimumRasterHeightMeters=0
|
||||
|
||||
[MapWidget]
|
||||
scales=20000000, 10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000, 50000, 25000, 10000, 5000, 2000
|
||||
size=2
|
||||
|
||||
[SurfaceManager]
|
||||
allocInRam=false
|
||||
blitRegionRate=0.5
|
||||
offscreenExtension=500
|
||||
smMode=0
|
150
src/apps/gis-map-viewer/deptheditor.cpp
Обычный файл
@ -0,0 +1,150 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "deptheditor.h"
|
||||
|
||||
DepthEditor::DepthEditor( QWidget *parent ) :
|
||||
QDialog( parent )
|
||||
{
|
||||
setWindowTitle( tr( "Depth Editor" ) );
|
||||
|
||||
vlayout = new QVBoxLayout();
|
||||
shallow_contour_lay = new QHBoxLayout();
|
||||
safety_contour_lay = new QHBoxLayout();
|
||||
safety_depth_lay = new QHBoxLayout();
|
||||
deep_contour_lay = new QHBoxLayout();
|
||||
two_color_depth_lay = new QHBoxLayout();
|
||||
shallow_pattern_lay = new QHBoxLayout();
|
||||
buttons_lay = new QHBoxLayout();
|
||||
|
||||
double *s57_SFD{new double};
|
||||
double *s57_SHC{new double};
|
||||
double *s57_SFC{new double};
|
||||
double *s57_DPC{new double};
|
||||
bool *s57_two_shades{new bool};
|
||||
bool *s57_shallow_pattern{new bool};
|
||||
|
||||
gis_map_style_get_SEABED( s57_SFD, s57_SHC, s57_SFC, s57_DPC, s57_two_shades, s57_shallow_pattern );
|
||||
|
||||
initSpinBox( shallow_contour_spinbox, *s57_SHC );
|
||||
shallow_contour_lay->addWidget( new QLabel( tr( "Shallow Contour" ) ) );
|
||||
shallow_contour_lay->addWidget( shallow_contour_spinbox );
|
||||
|
||||
initSpinBox( safety_contour_spinbox, *s57_SFC );
|
||||
safety_contour_lay->addWidget( new QLabel( tr( "Safety Contour" ) ) );
|
||||
safety_contour_lay->addWidget( safety_contour_spinbox );
|
||||
|
||||
initSpinBox( safety_depth_spinbox, *s57_SFD );
|
||||
safety_depth_lay->addWidget( new QLabel( tr( "Safety Depth" ) ) );
|
||||
safety_depth_lay->addWidget( safety_depth_spinbox );
|
||||
|
||||
initSpinBox( deep_contour_spinbox, *s57_DPC );
|
||||
deep_contour_lay->addWidget( new QLabel( tr( "Deep Contour" ) ) );
|
||||
deep_contour_lay->addWidget( deep_contour_spinbox );
|
||||
|
||||
initCheckBox( two_color_depth_chkbox, *s57_two_shades );
|
||||
two_color_depth_lay->addWidget( new QLabel( tr( "Use Two Color Depth" ) ) );
|
||||
two_color_depth_lay->addWidget( two_color_depth_chkbox );
|
||||
|
||||
initCheckBox( shallow_pattern_chkbox, *s57_shallow_pattern );
|
||||
shallow_pattern_lay->addWidget( new QLabel( tr( "Use Shallow Pattern" ) ) );
|
||||
shallow_pattern_lay->addWidget( shallow_pattern_chkbox );
|
||||
|
||||
accept_btn = new QPushButton( tr( "Accept" ) );
|
||||
connect( accept_btn, SIGNAL( released() ),
|
||||
this, SLOT( acceptAndChange() ) );
|
||||
|
||||
cancel_btn = new QPushButton( tr( "Cancel" ) );
|
||||
connect( cancel_btn, SIGNAL( released() ),
|
||||
this, SLOT( close() ) );
|
||||
|
||||
buttons_lay->addWidget( accept_btn );
|
||||
buttons_lay->addWidget( cancel_btn );
|
||||
|
||||
vlayout->addLayout( shallow_contour_lay );
|
||||
vlayout->addLayout( safety_contour_lay );
|
||||
vlayout->addLayout( safety_depth_lay );
|
||||
vlayout->addLayout( deep_contour_lay );
|
||||
vlayout->addLayout( two_color_depth_lay );
|
||||
vlayout->addLayout( shallow_pattern_lay );
|
||||
vlayout->addLayout( buttons_lay );
|
||||
|
||||
setLayout( vlayout );
|
||||
|
||||
delete s57_SFD;
|
||||
delete s57_SHC;
|
||||
delete s57_SFC;
|
||||
delete s57_DPC;
|
||||
delete s57_two_shades;
|
||||
delete s57_shallow_pattern;
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
|
||||
}
|
||||
|
||||
void DepthEditor::showEvent( QShowEvent *event )
|
||||
{
|
||||
if ( parentWidget() )
|
||||
{
|
||||
int x = ( parentWidget()->width() - ( 15 + sizeHint().width() ) );
|
||||
int y = ( parentWidget()->height() - sizeHint().height() ) / 2;
|
||||
|
||||
QPoint relative_pos = parentWidget()->mapToGlobal( QPoint( x, y ) );
|
||||
QWidget::move( relative_pos );
|
||||
}
|
||||
else
|
||||
qDebug() << "DepthEditor: can't get pointer to parent Widget!";
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void DepthEditor::initSpinBox( QDoubleSpinBox *&spin_box, double value )
|
||||
{
|
||||
spin_box = new QDoubleSpinBox();
|
||||
spin_box->setRange( 0, 50000 );
|
||||
spin_box->setSingleStep( 1 );
|
||||
spin_box->setDecimals( 2 );
|
||||
spin_box->setValue( value );
|
||||
spin_box->adjustSize();
|
||||
spin_box->setFixedSize( spin_box->size() );
|
||||
}
|
||||
|
||||
void DepthEditor::initCheckBox( QCheckBox *&check_box, bool value )
|
||||
{
|
||||
check_box = new QCheckBox();
|
||||
check_box->setStyleSheet( "QCheckBox::indicator{ width:20px; height: 20px; subcontrol-position: right; }" );
|
||||
check_box->setChecked( value );
|
||||
}
|
||||
|
||||
void DepthEditor::acceptAndChange()
|
||||
{
|
||||
gis_map_style_set_SEABED( safety_depth_spinbox->value(),
|
||||
shallow_contour_spinbox->value(),
|
||||
safety_contour_spinbox->value(),
|
||||
deep_contour_spinbox->value(),
|
||||
two_color_depth_chkbox->isChecked(),
|
||||
shallow_pattern_chkbox->isChecked() );
|
||||
accept();
|
||||
}
|
76
src/apps/gis-map-viewer/deptheditor.h
Обычный файл
@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 DEPTHEDITOR_H
|
||||
#define DEPTHEDITOR_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QDialog>
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QShowEvent>
|
||||
#include <QDoubleSpinBox>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
|
||||
class DepthEditor : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit DepthEditor( QWidget *parent = nullptr );
|
||||
|
||||
private:
|
||||
|
||||
QVBoxLayout *vlayout;
|
||||
QHBoxLayout *shallow_contour_lay;
|
||||
QHBoxLayout *safety_contour_lay;
|
||||
QHBoxLayout *safety_depth_lay;
|
||||
QHBoxLayout *deep_contour_lay;
|
||||
QHBoxLayout *two_color_depth_lay;
|
||||
QHBoxLayout *shallow_pattern_lay;
|
||||
QHBoxLayout *buttons_lay;
|
||||
|
||||
QDoubleSpinBox *shallow_contour_spinbox;
|
||||
QDoubleSpinBox *safety_contour_spinbox;
|
||||
QDoubleSpinBox *safety_depth_spinbox;
|
||||
QDoubleSpinBox *deep_contour_spinbox;
|
||||
|
||||
QCheckBox *two_color_depth_chkbox;
|
||||
QCheckBox *shallow_pattern_chkbox;
|
||||
|
||||
QPushButton *accept_btn;
|
||||
QPushButton *cancel_btn;
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
void initSpinBox( QDoubleSpinBox *&spin_box, double value );
|
||||
void initCheckBox( QCheckBox *&check_box, bool value );
|
||||
|
||||
private slots:
|
||||
|
||||
void acceptAndChange();
|
||||
};
|
||||
|
||||
#endif
|
247
src/apps/gis-map-viewer/distancemeter.cpp
Обычный файл
@ -0,0 +1,247 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "distancemeter.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
|
||||
DistanceMeter::DistanceMeter( gis_render_sm_context_t ext_sm_ctx, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
sm_ctx( ext_sm_ctx ),
|
||||
meter_line( nullptr ),
|
||||
contour_first_obj( nullptr ),
|
||||
firstLineDraw( true )
|
||||
{
|
||||
QGridLayout *grid_layout = new QGridLayout();
|
||||
pointList = new QListWidget();
|
||||
QLabel *dist_lbl = new QLabel( tr( "Distance (km):" ) );
|
||||
dist_edit = new QLineEdit();
|
||||
QLabel *area_lbl = new QLabel( tr( "Area (sq km):" ) );
|
||||
area_edit = new QLineEdit();
|
||||
add_btn = new QPushButton( tr( "Add ") );
|
||||
QPushButton *delete_btn = new QPushButton( tr( "Delete" ) );
|
||||
QPushButton *reset_btn = new QPushButton( tr( "Reset" ) );
|
||||
|
||||
reset_btn->setStyleSheet( "QPushButton {"
|
||||
"background-color: qradialgradient( cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, "
|
||||
"radius: 1.35, stop: 0 #FFFFFF, stop: 1 #ad2c23 );"
|
||||
"color: rgb( 0, 0, 0 );"
|
||||
"border-radius: 2px;"
|
||||
"border-width: 1px;"
|
||||
"border-style: solid;"
|
||||
"border-color: rgb( 162, 162, 162 );"
|
||||
"}"
|
||||
"QPushButton:hover {"
|
||||
"background-color: #ad463e;"
|
||||
"}"
|
||||
"QPushButton:pressed {"
|
||||
"background-color: #b37c78;"
|
||||
"}" );
|
||||
|
||||
dist_edit->setReadOnly( true );
|
||||
area_edit->setReadOnly( true );
|
||||
add_btn->setCheckable( true );
|
||||
|
||||
connect( delete_btn, SIGNAL( pressed() ), this, SLOT( slotDeletePnt() ) );
|
||||
connect( reset_btn, SIGNAL( pressed() ), this, SLOT( slotReset() ) );
|
||||
|
||||
grid_layout->addWidget( dist_lbl, 1, 1, 1, 2 );
|
||||
grid_layout->addWidget( dist_edit, 1, 3, 1, 1 );
|
||||
grid_layout->addWidget( area_lbl, 2, 1, 1, 2 );
|
||||
grid_layout->addWidget( area_edit, 2, 3, 1, 1 );
|
||||
grid_layout->addWidget( pointList, 3, 1, 3, 2 );
|
||||
grid_layout->addWidget( add_btn, 3, 3, 1, 1 );
|
||||
grid_layout->addWidget( delete_btn, 4, 3, 1, 1 );
|
||||
grid_layout->addWidget( reset_btn, 5, 3, 1, 1 );
|
||||
grid_layout->setHorizontalSpacing( 10 );
|
||||
grid_layout->setVerticalSpacing( 10 );
|
||||
|
||||
setLayout( grid_layout );
|
||||
setWindowTitle( tr( "Meter" ) );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
}
|
||||
|
||||
void DistanceMeter::createFirstPoint()
|
||||
{
|
||||
uint32_t contour_color = 0xF0FF0000;
|
||||
uint32_t contour_pen_width = 5;
|
||||
|
||||
contour_first_obj = gis_render_sm_userdata_add_contour_object( sm_ctx,
|
||||
degree_vector.data(),
|
||||
degree_vector.size(),
|
||||
contour_color,
|
||||
contour_pen_width );
|
||||
}
|
||||
|
||||
void DistanceMeter::deleteFirstPoint()
|
||||
{
|
||||
if ( contour_first_obj != nullptr )
|
||||
{
|
||||
gis_render_sm_userdata_delete_contour_object( sm_ctx, contour_first_obj );
|
||||
contour_first_obj = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DistanceMeter::slotClickPoint( double_point_t degree_pnt )
|
||||
{
|
||||
if ( add_btn->isChecked() )
|
||||
{
|
||||
degree_vector.append( degree_pnt );
|
||||
|
||||
if ( degree_vector.size() == 1 )
|
||||
{
|
||||
createFirstPoint();
|
||||
}
|
||||
|
||||
pointList->addItem( tr("lat:") + QString::number( degree_pnt.y ) +
|
||||
tr(" lon:") + QString::number( degree_pnt.x ) );
|
||||
|
||||
pointList->update();
|
||||
pointList->setMinimumWidth( pointList->sizeHintForColumn( 0 ) );
|
||||
pointList->setCurrentItem( pointList->item( pointList->count() - 1 ) );
|
||||
|
||||
if ( ( degree_vector.size() >= 2 ) )
|
||||
{
|
||||
measureDistance();
|
||||
}
|
||||
gis_render_sm_redraw_userobject( sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DistanceMeter::slotDeletePnt()
|
||||
{
|
||||
add_btn->setChecked( false );
|
||||
if ( degree_vector.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
degree_vector.remove( pointList->currentRow() );
|
||||
delete pointList->currentItem();
|
||||
pointList->update();
|
||||
setDistance( 0 );
|
||||
setArea( 0 );
|
||||
|
||||
if ( degree_vector.size() >= 2 )
|
||||
measureDistance();
|
||||
else if ( degree_vector.size() == 1 )
|
||||
{
|
||||
deleteMeterLine();
|
||||
firstLineDraw = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteFirstPoint();
|
||||
}
|
||||
|
||||
gis_render_sm_redraw_userobject( sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
void DistanceMeter::slotReset()
|
||||
{
|
||||
setDistance( 0 );
|
||||
setArea( 0 );
|
||||
pointList->clear();
|
||||
degree_vector.resize( 0 );
|
||||
add_btn->setChecked( false );
|
||||
deleteMeterLine();
|
||||
deleteFirstPoint();
|
||||
firstLineDraw = true;
|
||||
gis_render_sm_redraw_userobject( sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
void DistanceMeter::showEvent( QShowEvent *event )
|
||||
{
|
||||
emit widgetVisibilityChanged( true );
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void DistanceMeter::closeEvent( QCloseEvent *event )
|
||||
{
|
||||
slotReset();
|
||||
|
||||
emit widgetVisibilityChanged( false );
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void DistanceMeter::meterListener( QPoint pos )
|
||||
{
|
||||
double_point_t degree_pnt;
|
||||
int32_point_t px_pos = { pos.x(), pos.y() };
|
||||
gis_render_sm_convert_px2degree( sm_ctx, px_pos, °ree_pnt );
|
||||
slotClickPoint( degree_pnt );
|
||||
}
|
||||
|
||||
void DistanceMeter::measureDistance()
|
||||
{
|
||||
double distance = 0, area = 0, perimeter = 0;
|
||||
gis_render_sm_calculate_distance( sm_ctx,
|
||||
degree_vector.data(),
|
||||
degree_vector.size(),
|
||||
&distance );
|
||||
setDistance( distance );
|
||||
|
||||
gis_render_sm_calculate_polygon( sm_ctx,
|
||||
degree_vector.data(),
|
||||
degree_vector.size(),
|
||||
&area, &perimeter );
|
||||
setArea( area );
|
||||
|
||||
uint32_t color = 0xF0FF0000;
|
||||
uint32_t pen_width = 3;
|
||||
|
||||
if ( !firstLineDraw )
|
||||
{
|
||||
gis_render_sm_userdata_edit_object_points( sm_ctx,
|
||||
meter_line,
|
||||
degree_vector.data(),
|
||||
degree_vector.size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
meter_line = gis_render_sm_userdata_add_polyline( sm_ctx,
|
||||
degree_vector.data(),
|
||||
degree_vector.size(),
|
||||
color, pen_width, 1 );
|
||||
|
||||
firstLineDraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DistanceMeter::deleteMeterLine()
|
||||
{
|
||||
if ( meter_line != nullptr )
|
||||
{
|
||||
gis_render_sm_userdata_delete_object( sm_ctx, meter_line );
|
||||
meter_line = nullptr;
|
||||
}
|
||||
}
|
76
src/apps/gis-map-viewer/distancemeter.h
Обычный файл
@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 DISTANCEMETER_H
|
||||
#define DISTANCEMETER_H
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
#include <gis/gis_math.h>
|
||||
#include <gis/gis_surfacemanager.h>
|
||||
|
||||
class DistanceMeter : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DistanceMeter( gis_render_sm_context_t ext_sm_ctx, QWidget *parent = 0 );
|
||||
private:
|
||||
void closeEvent( QCloseEvent *event );
|
||||
void showEvent(QShowEvent *event);
|
||||
void setDistance( double distance ) { dist_edit->setText( QString::number( distance / 1000, 'f', 3 ) ); }
|
||||
void setArea( double area ) { area_edit->setText( QString::number( area / 1000000, 'f', 3 ) ); }
|
||||
|
||||
QVector <double_point_t> degree_vector;
|
||||
gis_render_sm_context_t sm_ctx;
|
||||
gis_userobject_t meter_line;
|
||||
gis_userobject_t contour_first_obj;
|
||||
|
||||
QLineEdit *dist_edit;
|
||||
QLineEdit *area_edit;
|
||||
QListWidget *pointList;
|
||||
|
||||
QPushButton *add_btn;
|
||||
bool firstLineDraw;
|
||||
|
||||
void createFirstPoint();
|
||||
void deleteFirstPoint();
|
||||
|
||||
public slots:
|
||||
void slotClickPoint(double_point_t );
|
||||
|
||||
private slots:
|
||||
void slotReset();
|
||||
void slotDeletePnt();
|
||||
void deleteMeterLine();
|
||||
void measureDistance();
|
||||
void meterListener( QPoint pos );
|
||||
|
||||
signals:
|
||||
void updateMapWidget();
|
||||
void widgetVisibilityChanged(bool);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
158
src/apps/gis-map-viewer/heightscale.cpp
Обычный файл
@ -0,0 +1,158 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "heightscale.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
HeightScale::HeightScale( QWidget *parent ) :
|
||||
QWidget( parent, Qt::Window ),
|
||||
maximal_height( 0 ),
|
||||
minimal_height( 0 ),
|
||||
delta( 0 )
|
||||
{
|
||||
height_scale = new QTableWidget();
|
||||
maxEdit = new QLineEdit();
|
||||
minEdit = new QLineEdit();
|
||||
|
||||
QHBoxLayout *hlay1 = new QHBoxLayout();
|
||||
QHBoxLayout *hlay2 = new QHBoxLayout();
|
||||
QVBoxLayout *vlay1 = new QVBoxLayout();
|
||||
|
||||
QLabel *min_lbl = new QLabel( tr( "Min: " ) );
|
||||
QLabel *max_lbl = new QLabel( tr( "Max: " ) );
|
||||
QPushButton *set_btn = new QPushButton( tr( "Set" ) );
|
||||
connect( set_btn, SIGNAL( released() ), this, SLOT( setHeightValues() ) );
|
||||
|
||||
height_scale->setEditTriggers( QAbstractItemView::NoEditTriggers );
|
||||
height_scale->setShowGrid( false );
|
||||
height_scale->horizontalHeader()->hide();
|
||||
height_scale->verticalHeader()->hide();
|
||||
height_scale->setColumnCount( 2 );
|
||||
height_scale->setColumnWidth( 1, 50 );
|
||||
height_scale->setFixedWidth( 120 );
|
||||
height_scale->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
|
||||
hlay1->addWidget( max_lbl );
|
||||
hlay1->addWidget( maxEdit );
|
||||
hlay2->addWidget( min_lbl );
|
||||
hlay2->addWidget( minEdit );
|
||||
vlay1->addWidget( height_scale );
|
||||
vlay1->addLayout( hlay1 );
|
||||
vlay1->addLayout( hlay2 );
|
||||
vlay1->addWidget( set_btn );
|
||||
|
||||
setLayout( vlay1 );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
}
|
||||
|
||||
void HeightScale::showEvent( QShowEvent *event )
|
||||
{
|
||||
if ( parentWidget() )
|
||||
{
|
||||
int x = 10;
|
||||
int y = ( parentWidget()->height() - sizeHint().height() / 2 ) / 2;
|
||||
|
||||
QPoint relative_pos = parentWidget()->mapToGlobal( QPoint( x, y ) );
|
||||
move( relative_pos );
|
||||
}
|
||||
else
|
||||
qDebug() << "HeightScale: can't get pointer to parent Widget!";
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void HeightScale::setHeightLimits( double min, double max )
|
||||
{
|
||||
if ( min > max )
|
||||
std::swap( min, max );
|
||||
|
||||
minEdit->setText( QString::number( min ) );
|
||||
maxEdit->setText( QString::number( max ) );
|
||||
|
||||
maximal_height = max;
|
||||
minimal_height = min;
|
||||
delta = ( maximal_height - minimal_height ) / ( colorMap.size() - 1 );
|
||||
|
||||
updateColorScale();
|
||||
}
|
||||
|
||||
void HeightScale::updateColorScale()
|
||||
{
|
||||
height_scale->clear();
|
||||
|
||||
for ( int i = 0; i < colorMap.size(); i++ )
|
||||
{
|
||||
QTableWidgetItem *value_item = new QTableWidgetItem;
|
||||
QTableWidgetItem *color_item = new QTableWidgetItem;
|
||||
value_item->setText( QString::number( minimal_height + delta * i, 'f', 1) );
|
||||
color_item->setBackground( QBrush( QColor( colorMap.at(i) ) ) );
|
||||
height_scale->setItem( colorMap.size() - i - 1, 0, value_item);
|
||||
height_scale->setItem( colorMap.size() - i - 1, 1, color_item);
|
||||
}
|
||||
}
|
||||
|
||||
void HeightScale::updateColorScale( QVector <uint32_t> extColorMap,
|
||||
double max_height,
|
||||
double min_height )
|
||||
{
|
||||
colorMap = extColorMap;
|
||||
|
||||
height_scale->setRowCount( colorMap.size() );
|
||||
|
||||
maximal_height = max_height;
|
||||
minimal_height = min_height;
|
||||
delta = ( maximal_height - minimal_height ) / colorMap.size();
|
||||
|
||||
maxEdit->setText( QString::number(maximal_height) );
|
||||
minEdit->setText( QString::number(minimal_height) );
|
||||
updateColorScale();
|
||||
|
||||
height_scale->resizeRowsToContents();
|
||||
height_scale->resizeColumnsToContents();
|
||||
height_scale->setColumnWidth( 1, 50 );
|
||||
height_scale->setMaximumWidth( 120 );
|
||||
height_scale->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
|
||||
setFixedWidth( height_scale->width() );
|
||||
}
|
||||
|
||||
void HeightScale::setHeightValues()
|
||||
{
|
||||
maximal_height = maxEdit->text().toDouble();
|
||||
minimal_height = minEdit->text().toDouble();
|
||||
|
||||
setHeightLimits( maximal_height, minimal_height );
|
||||
updateColorScale();
|
||||
|
||||
emit limitsChanged( maximal_height, minimal_height );
|
||||
}
|
63
src/apps/gis-map-viewer/heightscale.h
Обычный файл
@ -0,0 +1,63 @@
|
||||
/*
|
||||
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 HEIGHTSCALE_H
|
||||
#define HEIGHTSCALE_H
|
||||
|
||||
#include <QTableWidget>
|
||||
#include <QWidget>
|
||||
#include <QShowEvent>
|
||||
|
||||
class HeightScale : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HeightScale( QWidget *parent = 0 );
|
||||
double getMinHeight() { return minimal_height; }
|
||||
double getMaxHeight() { return maximal_height; }
|
||||
void setHeightLimits( double min, double max );
|
||||
void updateColorScale( QVector <uint32_t> colorMap, double min, double max );
|
||||
|
||||
private:
|
||||
QVector <uint32_t> colorMap;
|
||||
double minimal_height;
|
||||
double maximal_height;
|
||||
double delta;
|
||||
|
||||
QTableWidget *height_scale;
|
||||
QLineEdit *minEdit;
|
||||
QLineEdit *maxEdit;
|
||||
|
||||
void updateColorScale();
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
signals:
|
||||
void limitsChanged( double max, double min );
|
||||
void minHeight( double );
|
||||
void maxHeight( double );
|
||||
|
||||
public slots:
|
||||
void setHeightValues();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Двоичные данные
src/apps/gis-map-viewer/icons/pin.png
Обычный файл
После Ширина: | Высота: | Размер: 13 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/ruler.png
Обычный файл
После Ширина: | Высота: | Размер: 10 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/save_pin.png
Обычный файл
После Ширина: | Высота: | Размер: 13 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/shutdown.png
Обычный файл
После Ширина: | Высота: | Размер: 8.2 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/swd_logo.png
Обычный файл
После Ширина: | Высота: | Размер: 2.2 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/undo.png
Обычный файл
После Ширина: | Высота: | Размер: 8.1 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/zoomin50.png
Обычный файл
После Ширина: | Высота: | Размер: 1.0 KiB |
Двоичные данные
src/apps/gis-map-viewer/icons/zoomout50.png
Обычный файл
После Ширина: | Высота: | Размер: 1021 B |
459
src/apps/gis-map-viewer/layerwindow.cpp
Обычный файл
@ -0,0 +1,459 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "layerwindow.h"
|
||||
#include <QApplication>
|
||||
#include <algorithm>
|
||||
|
||||
#define RASTER_TABLE_ROW 0
|
||||
#define VECTOR_TABLE_ROW 1
|
||||
#define USER_TABLE_ROW 2
|
||||
|
||||
int LayerWindow::CHECKBOX_SIZE = 25;
|
||||
int LayerHeaderWithWidgets::PADDING_FOR_WIDGET = 6;
|
||||
|
||||
LayerHeaderCheckBox::LayerHeaderCheckBox( int index, const QString &text, QWidget *parent ) :
|
||||
QCheckBox( text, parent ),
|
||||
m_row( index )
|
||||
{
|
||||
QString style_sheet_str( "QCheckBox::indicator{"
|
||||
"width: px;"
|
||||
"height: px;"
|
||||
"subcontrol-position: left; }" );
|
||||
|
||||
style_sheet_str.replace( "width: ", "width: " + QString::number( LayerWindow::CHECKBOX_SIZE ) );
|
||||
style_sheet_str.replace( "height: ", "height: " + QString::number( LayerWindow::CHECKBOX_SIZE ) );
|
||||
|
||||
this->setStyleSheet( style_sheet_str );
|
||||
connect( this, SIGNAL( stateChanged( int ) ), this, SLOT( doStateChanged( int ) ) );
|
||||
}
|
||||
|
||||
void LayerHeaderWithWidgets::addSectionWidget( int section, QWidget* widget )
|
||||
{
|
||||
if ( !widget )
|
||||
return;
|
||||
|
||||
if ( section < 0 || section >= this->count() )
|
||||
return;
|
||||
|
||||
QWidget *old = m_widgets_map[section];
|
||||
delete old;
|
||||
|
||||
m_widgets_map[section] = widget;
|
||||
widget->setParent( this );
|
||||
|
||||
int header_width = this->sizeHint().width();
|
||||
int widget_width = widget->sizeHint().width();
|
||||
|
||||
|
||||
switch( this->orientation() )
|
||||
{
|
||||
case Qt::Orientation::Horizontal:
|
||||
{
|
||||
qDebug() << "LayerHeaderWithWidgets: h_header resizing is unsupported!";
|
||||
break;
|
||||
}
|
||||
case Qt::Orientation::Vertical:
|
||||
{
|
||||
if ( widget_width > header_width && widget_width > m_max_widget_width )
|
||||
{
|
||||
m_max_widget_width = widget_width;
|
||||
this->setFixedWidth( m_max_widget_width + PADDING_FOR_WIDGET );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fixWidgetPosition( section );
|
||||
}
|
||||
|
||||
QWidget *LayerHeaderWithWidgets::getSectionWidget( int section ) const
|
||||
{
|
||||
auto iter = m_widgets_map.find( section );
|
||||
|
||||
if ( iter == m_widgets_map.end() )
|
||||
return nullptr;
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
int LayerHeaderWithWidgets::getMaxWidthFromWidgets()
|
||||
{
|
||||
return m_max_widget_width;
|
||||
}
|
||||
|
||||
void LayerHeaderWithWidgets::showEvent( QShowEvent *e )
|
||||
{
|
||||
QHeaderView::showEvent( e );
|
||||
|
||||
for ( int s = 0; s < count(); ++s )
|
||||
{
|
||||
QWidget* widget = getSectionWidget( s );
|
||||
|
||||
if ( !widget )
|
||||
continue;
|
||||
|
||||
fixWidgetPosition( s );
|
||||
widget->show();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerHeaderWithWidgets::fixWidgetPosition( int section )
|
||||
{
|
||||
QWidget *widget = getSectionWidget( section );
|
||||
|
||||
if ( !widget )
|
||||
return;
|
||||
switch( this->orientation() )
|
||||
{
|
||||
case Qt::Orientation::Horizontal:
|
||||
{
|
||||
widget->setGeometry( sectionViewportPosition( section ) + PADDING_FOR_WIDGET / 2,
|
||||
0,
|
||||
sectionSize( section ) - PADDING_FOR_WIDGET, height() );
|
||||
break;
|
||||
}
|
||||
case Qt::Orientation::Vertical:
|
||||
{
|
||||
widget->setGeometry( PADDING_FOR_WIDGET / 2,
|
||||
sectionViewportPosition( section ),
|
||||
width() - 4, sectionSize( section ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LayerWindow::fillTableRow( std::vector<format_info_t> &formats, int row )
|
||||
{
|
||||
for ( uint i = 0; i < formats.size(); ++i )
|
||||
{
|
||||
QTableWidgetItem *item = new QTableWidgetItem();
|
||||
item->setText( formats.at(i).format_acronym );
|
||||
item->setTextAlignment( Qt::AlignLeft | Qt::AlignVCenter );
|
||||
item->setFlags( item->flags() | Qt::ItemIsUserCheckable );
|
||||
item->setCheckState( Qt::Unchecked );
|
||||
this->setItem( row, i, item );
|
||||
}
|
||||
}
|
||||
|
||||
void LayerWindow::fillVerticalHeader( QStringList header_text_list )
|
||||
{
|
||||
if ( !v_header )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < header_text_list.size(); ++i )
|
||||
{
|
||||
auto *v_header_box = new LayerHeaderCheckBox( i, header_text_list.at( i ) );
|
||||
|
||||
connect( v_header_box, SIGNAL( layerBoxStateChanged( int, int ) ),
|
||||
this, SLOT( slotSetNewStateAll( int, int ) ) );
|
||||
|
||||
v_header->addSectionWidget( i, v_header_box );
|
||||
}
|
||||
}
|
||||
|
||||
LayerWindow::LayerWindow( QWidget *parent ) :
|
||||
QTableWidget( parent ),
|
||||
min_width( 0 ),
|
||||
min_height( 0 )
|
||||
{
|
||||
setEditTriggers( QAbstractItemView::NoEditTriggers );
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
setSelectionMode( QAbstractItemView::NoSelection );
|
||||
|
||||
uint32_t format_iterator;
|
||||
GIS_CORE_DRIVER_FOR_LOOP_HEAD( format_iterator )
|
||||
{
|
||||
gis_core_map_data_source_t data_source = gis_helper_get_map_source_by_driver_id( (gis_core_driver_id_t)format_iterator );
|
||||
|
||||
if ( GIS_IS_CORE_MAP_DATA_SOURCE_VECTOR( data_source ) )
|
||||
{
|
||||
vector_formats.push_back( { gis_helper_get_core_data_source_name( data_source ), data_source, true } );
|
||||
}
|
||||
else
|
||||
{
|
||||
raster_formats.push_back( { gis_helper_get_core_data_source_name( data_source ), data_source, true } );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setColumnCount( std::max( vector_formats.size(), raster_formats.size() ) );
|
||||
setRowCount( GIS_RENDER_SM_SURFACE_NUMBER );
|
||||
|
||||
QString style_sheet_str( "QTableWidget::item{padding: 5px;}"
|
||||
"QAbstractItemView::indicator{"
|
||||
"width: px;"
|
||||
"height: px;"
|
||||
"subcontrol-position: left; }" );
|
||||
|
||||
style_sheet_str.replace( "width: ", "width: " + QString::number( CHECKBOX_SIZE ) );
|
||||
style_sheet_str.replace( "height: ", "height: " + QString::number( CHECKBOX_SIZE ) );
|
||||
|
||||
this->setStyleSheet( style_sheet_str );
|
||||
|
||||
|
||||
v_header = new LayerHeaderWithWidgets( Qt::Orientation::Vertical, this );
|
||||
this->setVerticalHeader( v_header );
|
||||
this->setVerticalHeaderLabels( {"", "", ""} );
|
||||
|
||||
h_header = this->horizontalHeader();
|
||||
|
||||
fillTableRow( raster_formats, RASTER_TABLE_ROW );
|
||||
fillTableRow( vector_formats, VECTOR_TABLE_ROW );
|
||||
|
||||
this->resizeColumnsToContents();
|
||||
this->resizeRowsToContents();
|
||||
|
||||
int max_col_width = 0;
|
||||
|
||||
for( int col = 0; col < this->columnCount(); ++col )
|
||||
{
|
||||
h_header->resizeSection( col, h_header->sectionSize( col ) + CHECKBOX_SIZE );
|
||||
|
||||
int section_size = h_header->sectionSize( col );
|
||||
|
||||
max_col_width = std::max( max_col_width, section_size );
|
||||
}
|
||||
|
||||
for( int col = 0; col < this->columnCount(); ++col )
|
||||
{
|
||||
min_width += max_col_width;
|
||||
setColumnWidth( col, max_col_width );
|
||||
}
|
||||
|
||||
for ( int row = 0; row < this->rowCount(); ++row )
|
||||
{
|
||||
v_header->resizeSection( row, v_header->sectionSize( row ) + CHECKBOX_SIZE );
|
||||
}
|
||||
|
||||
fillVerticalHeader( { tr( "Raster maps" ), tr( "Vector maps" ), tr( "User objects" ) } );
|
||||
|
||||
min_width += v_header->width() + 2;
|
||||
min_height += 2;
|
||||
|
||||
for ( int row = 0; row < this->rowCount(); ++row )
|
||||
{
|
||||
min_height += v_header->sectionSize( row );
|
||||
}
|
||||
|
||||
h_header->setSectionResizeMode( QHeaderView::Fixed );
|
||||
v_header->setSectionResizeMode( QHeaderView::Fixed );
|
||||
|
||||
h_header->hide();
|
||||
|
||||
this->setFixedSize( min_width, min_height );
|
||||
|
||||
connect( this, SIGNAL( itemChanged( QTableWidgetItem* ) ),
|
||||
this, SLOT( slotSetNewState( QTableWidgetItem* ) ) );
|
||||
|
||||
setWindowTitle( tr( "Surfaces and data formats" ) );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::Window |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
}
|
||||
|
||||
void LayerWindow::showEvent( QShowEvent *event )
|
||||
{
|
||||
if ( parentWidget() )
|
||||
{
|
||||
int x = ( parentWidget()->width() - width() ) / 2;
|
||||
int y = ( parentWidget()->height() - height() ) / 2;
|
||||
|
||||
QPoint relative_pos = parentWidget()->mapToGlobal( QPoint( x, y ) );
|
||||
QWidget::move( relative_pos );
|
||||
}
|
||||
else
|
||||
qDebug() << "LayerWindow: can't get pointer to parent Widget!";
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void LayerWindow::updateStates( QVector <LayerInfo> &layer_list )
|
||||
{
|
||||
if ( layer_list.size() != GIS_RENDER_SM_SURFACE_NUMBER )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < this->rowCount(); ++i )
|
||||
{
|
||||
QCheckBox *all_layers_box = qobject_cast<QCheckBox *>( v_header->getSectionWidget( i ) );
|
||||
if ( layer_list[i].layer_type == GIS_RENDER_SM_LAYER_TYPE_DISABLED )
|
||||
all_layers_box->setCheckState( Qt::Unchecked );
|
||||
else
|
||||
all_layers_box->setCheckState( Qt::Checked );
|
||||
}
|
||||
}
|
||||
|
||||
void LayerWindow::switch_all_data_sources_for_layer( int row,
|
||||
std::vector<format_info_t> &all_data_sources )
|
||||
{
|
||||
int enabled_data_sources_counter = 0, enabled_data_source_index = 0;
|
||||
{
|
||||
for ( uint i = 0; i < all_data_sources.size(); ++i )
|
||||
{
|
||||
if ( all_data_sources[i].is_enabled == true )
|
||||
{
|
||||
++enabled_data_sources_counter;
|
||||
enabled_data_source_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QCheckBox *all_layers_box = qobject_cast<QCheckBox *>( v_header->getSectionWidget( row ) );
|
||||
|
||||
if ( enabled_data_sources_counter == 1 && all_layers_box->checkState() == Qt::Checked )
|
||||
{
|
||||
item( row, enabled_data_source_index )->setCheckState( Qt::Checked );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( uint i = 0; i < all_data_sources.size(); ++i )
|
||||
{
|
||||
item( row, i )->setCheckState( all_layers_box->checkState() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LayerWindow::set_data_sources_for_layer( std::vector<format_info_t> &all_data_sources,
|
||||
gis_render_sm_layer_type_t layer_type,
|
||||
QTableWidgetItem *table_item )
|
||||
{
|
||||
int row_idx = ( layer_type == GIS_RENDER_SM_LAYER_TYPE_MTW ) ?
|
||||
RASTER_TABLE_ROW :
|
||||
VECTOR_TABLE_ROW;
|
||||
|
||||
{
|
||||
uint counter = 0;
|
||||
for ( uint i = 0; i < all_data_sources.size(); ++i )
|
||||
{
|
||||
if ( all_data_sources[i].is_enabled == false )
|
||||
++counter;
|
||||
}
|
||||
|
||||
QCheckBox *all_layers_box = qobject_cast<QCheckBox *>( v_header->getSectionWidget( row_idx ) );
|
||||
|
||||
if ( counter == all_data_sources.size() &&
|
||||
all_layers_box->checkState() == Qt::Unchecked )
|
||||
{
|
||||
all_data_sources[table_item->column()].is_enabled = true;
|
||||
all_layers_box->setCheckState( Qt::Checked );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for ( uint i = 0; i < all_data_sources.size(); ++i )
|
||||
{
|
||||
if ( item( row_idx, i )->checkState() == Qt::Checked )
|
||||
{
|
||||
picked_data_sources.push_back( all_data_sources[i].format_data_source );
|
||||
all_data_sources[i].is_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
for ( uint i = 0; i < all_data_sources.size(); ++i )
|
||||
{
|
||||
bool match = false;
|
||||
for ( uint j = 0; j < picked_data_sources.size(); ++j )
|
||||
{
|
||||
if ( all_data_sources[i].format_data_source == picked_data_sources[j] )
|
||||
match = true;
|
||||
}
|
||||
|
||||
if ( match )
|
||||
all_data_sources[i].is_enabled = true;
|
||||
else
|
||||
all_data_sources[i].is_enabled = false;
|
||||
}
|
||||
|
||||
if ( picked_data_sources.size() == 0 )
|
||||
{
|
||||
QCheckBox *all_layers_box = qobject_cast<QCheckBox *>( v_header->getSectionWidget( table_item->row() ) );
|
||||
all_layers_box->setCheckState( Qt::Unchecked );
|
||||
}
|
||||
}
|
||||
|
||||
void LayerWindow::slotSetNewStateAll( int row, int state )
|
||||
{
|
||||
switch ( row )
|
||||
{
|
||||
case RASTER_TABLE_ROW:
|
||||
if ( state == Qt::Unchecked )
|
||||
emit setLayer( 0, GIS_RENDER_SM_LAYER_TYPE_DISABLED );
|
||||
else
|
||||
emit setLayer( 0, GIS_RENDER_SM_LAYER_TYPE_MTW );
|
||||
|
||||
switch_all_data_sources_for_layer( RASTER_TABLE_ROW, raster_formats );
|
||||
break;
|
||||
|
||||
case VECTOR_TABLE_ROW:
|
||||
if ( state == Qt::Unchecked )
|
||||
emit setLayer( 1, GIS_RENDER_SM_LAYER_TYPE_DISABLED );
|
||||
else
|
||||
emit setLayer( 1, GIS_RENDER_SM_LAYER_TYPE_2DMAP );
|
||||
|
||||
switch_all_data_sources_for_layer( VECTOR_TABLE_ROW, vector_formats );
|
||||
break;
|
||||
|
||||
case USER_TABLE_ROW:
|
||||
if ( state == Qt::Unchecked )
|
||||
emit setLayer( 2, GIS_RENDER_SM_LAYER_TYPE_DISABLED );
|
||||
else
|
||||
emit setLayer( 2, GIS_RENDER_SM_LAYER_TYPE_USROBJ );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LayerWindow::slotSetNewState( QTableWidgetItem *table_cell_item )
|
||||
{
|
||||
picked_data_sources.clear();
|
||||
|
||||
switch ( table_cell_item->row() )
|
||||
{
|
||||
case RASTER_TABLE_ROW:
|
||||
set_data_sources_for_layer( raster_formats,
|
||||
GIS_RENDER_SM_LAYER_TYPE_MTW,
|
||||
table_cell_item );
|
||||
emit setDataSourcesForLayer( GIS_RENDER_SM_LAYER_TYPE_MTW,
|
||||
picked_data_sources.size(),
|
||||
&picked_data_sources[0] );
|
||||
break;
|
||||
|
||||
case VECTOR_TABLE_ROW:
|
||||
set_data_sources_for_layer( vector_formats,
|
||||
GIS_RENDER_SM_LAYER_TYPE_2DMAP,
|
||||
table_cell_item );
|
||||
emit setDataSourcesForLayer( GIS_RENDER_SM_LAYER_TYPE_2DMAP,
|
||||
picked_data_sources.size(),
|
||||
&picked_data_sources[0] );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
144
src/apps/gis-map-viewer/layerwindow.h
Обычный файл
@ -0,0 +1,144 @@
|
||||
/*
|
||||
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 LAYERWINDOW_H
|
||||
#define LAYERWINDOW_H
|
||||
|
||||
#include <QTableWidget>
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QString>
|
||||
#include <QCheckBox>
|
||||
#include <QHeaderView>
|
||||
#include <QShowEvent>
|
||||
|
||||
#include <gis/gis_surfacemanager.h>
|
||||
|
||||
struct format_info_t
|
||||
{
|
||||
QString format_acronym;
|
||||
gis_core_map_data_source_t format_data_source;
|
||||
bool is_enabled;
|
||||
};
|
||||
|
||||
class LayerHeaderCheckBox : public QCheckBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LayerHeaderCheckBox( int index, const QString &text, QWidget *parent = nullptr );
|
||||
|
||||
signals:
|
||||
void layerBoxStateChanged( int row, int state );
|
||||
|
||||
private slots:
|
||||
void doStateChanged( int state )
|
||||
{
|
||||
emit layerBoxStateChanged( m_row, state );
|
||||
}
|
||||
|
||||
private:
|
||||
int m_row;
|
||||
};
|
||||
|
||||
|
||||
class LayerHeaderWithWidgets : public QHeaderView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LayerHeaderWithWidgets( Qt::Orientation orientation, QWidget *parent = nullptr ) :
|
||||
QHeaderView( orientation, parent ),
|
||||
m_max_widget_width( 0 )
|
||||
{}
|
||||
|
||||
virtual ~LayerHeaderWithWidgets()
|
||||
{
|
||||
m_widgets_map.clear();
|
||||
}
|
||||
|
||||
void addSectionWidget( int section, QWidget* widget );
|
||||
|
||||
QWidget *getSectionWidget( int section ) const;
|
||||
|
||||
protected:
|
||||
void showEvent( QShowEvent *e );
|
||||
|
||||
int getMaxWidthFromWidgets();
|
||||
void fixWidgetPosition( int section );
|
||||
|
||||
private:
|
||||
static int PADDING_FOR_WIDGET;
|
||||
|
||||
std::map<int, QWidget*> m_widgets_map;
|
||||
int m_max_widget_width;
|
||||
};
|
||||
|
||||
|
||||
class LayerWindow : public QTableWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
friend LayerHeaderCheckBox;
|
||||
friend LayerHeaderWithWidgets;
|
||||
|
||||
explicit LayerWindow( QWidget *parent = 0 );
|
||||
|
||||
private:
|
||||
void fillTableRow( std::vector<format_info_t> &formats, int row );
|
||||
|
||||
void fillVerticalHeader( QStringList header_text_list );
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
void switch_all_data_sources_for_layer( int row, std::vector<format_info_t> &all_data_sources );
|
||||
void set_data_sources_for_layer( std::vector<format_info_t> &all_data_sources,
|
||||
gis_render_sm_layer_type_t layer_type,
|
||||
QTableWidgetItem *table_item );
|
||||
|
||||
QHeaderView *h_header;
|
||||
LayerHeaderWithWidgets *v_header;
|
||||
|
||||
int min_width;
|
||||
int min_height;
|
||||
|
||||
static int CHECKBOX_SIZE;
|
||||
|
||||
std::vector<format_info_t> vector_formats;
|
||||
std::vector<format_info_t> raster_formats;
|
||||
|
||||
std::vector<gis_core_map_data_source_t> picked_data_sources;
|
||||
|
||||
public slots:
|
||||
void updateStates( QVector<LayerInfo> &layer_list );
|
||||
|
||||
private slots:
|
||||
void slotSetNewState( QTableWidgetItem *it );
|
||||
void slotSetNewStateAll( int row, int state );
|
||||
|
||||
signals:
|
||||
void changeLayerName();
|
||||
void changeLayerState();
|
||||
void setLayer( int, gis_render_sm_layer_type_t );
|
||||
void setDataSourcesForLayer( gis_render_sm_layer_type_t, int, gis_core_map_data_source_t* );
|
||||
};
|
||||
|
||||
#endif
|
178
src/apps/gis-map-viewer/main.cpp
Обычный файл
@ -0,0 +1,178 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
#include <QTranslator>
|
||||
#include <QFontDatabase>
|
||||
#include <QDirIterator>
|
||||
|
||||
#include <gis/gis_types.h>
|
||||
|
||||
#define MAP_VIEWER_PREFIX ("[gis-map-viewer] ")
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gis_core_driver_id_t enabledDriverId = GIS_CORE_DRIVERS_ALL;
|
||||
|
||||
gis_helper_debug_mode_setmask( GIS_DEBUG_MODE_STD | GIS_DEBUG_MODE_FD );
|
||||
gis_helper_debug_file_setname( "gis-map-viewer.log" );
|
||||
|
||||
QString gis_config( gis_helper_env_get_config_directory() );
|
||||
QSettings settings( gis_config + "gis-map-viewer.conf", QSettings::IniFormat );
|
||||
|
||||
bool oneMapMode = settings.value( "MainWindow/oneMapMode" ).toBool();
|
||||
settings.beginGroup( "MapWidget" );
|
||||
|
||||
if ( oneMapMode )
|
||||
{
|
||||
QStringList old_map_widgets = settings.childGroups();
|
||||
|
||||
for( auto child : old_map_widgets )
|
||||
{
|
||||
settings.remove( child );
|
||||
}
|
||||
}
|
||||
|
||||
int index = settings.childGroups().size();
|
||||
settings.endGroup();
|
||||
|
||||
bool new_map_tab_added = false;
|
||||
|
||||
int opt = 0;
|
||||
extern char *optarg;
|
||||
|
||||
while ( (opt = getopt( argc, argv,"X::Y::w::h::x::y::s::D::ti::" ) ) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'X':
|
||||
settings.setValue( "MainWindow/window_x", atoi( optarg ) );
|
||||
break;
|
||||
case 'Y':
|
||||
settings.setValue( "MainWindow/window_y", atoi( optarg ) );
|
||||
break;
|
||||
case 'w':
|
||||
settings.setValue( "MainWindow/width", atoi( optarg ) );
|
||||
break;
|
||||
case 'h':
|
||||
settings.setValue( "MainWindow/height", atoi( optarg ) );
|
||||
break;
|
||||
case 'x':
|
||||
settings.beginGroup( "MapWidget" );
|
||||
settings.beginGroup( QString::number( index ) );
|
||||
settings.setValue( "longitude", std::strtod( optarg, NULL ) );
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
new_map_tab_added = true;
|
||||
break;
|
||||
case 'y':
|
||||
settings.beginGroup( "MapWidget" );
|
||||
settings.beginGroup( QString::number( index ) );
|
||||
settings.setValue( "latitude", std::strtod( optarg, NULL ) );
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
new_map_tab_added = true;
|
||||
break;
|
||||
case 's':
|
||||
settings.beginGroup( "MapWidget" );
|
||||
settings.beginGroup( QString::number( index ) );
|
||||
settings.setValue( "scaleVectorIndex", atoi( optarg ) );
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
new_map_tab_added = true;
|
||||
break;
|
||||
case 'D':
|
||||
{
|
||||
int option_driver_enable = atoi( optarg );
|
||||
if ( GIS_CORE_DRIVER_ID_CHECK(option_driver_enable) )
|
||||
{
|
||||
enabledDriverId = (gis_core_driver_id_t)option_driver_enable;
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_INFO, MAP_VIEWER_PREFIX,
|
||||
"Current driver id %d is only enabled [%s()]", option_driver_enable, __FUNCTION__ );
|
||||
}
|
||||
else
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_WARNING, MAP_VIEWER_PREFIX,
|
||||
"Invalid driver id %d, all drivers enabled by default [%s()]",
|
||||
option_driver_enable, __FUNCTION__ );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
settings.setValue( "SurfaceManager/allocInRam", true );
|
||||
break;
|
||||
case 'i':
|
||||
settings.setValue( "MainWindow/sharedMemoryUserId", atoi( optarg ) );
|
||||
break;
|
||||
case '?':
|
||||
printf( "Error: unknown option\n" );
|
||||
exit( 1 );
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if ( new_map_tab_added )
|
||||
{
|
||||
settings.setValue( "MainWindow/lastOpenedTabIndex", index );
|
||||
}
|
||||
|
||||
CleanExit cleanExit;
|
||||
|
||||
QApplication a( argc, argv );
|
||||
|
||||
const char *lang = getenv( "ABLANG" );
|
||||
QString locale = "en_EN";
|
||||
|
||||
if ( lang )
|
||||
{
|
||||
locale = QString( lang );
|
||||
}
|
||||
|
||||
QTranslator myTranslator;
|
||||
myTranslator.load( ":/translations/gis-map-viewer_" + locale );
|
||||
a.installTranslator( &myTranslator );
|
||||
|
||||
MainWindow w;
|
||||
|
||||
if ( w.connectGisCore( enabledDriverId ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_WARNING, MAP_VIEWER_PREFIX,
|
||||
"Conection to gis-core failed. Retry... [%s()]", __FUNCTION__ );
|
||||
|
||||
if ( w.connectGisCore( enabledDriverId ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, MAP_VIEWER_PREFIX,
|
||||
"Conection failed. Exiting... [%s()]", __FUNCTION__ );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
w.createMapWidgets();
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
532
src/apps/gis-map-viewer/mainwindow.cpp
Обычный файл
@ -0,0 +1,532 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QGridLayout>
|
||||
|
||||
MainWindow::MainWindow( QWidget *parent ) :
|
||||
QMainWindow(parent)
|
||||
{
|
||||
loadSettings();
|
||||
|
||||
setGeometry( windowX, windowY, widthPx, heightPx );
|
||||
|
||||
tab_wgt = new MapTabWidget( this );
|
||||
connect( tab_wgt, SIGNAL( firstTabAdded( int ) ), this, SLOT( processTabChanging( int ) ) );
|
||||
tab_wgt->setDocumentMode( true );
|
||||
|
||||
setCentralWidget( tab_wgt );
|
||||
|
||||
layer_window = new LayerWindow( this );
|
||||
connect( layer_window, SIGNAL( setLayer( int,gis_render_sm_layer_type_t ) ),
|
||||
tab_wgt, SLOT( updateLayerOrder( int,gis_render_sm_layer_type_t ) ) );
|
||||
connect( layer_window, SIGNAL( setDataSourcesForLayer( gis_render_sm_layer_type_t, int, gis_core_map_data_source_t* ) ),
|
||||
tab_wgt, SLOT( updateDataSourcesForLayer( gis_render_sm_layer_type_t, int, gis_core_map_data_source_t* ) ) );
|
||||
|
||||
mapstyle_layer_window = new MapStyleLayerWindow( this );
|
||||
connect( mapstyle_layer_window, SIGNAL( updateMapWidget() ),
|
||||
tab_wgt, SLOT( syncCurrentTab() ) );
|
||||
|
||||
view_params = new ViewParameters( this );
|
||||
connect( view_params, SIGNAL( signalNewBrightnessContrastValues( float, float ) ),
|
||||
tab_wgt, SLOT( updateBrightnessContrast( float, float ) ) );
|
||||
|
||||
height_scale = new HeightScale( this );
|
||||
connect( height_scale, SIGNAL( limitsChanged( double, double ) ),
|
||||
this, SLOT( setManualHeightLimits( double, double ) ) );
|
||||
|
||||
object_search = new ObjectSearch( this );
|
||||
|
||||
setMaximumSize( 1910, 1053 * 2 + menuBar()->height() - 1 - 3 );
|
||||
|
||||
fillMenuBar();
|
||||
|
||||
setWindowTitle( tr( "Map Viewer" ) );
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
saveSettings();
|
||||
|
||||
gis_core_databuffer_detach();
|
||||
gis_core_link_destroy( &connection, true );
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent( QCloseEvent *event )
|
||||
{
|
||||
tab_wgt->close();
|
||||
layer_window->close();
|
||||
mapstyle_layer_window->close();
|
||||
view_params->close();
|
||||
height_scale->close();
|
||||
object_search->close();
|
||||
depth_editor->close();
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void MainWindow::loadSettings()
|
||||
{
|
||||
QString config_dir( gis_helper_env_get_config_directory() );
|
||||
QSettings settings( config_dir + "gis-map-viewer.conf", QSettings::IniFormat );
|
||||
|
||||
windowX = settings.value( "MainWindow/window_x" ).toInt();
|
||||
windowY = settings.value( "MainWindow/window_y" ).toInt();
|
||||
|
||||
windowX = windowX < 0 ? 0 : windowX;
|
||||
windowY = windowY < 0 ? 0 : windowY;
|
||||
|
||||
widthPx = settings.value( "MainWindow/width" ).toInt();
|
||||
heightPx = settings.value( "MainWindow/height" ).toInt();
|
||||
|
||||
lastOpenedTabIndex = settings.value( "MainWindow/lastOpenedTabIndex" ).toInt();
|
||||
oneMapMode = settings.value( "MainWindow/oneMapMode" ).toBool();
|
||||
|
||||
sharedMemoryUserId = settings.value( "MainWindow/sharedMemoryUserId" ).toInt();
|
||||
|
||||
settings.beginGroup( "MapWidget" );
|
||||
nTabs = settings.childGroups().size();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
QString config_dir( gis_helper_env_get_config_directory() );
|
||||
QSettings settings( config_dir + "gis-map-viewer.conf", QSettings::IniFormat);
|
||||
|
||||
settings.setValue( "MainWindow/window_x", x() );
|
||||
settings.setValue( "MainWindow/window_y", y() );
|
||||
settings.setValue( "MainWindow/width", width() );
|
||||
settings.setValue( "MainWindow/height", height() );
|
||||
|
||||
settings.setValue( "MainWindow/oneMapMode", oneMapMode );
|
||||
settings.setValue( "MainWindow/lastOpenedTabIndex", lastOpenedTabIndex );
|
||||
|
||||
settings.beginGroup( "MapWidget" );
|
||||
QStringList old_map_widgets = settings.childGroups();
|
||||
|
||||
for( auto child : old_map_widgets )
|
||||
{
|
||||
settings.remove( child );
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void MainWindow::fillMenuBar()
|
||||
{
|
||||
QMenu *menuMain = new QMenu( tr( "Main" ), this );
|
||||
QAction *oneMapAction = menuMain->addAction( tr( "Show only one map" ), this, SLOT( flipOneMapMode() ) );
|
||||
oneMapAction->setCheckable( true );
|
||||
if( oneMapMode )
|
||||
oneMapAction->setChecked( true );
|
||||
|
||||
menuMain->addSeparator();
|
||||
menuMain->addAction( tr( "About" ), this, SLOT( showAboutDialog() ) );
|
||||
menuMain->addAction( tr( "Exit" ), QApplication::instance(), SLOT( quit() ),
|
||||
QKeySequence( Qt::CTRL | Qt::Key_Q ) );
|
||||
|
||||
QMenu *menuView = new QMenu( tr( "View parameters" ), this );
|
||||
menuView->addAction( tr( "Projections" ), tab_wgt, SLOT( showProjectionDialog() ) );
|
||||
menuView->addAction( tr( "Screen parameters" ), tab_wgt, SLOT( showScreenParametersDialog() ) );
|
||||
menuView->addAction( tr( "Layers" ), layer_window, SLOT( show() ) );
|
||||
menuView->addSeparator();
|
||||
menuView->addAction( tr( "Brighntess / Contrast" ), view_params, SLOT( show() ) );
|
||||
|
||||
scaling_action = new QAction( tr( "New scaling mode" ), this );
|
||||
scaling_action->setCheckable( true );
|
||||
connect( scaling_action, SIGNAL( triggered( bool ) ),
|
||||
tab_wgt, SLOT( setConstScalingMode( bool )) );
|
||||
|
||||
menuView->addAction( scaling_action );
|
||||
menuView->addSeparator();
|
||||
|
||||
aliasing_action = new QAction( tr( "Aliasing" ), this );
|
||||
aliasing_action->setCheckable( true );
|
||||
connect( aliasing_action, SIGNAL( triggered( bool ) ),
|
||||
tab_wgt, SLOT( setAliasingMode( bool )) );
|
||||
|
||||
menuView->addAction( aliasing_action );
|
||||
menuView->addSeparator();
|
||||
|
||||
center_scaling_action = new QAction( tr( "Center at cursor" ), this );
|
||||
center_scaling_action->setCheckable( true );
|
||||
connect( center_scaling_action, SIGNAL( triggered( bool ) ),
|
||||
tab_wgt, SLOT( setCenterAtCursor( bool ) ) );
|
||||
|
||||
menuView->addAction( center_scaling_action );
|
||||
menuView->addSeparator();
|
||||
|
||||
rescale_by_wheel_action = new QAction( tr( "Scale by scroll" ), this );
|
||||
rescale_by_wheel_action->setCheckable( true );
|
||||
rescale_by_wheel_action->setChecked( true );
|
||||
connect( rescale_by_wheel_action, SIGNAL( triggered( bool ) ),
|
||||
tab_wgt, SLOT( setRescaleByWheel( bool ) ) );
|
||||
|
||||
menuView->addAction( rescale_by_wheel_action );
|
||||
menuView->addSeparator();
|
||||
|
||||
QMenu *menuVector = new QMenu( tr( "Vector" ), this );
|
||||
|
||||
menuPalette = new QMenu( tr( "Palette" ), this );
|
||||
menuLanguage = new QMenu( tr( "Language" ), this );
|
||||
menuFormatFeatures = new QMenu( tr( "Format features" ), this );
|
||||
|
||||
menuVector->addMenu( menuPalette );
|
||||
menuVector->addMenu( menuLanguage );
|
||||
menuVector->addMenu( menuFormatFeatures );
|
||||
|
||||
menuView->addMenu( menuVector );
|
||||
menuView->addSeparator();
|
||||
|
||||
QMenu *menuRaster = new QMenu( tr("Raster"), this );
|
||||
menuRaster->addAction( tr("Raster scale"), height_scale, SLOT( show() ) );
|
||||
|
||||
auto_height_action = new QAction( tr( "Auto height mode" ), this );
|
||||
auto_height_action->setCheckable( true );
|
||||
connect( auto_height_action, SIGNAL( triggered( bool ) ),
|
||||
this, SLOT( autoHeightChecked( bool ) ) );
|
||||
|
||||
menuRaster->addAction( auto_height_action );
|
||||
|
||||
invalid_height_action = new QAction( tr( "Show out of limits height" ), this );
|
||||
invalid_height_action->setCheckable( true );
|
||||
connect( invalid_height_action, SIGNAL( triggered( bool ) ),
|
||||
tab_wgt, SLOT( setRasterInvalidHeightMode( bool ) ) );
|
||||
|
||||
menuRaster->addAction( invalid_height_action );
|
||||
|
||||
palette_action = new QAction( tr( "Discrete palette" ), this );
|
||||
palette_action->setCheckable( true );
|
||||
connect( palette_action, SIGNAL( triggered( bool ) ),
|
||||
tab_wgt, SLOT( setDiscretePaletteEnabled( bool ) ) );
|
||||
|
||||
menuRaster->addAction( palette_action );
|
||||
|
||||
menuView->addMenu( menuRaster );
|
||||
menuView->addSeparator();
|
||||
|
||||
QMenu *menuTools = new QMenu( tr( "Tools" ), this );
|
||||
menuTools->addAction( tr( "Refresh" ), this, SLOT( refreshMapData() ), QKeySequence( Qt::Key_F5 ) );
|
||||
menuTools->addSeparator();
|
||||
menuTools->addAction( tr( "User objects" ), tab_wgt, SLOT( showUserForm() ) );
|
||||
menuTools->addAction( tr( "Map ruler" ), tab_wgt, SLOT( showMeter() ) );
|
||||
|
||||
QMenu *menuFilter = new QMenu( tr( "Filters" ), this );
|
||||
menuFilter->addAction( tr( "Map style layers" ), mapstyle_layer_window, SLOT( show()) );
|
||||
menuFilter->addAction( tr( "Type of primitive" ) )->setVisible( false );
|
||||
menuFilter->addAction( tr( "Map type" ) )->setVisible( false );
|
||||
|
||||
menuTools->addMenu( menuFilter );
|
||||
menuTools->addAction( tr( "Search" ), object_search, SLOT( show() ) );
|
||||
|
||||
menuBar()->addMenu( menuMain );
|
||||
menuBar()->addMenu( menuView );
|
||||
menuBar()->addMenu( menuTools );
|
||||
}
|
||||
|
||||
void MainWindow::flipOneMapMode()
|
||||
{
|
||||
oneMapMode = !oneMapMode;
|
||||
|
||||
int current = lastOpenedTabIndex;
|
||||
|
||||
for ( int i = 0; i >= 0 && i < tab_wgt->count(); i++ )
|
||||
{
|
||||
MapWidget *map_widget = qobject_cast<MapWidget *>( tab_wgt->widget( i ) );
|
||||
|
||||
if ( map_widget->getIndex() == current )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tab_wgt->removeTab( i );
|
||||
map_widget->close();
|
||||
|
||||
i--;
|
||||
}
|
||||
|
||||
tab_wgt->currentMapWidget()->setIndex( 0 );
|
||||
}
|
||||
|
||||
void MainWindow::createMapWidgets()
|
||||
{
|
||||
int current_from_cfg = lastOpenedTabIndex;
|
||||
|
||||
for ( int i = 0; i < nTabs; i++ )
|
||||
{
|
||||
tab_wgt->addMapWidget( &connection );
|
||||
}
|
||||
|
||||
connect( tab_wgt, SIGNAL( currentChanged( int ) ),
|
||||
this, SLOT( processTabChanging( int ) ) );
|
||||
|
||||
tab_wgt->setCurrentIndex( current_from_cfg );
|
||||
}
|
||||
|
||||
int MainWindow::connectGisCore( gis_core_driver_id_t enabledDriverId )
|
||||
{
|
||||
gis_core_link_init( &connection );
|
||||
|
||||
gis_core_request_parameters_t map;
|
||||
gis_core_request_parameters_init( &map );
|
||||
|
||||
if ( enabledDriverId != GIS_CORE_DRIVERS_ALL )
|
||||
{
|
||||
gis_core_request_parameters_set_driver( &map, enabledDriverId );
|
||||
}
|
||||
|
||||
sharedMemoryUserId += 100;
|
||||
qDebug() << QTime::currentTime().toString() << " SHID: " << sharedMemoryUserId;
|
||||
|
||||
int result = gis_core_link_connect( &connection, sharedMemoryUserId );
|
||||
|
||||
if ( result != EOK && result != EALREADY )
|
||||
{
|
||||
qDebug() << QTime::currentTime().toString() << " GIS Core connection failed";
|
||||
return result;
|
||||
}
|
||||
|
||||
result = gis_core_databuffer_attach( &connection );
|
||||
|
||||
if ( result != EOK && result != EALREADY )
|
||||
{
|
||||
qDebug() << QTime::currentTime().toString() << " GIS Core draw buffer attach failed";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if ( (result = gis_core_databuffer_data_request( &connection, &map, 1 ) ) != EOK )
|
||||
{
|
||||
if ( result != EOVERFLOW )
|
||||
{
|
||||
qDebug() << QTime::currentTime().toString() << " GIS Core map draw request failed";
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << QTime::currentTime().toString() << " GIS Core map draw request EOVERFLOW";
|
||||
}
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
void MainWindow::refreshMapData()
|
||||
{
|
||||
gis_core_request_update_cache( &connection, GIS_CORE_DRIVERS_ALL, GIS_CORE_UPDATE_CACHE_MODE_SOFT_UPDATE );
|
||||
|
||||
gis_core_request_parameters_t map;
|
||||
gis_core_request_parameters_init( &map );
|
||||
|
||||
gis_core_databuffer_data_request( &connection, &map, 1 );
|
||||
|
||||
emit updateAllDataEngines();
|
||||
}
|
||||
|
||||
void MainWindow::flipLocale()
|
||||
{
|
||||
QAction *action = qobject_cast<QAction *>( sender() );
|
||||
|
||||
gis_map_style_flip_language( static_cast<gis_map_style_t>( action->data().toInt() ) );
|
||||
|
||||
tab_wgt->updateCurrentTabMap();
|
||||
}
|
||||
|
||||
void MainWindow::changePalette()
|
||||
{
|
||||
QAction *action = qobject_cast<QAction *>( sender() );
|
||||
|
||||
QMenu *menu = qobject_cast<QMenu *>( action->parent() );
|
||||
|
||||
auto pair = palettes_map.find( menu->title() );
|
||||
|
||||
if ( pair != palettes_map.end() )
|
||||
{
|
||||
gis_vector_palette_list_t *palettes = pair->second;
|
||||
|
||||
gis_map_style_set_active_palette_idx( palettes, action->data().toInt() );
|
||||
|
||||
tab_wgt->updateCurrentTabMap();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateMapStyles( std::vector<ClassifierInfo> &classifier_list )
|
||||
{
|
||||
map_style_vector.clear();
|
||||
|
||||
for ( auto classifier : classifier_list )
|
||||
{
|
||||
gis_core_map_data_source_t map_data_source = classifier.layers.at( 0 ).classes.at( 0 ).class_data.src;
|
||||
|
||||
gis_map_style_t map_style = gis_helper_get_map_style_by_data_source( map_data_source );
|
||||
|
||||
if ( std::find( map_style_vector.begin(), map_style_vector.end(), map_style ) == map_style_vector.end() )
|
||||
{
|
||||
map_style_vector.push_back( map_style );
|
||||
}
|
||||
}
|
||||
|
||||
updatePaletteMenu( map_style_vector );
|
||||
updateLanguageMenu( map_style_vector );
|
||||
updateFormatFeaturesMenu( map_style_vector );
|
||||
}
|
||||
|
||||
void MainWindow::updateFormatFeaturesMenu( std::vector<gis_map_style_t> &mapstyle_list )
|
||||
{
|
||||
menuFormatFeatures->clear();
|
||||
|
||||
for ( auto map_style : mapstyle_list )
|
||||
{
|
||||
const QString &submenu_name = QString::fromLatin1( gis_helper_get_map_style_name( map_style ) );
|
||||
|
||||
QMenu *submenu = menuFormatFeatures->addMenu( submenu_name );
|
||||
|
||||
if ( map_style == GIS_MAP_STYLE_S52 )
|
||||
{
|
||||
depth_editor = new DepthEditor( this );
|
||||
connect( depth_editor, SIGNAL( accepted() ), tab_wgt, SLOT( updateCurrentTabMap() ) );
|
||||
submenu->addAction( tr( "Depth editor" ), depth_editor, SLOT( show() ) );
|
||||
}
|
||||
}
|
||||
menuFormatFeatures->update();
|
||||
}
|
||||
|
||||
void MainWindow::updateLanguageMenu( std::vector<gis_map_style_t> &mapstyle_list )
|
||||
{
|
||||
menuLanguage->clear();
|
||||
|
||||
for ( auto map_style : mapstyle_list )
|
||||
{
|
||||
const QString &submenu_name = QString::fromLatin1( gis_helper_get_map_style_name( map_style ) );
|
||||
|
||||
QMenu *submenu = menuLanguage->addMenu( submenu_name );
|
||||
|
||||
if ( map_style == GIS_MAP_STYLE_S52 )
|
||||
{
|
||||
QAction *action = submenu->addAction( tr( "National language" ), this, SLOT( flipLocale() ) );
|
||||
action->setCheckable( true );
|
||||
action->setData( map_style );
|
||||
}
|
||||
}
|
||||
menuLanguage->update();
|
||||
}
|
||||
|
||||
void MainWindow::updatePaletteMenu( std::vector<gis_map_style_t> &mapstyle_list )
|
||||
{
|
||||
if ( mapstyle_list.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( menuPalette == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( auto pair : palettes_map )
|
||||
{
|
||||
gis_map_style_palette_list_free( &pair.second );
|
||||
}
|
||||
|
||||
menuPalette->clear();
|
||||
|
||||
palettes_map.clear();
|
||||
|
||||
for ( auto map_style : mapstyle_list )
|
||||
{
|
||||
const QString &submenu_name = QString::fromLatin1( gis_helper_get_map_style_name( map_style ) );
|
||||
|
||||
QMenu *submenu = menuPalette->addMenu( submenu_name );
|
||||
|
||||
gis_vector_palette_list_t *palettes = gis_map_style_get_palette_list( map_style );
|
||||
|
||||
if ( palettes == NULL )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
palettes_map.emplace( submenu_name, palettes );
|
||||
|
||||
for ( unsigned int i = 0; i < gis_map_style_palette_get_entry_count( palettes ); i++ )
|
||||
{
|
||||
const QString &submenu_action_name =
|
||||
QString::fromLatin1( gis_map_style_palette_get_entry_list( palettes )[i].name );
|
||||
|
||||
QAction *action = submenu->addAction( submenu_action_name, this, SLOT( changePalette() ) );
|
||||
action->setData( i );
|
||||
}
|
||||
}
|
||||
menuPalette->update();
|
||||
}
|
||||
|
||||
void MainWindow::processTabChanging( int idx )
|
||||
{
|
||||
if ( idx < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( tab_wgt->checkLock( idx ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lastOpenedTabIndex = idx;
|
||||
|
||||
MapWidget *mw = tab_wgt->currentMapWidget();
|
||||
aliasing_action->setChecked( mw->isAliasingEnabled );
|
||||
scaling_action->setChecked( mw->isConstScalingEnabled );
|
||||
center_scaling_action->setChecked( mw->centerOnScaling );
|
||||
rescale_by_wheel_action->setChecked( mw->rescaleByWheel );
|
||||
auto_height_action->setChecked( mw->autoRasterHeightLimits );
|
||||
palette_action->setChecked( mw->rasterDiscretePalette );
|
||||
invalid_height_action->setChecked( mw->rasterInvalidHeightMode );
|
||||
|
||||
layer_window->updateStates( mw->layer_list );
|
||||
height_scale->updateColorScale( mw->colorMap, mw->maxRasterHeight, mw->minRasterHeight );
|
||||
view_params->updateBrightnessContrast( mw->brightness, mw->contrast );
|
||||
mapstyle_layer_window->updateLists( mw->classifiers );
|
||||
object_search->updateLists( mw->classifiers );
|
||||
|
||||
if ( object_search->getCurrentTab() != NULL )
|
||||
{
|
||||
disconnect( object_search, SIGNAL( centerAtObject( double_point_t ) ),
|
||||
object_search->getCurrentTab(), SLOT( setMapWidgetCenterAtPoint( double_point_t ) ) );
|
||||
|
||||
disconnect( object_search, SIGNAL( showInfoForFoundObject( gis_object_t ) ),
|
||||
object_search->getCurrentTab(), SLOT( showObjectInfoWindow( gis_object_t ) ) );
|
||||
}
|
||||
|
||||
connect( object_search, SIGNAL( centerAtObject( double_point_t ) ),
|
||||
mw, SLOT( setMapWidgetCenterAtPoint( double_point_t ) ) );
|
||||
|
||||
connect( object_search, SIGNAL( showInfoForFoundObject( gis_object_t ) ),
|
||||
mw, SLOT( showObjectInfoWindow( gis_object_t ) ) );
|
||||
|
||||
object_search->setCurrentTab( mw );
|
||||
|
||||
mapstyle_layer_window->setCurrentTab( mw );
|
||||
|
||||
updateMapStyles( mw->classifiers );
|
||||
}
|
177
src/apps/gis-map-viewer/mainwindow.h
Обычный файл
@ -0,0 +1,177 @@
|
||||
/*
|
||||
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 MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QPointer>
|
||||
#include <QSettings>
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
#include <QWidget>
|
||||
|
||||
#include "heightscale.h"
|
||||
#include "mapstylelayerwindow.h"
|
||||
#include "mapwidget.h"
|
||||
#include "layerwindow.h"
|
||||
#include "viewparameters.h"
|
||||
#include "objectsearch.h"
|
||||
#include "deptheditor.h"
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gisrender.h>
|
||||
|
||||
|
||||
struct CleanExit
|
||||
{
|
||||
CleanExit()
|
||||
{
|
||||
signal( SIGINT, &CleanExit::exitQt );
|
||||
signal( SIGTERM, &CleanExit::exitQt );
|
||||
}
|
||||
|
||||
static void exitQt( int sig )
|
||||
{
|
||||
Q_UNUSED( sig );
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow( QWidget *parent = 0 );
|
||||
~MainWindow();
|
||||
|
||||
int nTabs;
|
||||
|
||||
int lastOpenedTabIndex;
|
||||
bool oneMapMode;
|
||||
|
||||
int connectGisCore( gis_core_driver_id_t enabledDriverId );
|
||||
|
||||
void addTabWidget();
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
MapTabWidget *tab_wgt;
|
||||
QAction *aliasing_action;
|
||||
QAction *center_scaling_action;
|
||||
QAction *rescale_by_wheel_action;
|
||||
QAction *palette_action;
|
||||
QAction *scaling_action;
|
||||
QAction *auto_height_action;
|
||||
QAction *invalid_height_action;
|
||||
QAction *test_action;
|
||||
|
||||
QPointer <ViewParameters> view_params;
|
||||
QPointer <LayerWindow> layer_window;
|
||||
QPointer <MapStyleLayerWindow> mapstyle_layer_window;
|
||||
QPointer <HeightScale> height_scale;
|
||||
QPointer <ObjectSearch> object_search;
|
||||
|
||||
QPointer <DepthEditor> depth_editor;
|
||||
|
||||
gis_core_connection_t connection;
|
||||
|
||||
std::vector<gis_map_style_t> map_style_vector;
|
||||
|
||||
std::map<const QString, gis_vector_palette_list_t *> palettes_map;
|
||||
|
||||
QMenu *menuPalette;
|
||||
QMenu *menuLanguage;
|
||||
QMenu *menuFormatFeatures;
|
||||
|
||||
int windowX;
|
||||
int windowY;
|
||||
int widthPx;
|
||||
int heightPx;
|
||||
int32_t sharedMemoryUserId;
|
||||
|
||||
void closeEvent( QCloseEvent *event );
|
||||
|
||||
void updateMapStyles( std::vector<ClassifierInfo> &classifier_list );
|
||||
|
||||
void updateFormatFeaturesMenu( std::vector<gis_map_style_t> &mapstyle_list );
|
||||
void updatePaletteMenu( std::vector<gis_map_style_t> &mapstyle_list );
|
||||
void updateLanguageMenu( std::vector<gis_map_style_t> &mapstyle_list );
|
||||
|
||||
private slots:
|
||||
void fillMenuBar();
|
||||
|
||||
void autoHeightChecked( bool checked )
|
||||
{
|
||||
MapWidget *mw = tab_wgt->currentMapWidget();
|
||||
mw->setAutoRasterHeightLimits( checked );
|
||||
|
||||
if ( checked )
|
||||
height_scale->updateColorScale( mw->colorMap,
|
||||
mw->maxRasterHeight,
|
||||
mw->minRasterHeight );
|
||||
}
|
||||
|
||||
void changePalette();
|
||||
void flipLocale();
|
||||
void flipOneMapMode();
|
||||
|
||||
public slots:
|
||||
void createMapWidgets();
|
||||
void processTabChanging( int idx );
|
||||
void refreshMapData();
|
||||
|
||||
void setManualHeightLimits( double max, double min )
|
||||
{
|
||||
tab_wgt->currentMapWidget()->setRasterHeightLimits( min, max );
|
||||
auto_height_action->setChecked( false );
|
||||
}
|
||||
|
||||
void setMapWidgetCenterAtPoint( double_point_t object_center )
|
||||
{
|
||||
tab_wgt->currentMapWidget()->setMapWidgetCenterAtPoint( object_center );
|
||||
}
|
||||
|
||||
void showObjectInfoWindow( gis_object_t current_object )
|
||||
{
|
||||
tab_wgt->currentMapWidget()->showObjectInfoWindow( current_object );
|
||||
}
|
||||
|
||||
void showAboutDialog()
|
||||
{
|
||||
gis_gui_about( &connection, this );
|
||||
}
|
||||
|
||||
signals:
|
||||
void resetMapWidget();
|
||||
void updateAllDataEngines();
|
||||
};
|
||||
|
||||
#endif
|
296
src/apps/gis-map-viewer/mapstylelayerwindow.cpp
Обычный файл
@ -0,0 +1,296 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mapstylelayerwindow.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
|
||||
#define TYPE_LAYER_ITEM 6
|
||||
|
||||
MapStyleLayerWindow::MapStyleLayerWindow( QWidget *parent ) :
|
||||
QWidget( parent, Qt::Window ),
|
||||
cont( nullptr ),
|
||||
check_column( 0 ),
|
||||
acronym_column( 1 ),
|
||||
idx_column( 2 ),
|
||||
sequence_column( 3 )
|
||||
{
|
||||
borders.degrees.west = 180;
|
||||
borders.degrees.east = 180;
|
||||
borders.degrees.north = 90;
|
||||
borders.degrees.south = 90;
|
||||
|
||||
grid_layout = new QGridLayout;
|
||||
mapstyle_box = new QComboBox;
|
||||
listLayers = new QTreeWidget;
|
||||
|
||||
listLayers->setColumnCount( 4 );
|
||||
QStringList listLayersHeaders;
|
||||
listLayersHeaders << tr( "State" )
|
||||
<< tr( "Layer name" )
|
||||
<< tr( "Layer number" )
|
||||
<< tr( "Sequence number" );
|
||||
listLayers->setHeaderLabels( listLayersHeaders );
|
||||
listLayers->setColumnWidth( acronym_column, 170 );
|
||||
listLayers->setMaximumHeight( 350 );
|
||||
listLayers->setUniformRowHeights( true );
|
||||
|
||||
btnsBoxLayout = new QHBoxLayout;
|
||||
|
||||
selectAllBtn = new QPushButton;
|
||||
selectAllBtn->setText( tr("Select All") );
|
||||
connect( selectAllBtn, SIGNAL( clicked( bool ) ),
|
||||
this, SLOT( selectAllBtnClicked( bool ) ) );
|
||||
btnsBoxLayout->addWidget( selectAllBtn );
|
||||
|
||||
removeAllBtn = new QPushButton;
|
||||
removeAllBtn->setText( tr("Remove All") );
|
||||
connect( removeAllBtn, SIGNAL( clicked( bool ) ),
|
||||
this, SLOT( removeAllBtnClicked( bool ) ) );
|
||||
btnsBoxLayout->addWidget( removeAllBtn );
|
||||
|
||||
grid_layout->addWidget( new QLabel( tr( "Classifier name: " ) ), 1, 1 );
|
||||
grid_layout->addWidget( mapstyle_box, 1, 2 );
|
||||
grid_layout->addWidget( listLayers, 2, 1, 2, 2 );
|
||||
grid_layout->addLayout( btnsBoxLayout, 4, 1, 1, 2 );
|
||||
|
||||
grid_layout->setHorizontalSpacing( 10 );
|
||||
grid_layout->setVerticalSpacing( 10 );
|
||||
|
||||
connect( mapstyle_box, SIGNAL( currentIndexChanged( int ) ),
|
||||
this, SLOT( slotMapIndexChanged( int ) ) );
|
||||
connect( listLayers, SIGNAL( itemChanged( QTreeWidgetItem*, int ) ),
|
||||
this, SLOT( slotItemChanged( QTreeWidgetItem*, int ) ) );
|
||||
connect( this, SIGNAL( layerChecked( QTreeWidgetItem* ) ),
|
||||
this, SLOT( slotLayerChecked( QTreeWidgetItem* ) ) );
|
||||
connect( this, SIGNAL( layerUnchecked( QTreeWidgetItem* ) ),
|
||||
this, SLOT( slotLayerUnchecked( QTreeWidgetItem* ) ) );
|
||||
|
||||
setGeometry( 0, 0, 500, 300 );
|
||||
setFixedSize( 500, 300 );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
|
||||
setLayout( grid_layout );
|
||||
setWindowTitle( tr( "Classifier layer management" ) );
|
||||
}
|
||||
|
||||
MapStyleLayerWindow::~MapStyleLayerWindow()
|
||||
{
|
||||
delete removeAllBtn;
|
||||
delete selectAllBtn;
|
||||
delete btnsBoxLayout;
|
||||
delete listLayers;
|
||||
delete mapstyle_box;
|
||||
delete grid_layout;
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::setCurrentTab( MapWidget *wgt )
|
||||
{
|
||||
currentMapWidget = wgt;
|
||||
}
|
||||
|
||||
bool MapStyleLayerWindow::updateBorders()
|
||||
{
|
||||
gis_render_sm_context_t current_sm_ctx = currentMapWidget->getSurfacemanagerContext();
|
||||
|
||||
if ( !current_sm_ctx )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int res = gis_render_sm_get_draw_canvas_borders( current_sm_ctx, &borders );
|
||||
|
||||
if ( res != EOK )
|
||||
{
|
||||
qDebug() << "MapStyleLayerWindow: Failed to get canvas borders (" << strerror( res ) << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::showEvent( QShowEvent *event )
|
||||
{
|
||||
if ( parentWidget() )
|
||||
{
|
||||
int x = ( parentWidget()->width() - width() ) / 2;
|
||||
int y = ( parentWidget()->height() - height() ) / 2;
|
||||
|
||||
QPoint relative_pos = parentWidget()->mapToGlobal( QPoint( x, y ) );
|
||||
QWidget::move( relative_pos );
|
||||
}
|
||||
else
|
||||
qDebug() << "MapStyleLayerWindow: can't get pointer to parent Widget!";
|
||||
|
||||
if ( updateBorders() )
|
||||
{
|
||||
char **classifier_list = gis_map_style_fill_active_classifier_name_list( &borders );
|
||||
|
||||
if ( !classifier_list )
|
||||
{
|
||||
qDebug() << "MapStyleLayerWindow: active classifier list is nullptr!";
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !classifier_list[0] )
|
||||
{
|
||||
mapstyle_box->setCurrentIndex( 0 );
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( classifier_list[1] == nullptr )
|
||||
{
|
||||
int new_idx = mapstyle_box->findText( QString::fromLatin1( classifier_list[0] ) );
|
||||
mapstyle_box->setCurrentIndex( new_idx );
|
||||
}
|
||||
else
|
||||
mapstyle_box->setCurrentIndex( 0 );
|
||||
|
||||
gis_helper_free_string_list( &classifier_list );
|
||||
}
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::selectAllBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED( clicked );
|
||||
|
||||
int nLayer = listLayers->invisibleRootItem()->childCount();
|
||||
for ( int i = 0; i < nLayer; i++ )
|
||||
{
|
||||
auto item = listLayers->invisibleRootItem()->child( i );
|
||||
item->setCheckState( check_column, Qt::Checked );
|
||||
}
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::removeAllBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED( clicked );
|
||||
|
||||
int nLayer = listLayers->invisibleRootItem()->childCount();
|
||||
for ( int i = 0; i < nLayer; i++ )
|
||||
{
|
||||
auto item = listLayers->invisibleRootItem()->child(i);
|
||||
item->setCheckState( check_column, Qt::Unchecked );
|
||||
}
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::updateLists( std::vector<ClassifierInfo> &classifier_list )
|
||||
{
|
||||
if ( cont )
|
||||
{
|
||||
delete cont;
|
||||
}
|
||||
|
||||
cont = new MapStyleLayerContainer( classifier_list );
|
||||
|
||||
mapstyle_box->clear();
|
||||
for ( auto style : cont->_classifier_list )
|
||||
{
|
||||
mapstyle_box->addItem( QString::fromUtf8( style.name.c_str() ) );
|
||||
}
|
||||
|
||||
mapstyle_box->setCurrentIndex( 0 );
|
||||
|
||||
slotMapIndexChanged( 0 );
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::slotMapIndexChanged( int map_idx )
|
||||
{
|
||||
listLayers->clear();
|
||||
|
||||
if ( map_idx < 0 || cont->_classifier_list.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClassifierInfo &info = cont->_classifier_list.at( map_idx );
|
||||
for ( auto &layer : info.layers )
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem( TYPE_LAYER_ITEM );
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable );
|
||||
|
||||
if ( layer.layerIsActive )
|
||||
{
|
||||
item->setCheckState( check_column, Qt::Checked );
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setCheckState( check_column, Qt::Unchecked );
|
||||
}
|
||||
|
||||
item->setText( acronym_column, QString::fromUtf8( layer.layerAcronym.c_str() ) );
|
||||
item->setText( idx_column, QString::number( layer.layerNumber ) );
|
||||
item->setText( sequence_column, QString::number( layer.sequenceNumber ) );
|
||||
listLayers->addTopLevelItem( item );
|
||||
}
|
||||
|
||||
listLayers->resizeColumnToContents( check_column );
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::slotItemChanged( QTreeWidgetItem *item, int column )
|
||||
{
|
||||
if ( column == check_column )
|
||||
{
|
||||
if ( item->checkState( check_column ) == Qt::Checked)
|
||||
{
|
||||
emit layerChecked( item );
|
||||
}
|
||||
|
||||
if ( item->checkState( check_column ) == Qt::Unchecked)
|
||||
{
|
||||
emit layerUnchecked( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::slotLayerChecked( QTreeWidgetItem *item )
|
||||
{
|
||||
if ( item->type() == TYPE_LAYER_ITEM )
|
||||
{
|
||||
ClassifierInfo &info = cont->_classifier_list.at( mapstyle_box->currentIndex() );
|
||||
int32_t l_idx = listLayers->invisibleRootItem()->indexOfChild(item);
|
||||
info.layers[l_idx].layerIsActive = true;
|
||||
}
|
||||
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
void MapStyleLayerWindow::slotLayerUnchecked( QTreeWidgetItem *item )
|
||||
{
|
||||
if ( item->type() == TYPE_LAYER_ITEM )
|
||||
{
|
||||
ClassifierInfo &info = cont->_classifier_list.at( mapstyle_box->currentIndex() );
|
||||
int32_t l_idx = listLayers->invisibleRootItem()->indexOfChild( item );
|
||||
info.layers[l_idx].layerIsActive = false;
|
||||
}
|
||||
|
||||
emit updateMapWidget();
|
||||
}
|
92
src/apps/gis-map-viewer/mapstylelayerwindow.h
Обычный файл
@ -0,0 +1,92 @@
|
||||
/*
|
||||
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 MAPSTYLELAYERWINDOW_H
|
||||
#define MAPSTYLELAYERWINDOW_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QMainWindow>
|
||||
#include <QPushButton>
|
||||
#include <QTreeWidget>
|
||||
#include <QShowEvent>
|
||||
|
||||
#include <gis/gis_databuffer.h>
|
||||
|
||||
#include "mapwidget.h"
|
||||
|
||||
class MapStyleLayerContainer
|
||||
{
|
||||
public:
|
||||
explicit MapStyleLayerContainer( std::vector<ClassifierInfo> &classifier_list ) :
|
||||
_classifier_list(classifier_list) {}
|
||||
|
||||
std::vector <ClassifierInfo> &_classifier_list;
|
||||
};
|
||||
|
||||
class MapStyleLayerWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MapStyleLayerWindow( QWidget *parent = 0 );
|
||||
|
||||
~MapStyleLayerWindow();
|
||||
|
||||
void updateLists( std::vector<ClassifierInfo> &classifier_list );
|
||||
void setCurrentTab( MapWidget *wgt );
|
||||
|
||||
private:
|
||||
MapStyleLayerContainer *cont;
|
||||
QGridLayout *grid_layout;
|
||||
QComboBox *mapstyle_box;
|
||||
QTreeWidget *listLayers;
|
||||
QPushButton *removeAllBtn;
|
||||
QPushButton *selectAllBtn;
|
||||
QHBoxLayout *btnsBoxLayout;
|
||||
|
||||
QPointer<MapWidget> currentMapWidget;
|
||||
|
||||
int check_column;
|
||||
int acronym_column;
|
||||
int idx_column;
|
||||
int sequence_column;
|
||||
|
||||
gis_borders_t borders;
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
bool updateBorders();
|
||||
|
||||
private slots:
|
||||
void removeAllBtnClicked( bool clicked);
|
||||
void selectAllBtnClicked( bool clicked);
|
||||
void slotMapIndexChanged( int);
|
||||
void slotItemChanged( QTreeWidgetItem*, int );
|
||||
void slotLayerChecked( QTreeWidgetItem* );
|
||||
void slotLayerUnchecked( QTreeWidgetItem* );
|
||||
|
||||
signals:
|
||||
void layerChecked( QTreeWidgetItem* );
|
||||
void layerUnchecked( QTreeWidgetItem* );
|
||||
void updateMapWidget();
|
||||
};
|
||||
|
||||
#endif
|
966
src/apps/gis-map-viewer/mapwidget.cpp
Обычный файл
@ -0,0 +1,966 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mapwidget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QGridLayout>
|
||||
#include <QPainter>
|
||||
#include <QSettings>
|
||||
|
||||
#include <gis/gis_objects.h>
|
||||
|
||||
MapWidget::MapWidget( gis_core_connection_t *outer_connection, int idx, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
isAliasingEnabled( false ),
|
||||
isConstScalingEnabled( true ),
|
||||
centerOnScaling( true ),
|
||||
rescaleByWheel( true ),
|
||||
autoRasterHeightLimits( true ),
|
||||
rasterDiscretePalette( false ),
|
||||
rasterInvalidHeightMode( false ),
|
||||
index( idx ),
|
||||
connection( outer_connection ),
|
||||
pin( true ),
|
||||
dont_save_to_config( false ),
|
||||
initialized( false ),
|
||||
userForm( nullptr ),
|
||||
distance_meter( nullptr ),
|
||||
objInfo( nullptr )
|
||||
{
|
||||
if( loadSettings() != EOK )
|
||||
{
|
||||
qDebug() << "Failed reading settings for this[" << index << "] mapwidget config!" << endl;
|
||||
}
|
||||
|
||||
setMinimumSize( minimumWidgetWidth, minimumWidgetHeight );
|
||||
setMaximumSize( maximumWidgetWidth, maximumWidgetHeight );
|
||||
|
||||
setAttribute( Qt::WA_OpaquePaintEvent );
|
||||
|
||||
QGridLayout *layout = new QGridLayout( this );
|
||||
increaseButton = new QPushButton( QIcon( ":/icons/zoomin50.png" ), "" );
|
||||
decreaseButton = new QPushButton( QIcon( ":/icons/zoomout50.png" ), "" );
|
||||
closeButton = new QPushButton( QIcon( ":/icons/shutdown.png" ), "" );
|
||||
meterButton = new QPushButton( QIcon( ":/icons/ruler.png" ), "" );
|
||||
savePinButton = new QPushButton( QIcon( ":/icons/save_pin.png" ), "" );
|
||||
showPinButton = new QPushButton( QIcon( ":/icons/pin.png" ), "" );
|
||||
|
||||
|
||||
QSize iconSize( iconSideSizePx, iconSideSizePx );
|
||||
increaseButton->setIconSize( iconSize );
|
||||
decreaseButton->setIconSize( iconSize );
|
||||
closeButton->setIconSize( iconSize );
|
||||
meterButton->setIconSize( iconSize );
|
||||
savePinButton->setIconSize( iconSize );
|
||||
showPinButton->setIconSize( iconSize );
|
||||
|
||||
scaleLabel = new QLabel();
|
||||
scaleLabel->setAutoFillBackground( true );
|
||||
scaleLabel->setBackgroundRole( QPalette::Base );
|
||||
scaleLabel->setAlignment( Qt::AlignRight );
|
||||
|
||||
positionLabel = new QLabel();
|
||||
positionLabel->setAutoFillBackground( true );
|
||||
positionLabel->setBackgroundRole( QPalette::Base );
|
||||
|
||||
layout->setSpacing( buttonBorderOffset );
|
||||
|
||||
QHBoxLayout *h_lay = new QHBoxLayout;
|
||||
|
||||
h_lay->addWidget( increaseButton );
|
||||
h_lay->addWidget( decreaseButton );
|
||||
h_lay->addWidget( meterButton );
|
||||
h_lay->addWidget( savePinButton );
|
||||
h_lay->addWidget( showPinButton );
|
||||
|
||||
layout->addLayout( h_lay, 0, 0, Qt::AlignLeft | Qt::AlignTop );
|
||||
layout->addWidget( closeButton, 0, 2, 1, 1, Qt::AlignRight | Qt::AlignTop );
|
||||
layout->addWidget( scaleLabel, 2, 2, 1, 1, Qt::AlignRight | Qt::AlignBottom );
|
||||
layout->addWidget( positionLabel, 2, 0, 1, 1, Qt::AlignLeft | Qt::AlignBottom );
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
connect( increaseButton, SIGNAL( released() ), this, SLOT( increaseScale() ) );
|
||||
connect( decreaseButton, SIGNAL( released() ), this, SLOT( decreaseScale() ) );
|
||||
connect( meterButton, SIGNAL( released() ), this, SLOT( showMeter() ) );
|
||||
connect( savePinButton, SIGNAL( released() ), this, SLOT( savePin() ) );
|
||||
connect( showPinButton, SIGNAL( released() ), this, SLOT( showPin() ) );
|
||||
connect( closeButton, SIGNAL( released() ), QApplication::instance(), SLOT( quit() ) );
|
||||
|
||||
connect( this, SIGNAL( getMouseRelease( QPoint ) ), this, SLOT( updatePositionLabel( QPoint ) ) );
|
||||
connect( this, SIGNAL( scaleValueChanged( uint32_t ) ), this, SLOT( updateScaleLabel( uint32_t ) ) );
|
||||
|
||||
QList<Qt::GestureType> gestures;
|
||||
gestures << Qt::PinchGesture;
|
||||
grabGestures( gestures );
|
||||
|
||||
|
||||
if ( idx_scale >= scale_values.size() )
|
||||
{
|
||||
qWarning() << QTime::currentTime().toString() << "Scale limit";
|
||||
idx_scale = ( scale_values.size() - 1 ) / 2;
|
||||
}
|
||||
|
||||
setScaleValue( scale_values[idx_scale] );
|
||||
}
|
||||
|
||||
MapWidget::~MapWidget()
|
||||
{
|
||||
if ( !dont_save_to_config )
|
||||
{
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
gis_render_sm_free( &sm_ctx );
|
||||
gis_data_engine_free( &data_engine_ctx );
|
||||
}
|
||||
|
||||
int MapWidget::loadSettings()
|
||||
{
|
||||
QString gis_config( gis_helper_env_get_config_directory() );
|
||||
QSettings settings( gis_config + "gis-map-viewer.conf", QSettings::IniFormat);
|
||||
|
||||
settings.beginGroup("MapWidget");
|
||||
|
||||
QVector<QVariant> scales_str = settings.value( "scales", 0 ).toList().toVector();
|
||||
|
||||
for( int i = 0; i < scales_str.size(); i++)
|
||||
{
|
||||
scale_values.push_back( scales_str[i].toInt() );
|
||||
}
|
||||
|
||||
settings.beginGroup( QString::number( index ) );
|
||||
|
||||
geo_center.x = settings.value( "longitude", 0 ).toDouble();
|
||||
geo_center.y = settings.value( "latitude", 0 ).toDouble();
|
||||
idx_scale = settings.value("scaleVectorIndex", ( scale_values.size() - 1 ) / 2 ).toInt();
|
||||
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
offscreen_ext_px = settings.value( "SurfaceManager/offscreenExtension", 0 ).toInt();
|
||||
blit_region_rate = settings.value( "SurfaceManager/blitRegionRate", 0.5 ).toFloat();
|
||||
allocInRam = settings.value( "SurfaceManager/allocInRam", false ).toBool();
|
||||
smMode = settings.value( "SurfaceManager/smMode", GIS_RENDER_SM_MODE_ASYNC ).toInt();
|
||||
|
||||
brightness = settings.value( "MapDisplayParameters/brightness" ).toFloat();
|
||||
contrast = settings.value( "MapDisplayParameters/contrast" ).toFloat();
|
||||
|
||||
invalidRasterHeightColor =
|
||||
settings.value( "MapDisplayParameters/invalidRasterHeightColor" ).toString().toUInt( nullptr, 16 );
|
||||
|
||||
maxRasterHeight = settings.value( "MapDisplayParameters/maximumRasterHeightMeters" ).toDouble();
|
||||
minRasterHeight = settings.value( "MapDisplayParameters/minimumRasterHeightMeters" ).toDouble();
|
||||
|
||||
minimumWidgetWidth = settings.value( "InterfaceParameters/minWidth" ).toInt();
|
||||
minimumWidgetHeight = settings.value( "InterfaceParameters/minHeight" ).toInt();
|
||||
maximumWidgetWidth = settings.value( "InterfaceParameters/maxWidth" ).toInt();
|
||||
maximumWidgetHeight = settings.value( "InterfaceParameters/maxHeight" ).toInt();
|
||||
objectSearchSideSizePx = settings.value( "InterfaceParameters/objectSearchSideSizePx" ).toInt();
|
||||
buttonBorderOffset = settings.value( "InterfaceParameters/buttonBorderOffset" ).toInt();
|
||||
iconSideSizePx = settings.value( "InterfaceParameters/iconSideSizePx" ).toInt();
|
||||
|
||||
settings.beginGroup( "MapWidget" );
|
||||
|
||||
if ( !settings.childGroups().contains( QString::number( index ) ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
void MapWidget::saveSettings()
|
||||
{
|
||||
QString gis_config( gis_helper_env_get_config_directory() );
|
||||
QSettings settings( gis_config + "gis-map-viewer.conf", QSettings::IniFormat);
|
||||
|
||||
gis_mdp_t mdp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
double_point_t center;
|
||||
gis_mdp_get_center_point_deg( mdp, ¢er );
|
||||
|
||||
settings.beginGroup( "MapWidget" );
|
||||
settings.beginGroup( QString::number( index ) );
|
||||
|
||||
settings.setValue( "longitude", center.x );
|
||||
settings.setValue( "latitude", center.y );
|
||||
settings.setValue( "scaleVectorIndex", idx_scale );
|
||||
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
settings.setValue( "MapDisplayParameters/brightness", brightness );
|
||||
settings.setValue( "MapDisplayParameters/contrast", contrast );
|
||||
}
|
||||
|
||||
void MapWidget::initialize()
|
||||
{
|
||||
if ( gis_data_engine_alloc( width(),
|
||||
height(),
|
||||
GIS_DATA_ENGINE_MODE_SM,
|
||||
GIS_DATA_ENGINE_BPP_32,
|
||||
connection,
|
||||
&data_engine_ctx ) != EOK )
|
||||
{
|
||||
qWarning() << QTime::currentTime().toString() << "Failed to alloc data engine";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gis_data_engine_set_notify_func( &data_engine_ctx, this );
|
||||
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
gis_map_projection_init( &proj_params );
|
||||
|
||||
if ( gis_map_projection_init( &proj_params ) != EOK )
|
||||
{
|
||||
qWarning( "Failed to init projection\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gis_data_engine_get_maps_projection( data_engine_ctx, &geo_center, &proj_params );
|
||||
|
||||
gis_mdp_set_projection( disp_param, &proj_params );
|
||||
gis_mdp_set_center_point( disp_param, geo_center );
|
||||
gis_mdp_set_phys_scale( disp_param, scale_value );
|
||||
gis_mdp_set_background_color( disp_param, 0xffffff );
|
||||
gis_mdp_set_scaling_mode( disp_param, true );
|
||||
gis_mdp_set_map_antialiasing_level( disp_param, 0 );
|
||||
|
||||
uint32_t flags = 0;
|
||||
if ( allocInRam )
|
||||
{
|
||||
flags |= GIS_RENDER_SM_ALLOC_RAM;
|
||||
}
|
||||
|
||||
if ( gis_render_sm_alloc( &sm_ctx,
|
||||
data_engine_ctx,
|
||||
offscreen_ext_px,
|
||||
blit_region_rate,
|
||||
flags ) != EOK )
|
||||
{
|
||||
qWarning( "Failed to alloc surface manager" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gis_render_sm_set_update_func( sm_ctx, (SMCallbacks*)this );
|
||||
|
||||
if ( allocInRam )
|
||||
{
|
||||
gis_render_sm_set_render_mode( sm_ctx, GIS_RENDER_SM_MODE_SYNC );
|
||||
}
|
||||
else
|
||||
{
|
||||
gis_render_sm_set_render_mode( sm_ctx, smMode );
|
||||
}
|
||||
|
||||
setRasterPalette();
|
||||
fillClassifierInfo();
|
||||
fillLayerTypeList();
|
||||
|
||||
distance_meter = new DistanceMeter( sm_ctx );
|
||||
connect( distance_meter, SIGNAL( updateMapWidget() ), this, SLOT( update() ) );
|
||||
connect( this, SIGNAL( getNewMeterPoint( QPoint ) ), distance_meter, SLOT( meterListener( QPoint ) ) );
|
||||
connect( distance_meter, SIGNAL( widgetVisibilityChanged( bool ) ), this, SLOT( setTabBlockingFlag( bool ) ) );
|
||||
|
||||
objInfo = new ObjectInfo( sm_ctx );
|
||||
connect( objInfo, SIGNAL( updateMapWidget() ), this, SLOT( update() ) );
|
||||
connect( objInfo, SIGNAL( widgetVisibilityChanged( bool ) ), this, SLOT( setTabBlockingFlag( bool ) ) );
|
||||
|
||||
userForm = new UserDialog( sm_ctx, disp_param, scale_values );
|
||||
connect( userForm, SIGNAL( updateMapWidget() ), this, SLOT( update() ) );
|
||||
connect( this, SIGNAL( getNewUserObjPoint( QPoint ) ), userForm, SLOT( userObjListener( QPoint ) ) );
|
||||
connect( userForm, SIGNAL( widgetVisibilityChanged( bool ) ), this, SLOT( setTabBlockingFlag( bool ) ) );
|
||||
|
||||
initialized = true;
|
||||
|
||||
emit getMouseRelease( QPoint( width() / 2, height() / 2 ) );
|
||||
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
gis_render_sm_context_t MapWidget::getSurfacemanagerContext()
|
||||
{
|
||||
if ( initialized )
|
||||
{
|
||||
return sm_ctx;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::updateDatabufferDescriptor()
|
||||
{
|
||||
if ( gis_data_engine_update( data_engine_ctx ) != EOK )
|
||||
{
|
||||
qDebug() << QTime::currentTime().toString() << "Failed to update databuffer descriptor";
|
||||
exit( EFAULT );
|
||||
}
|
||||
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::updateProjectionParameters()
|
||||
{
|
||||
gis_map_projection_t saved_params = proj_params;
|
||||
|
||||
if ( gis_gui_get_projection_parameters( &proj_params, this ) == EOK )
|
||||
{
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
if ( gis_mdp_set_projection( disp_param, &proj_params ) != EOK )
|
||||
{
|
||||
qDebug() << QTime::currentTime().toString() << "Failed to set projection";
|
||||
proj_params = saved_params;
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << QTime::currentTime().toString() << "Projection:" << gis_map_projection_get_full_name( &proj_params );
|
||||
qDebug() << QTime::currentTime().toString() << "Ellipsoid:" << gis_map_ellipsoid_get_full_name( &proj_params );
|
||||
qDebug() << QTime::currentTime().toString() << "EPSG:" << proj_params.EPSG;
|
||||
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::updateScreenParameters()
|
||||
{
|
||||
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
if ( gis_gui_get_screen_parameters( dp, this ) == EOK )
|
||||
{
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::setIndex( int idx )
|
||||
{
|
||||
this->index = idx;
|
||||
}
|
||||
|
||||
int MapWidget::getIndex()
|
||||
{
|
||||
return this->index;
|
||||
}
|
||||
|
||||
void MapWidget::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
Q_UNUSED( event );
|
||||
if ( initialized )
|
||||
{
|
||||
if ( gis_data_engine_set_canvas_size( data_engine_ctx, width(), height() ) == EOK )
|
||||
{
|
||||
if ( gis_render_sm_update( sm_ctx, offscreen_ext_px, blit_region_rate ) != EOK )
|
||||
{
|
||||
qWarning( "Failed to update surface manager context" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::paintEvent( QPaintEvent * event )
|
||||
{
|
||||
if ( event->rect().size() != size() )
|
||||
{
|
||||
return QWidget::paintEvent( event );
|
||||
}
|
||||
|
||||
if ( initialized )
|
||||
{
|
||||
gis_render_sm_draw( sm_ctx );
|
||||
|
||||
QPixmap *pixmap = (QPixmap*)gis_render_sm_get_view_pixmap( sm_ctx, &viewport_pos );
|
||||
QPainter painter( this );
|
||||
painter.drawPixmap( 0, 0, *pixmap, viewport_pos.x, viewport_pos.y, width(), height() );
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::updatePositionLabel( QPoint pos )
|
||||
{
|
||||
double_point_t degree_pos = { 0, 0 };
|
||||
double_point_t meter_pos = { 0, 0 };
|
||||
int32_point_t px_pos = { pos.x(), pos.y() };
|
||||
gis_render_sm_convert_px2degree( sm_ctx, px_pos, °ree_pos );
|
||||
gis_render_sm_convert_px2meters( sm_ctx, px_pos, &meter_pos );
|
||||
|
||||
QString positionString;
|
||||
positionString = tr(" Lat: ") + QString::number( degree_pos.y, 'f', 5 ) + QString::fromUtf8("°")
|
||||
+ tr(" Long: ") + QString::number( degree_pos.x, 'f', 5 ) + QString::fromUtf8("°");
|
||||
|
||||
positionString += " X: " + QString::number( meter_pos.x, 'f', 2 )
|
||||
+ "m Y: " + QString::number( meter_pos.y, 'f', 2 ) + "m";
|
||||
|
||||
positionLabel->setText( positionString );
|
||||
|
||||
QString croppedDegreePosition = tr(" Lat: ") + QString::number( degree_pos.y, 'f', 2 ) + QString::fromUtf8("°")
|
||||
+ tr(" Long: ") + QString::number( degree_pos.x, 'f', 2 ) + QString::fromUtf8("°");
|
||||
|
||||
emit positionLabelChanged( index, croppedDegreePosition );
|
||||
}
|
||||
|
||||
void MapWidget::setMapWidgetCenterAtPoint( double_point_t object_center )
|
||||
{
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_center_point( disp_param, object_center );
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::updateScaleLabel( uint32_t scale_val )
|
||||
{
|
||||
QString scaleString = "1:" + QString::number( (long)scale_val );
|
||||
scaleLabel->setText( scaleString );
|
||||
}
|
||||
|
||||
void MapWidget::increaseScale()
|
||||
{
|
||||
if ( idx_scale + 1 >= scale_values.size() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setScaleValue( scale_values[++idx_scale] );
|
||||
|
||||
gis_render_sm_rescale( sm_ctx, scale_value );
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::decreaseScale()
|
||||
{
|
||||
if ( idx_scale - 1 < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setScaleValue( scale_values[--idx_scale] );
|
||||
|
||||
gis_render_sm_rescale( sm_ctx, scale_value );
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::sync()
|
||||
{
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void MapWidget::mousePressEvent( QMouseEvent *event )
|
||||
{
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
{
|
||||
last_position = event->pos();
|
||||
|
||||
if ( !distance_meter->isHidden() )
|
||||
{
|
||||
emit getNewMeterPoint( event->pos() );
|
||||
}
|
||||
|
||||
if ( !userForm->isHidden() )
|
||||
{
|
||||
emit getNewUserObjPoint( event->pos() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( event->button() == Qt::RightButton )
|
||||
{
|
||||
last_position = event->pos();
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void MapWidget::mouseMoveEvent( QMouseEvent *event )
|
||||
{
|
||||
QPoint delta = event->pos() - last_position;
|
||||
last_position = event->pos();
|
||||
|
||||
gis_render_sm_move( sm_ctx, delta.x(), delta.y() );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::mouseReleaseEvent( QMouseEvent *event )
|
||||
{
|
||||
emit getMouseRelease( event->pos() );
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void MapWidget::wheelEvent( QWheelEvent *event )
|
||||
{
|
||||
double_point_t center;
|
||||
int32_point_t scale_pnt_px;
|
||||
|
||||
scale_pnt_px.x = event->x();
|
||||
scale_pnt_px.y = event->y();
|
||||
|
||||
if ( centerOnScaling )
|
||||
{
|
||||
if ( gis_render_sm_convert_px2degree( sm_ctx, scale_pnt_px, ¢er ) == EOK )
|
||||
{
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_center_point( disp_param, center );
|
||||
if ( !rescaleByWheel )
|
||||
{
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( rescaleByWheel )
|
||||
{
|
||||
if ( event->delta() > 0 )
|
||||
increaseScale();
|
||||
else if ( event->delta() < 0 )
|
||||
decreaseScale();
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::mouseDoubleClickEvent( QMouseEvent *event )
|
||||
{
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
showObjectInfo(event->pos());
|
||||
}
|
||||
|
||||
void MapWidget::closeEvent( QCloseEvent *event )
|
||||
{
|
||||
dont_save_to_config = true;
|
||||
event->accept();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MapWidget::grabGestures( const QList<Qt::GestureType> &gestures )
|
||||
{
|
||||
foreach ( Qt::GestureType gesture, gestures )
|
||||
grabGesture( gesture );
|
||||
}
|
||||
|
||||
bool MapWidget::event( QEvent *event )
|
||||
{
|
||||
if ( event->type() == QEvent::Gesture )
|
||||
{
|
||||
event->accept();
|
||||
return gestureEvent( static_cast<QGestureEvent*>(event) );
|
||||
}
|
||||
return QWidget::event( event );
|
||||
}
|
||||
|
||||
bool MapWidget::gestureEvent( QGestureEvent *event )
|
||||
{
|
||||
if ( QGesture *swipe = event->gesture( Qt::SwipeGesture ) )
|
||||
{
|
||||
swipeTriggered( (QSwipeGesture*)swipe );
|
||||
}
|
||||
else if ( QGesture *pan = event->gesture( Qt::PanGesture ) )
|
||||
{
|
||||
panTriggered( (QPanGesture*)pan );
|
||||
}
|
||||
else if ( QGesture *pinch = event->gesture( Qt::PinchGesture ) )
|
||||
{
|
||||
pinchTriggered( (QPinchGesture*)pinch );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MapWidget::pinchTriggered( QPinchGesture *gesture )
|
||||
{
|
||||
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
|
||||
|
||||
if ( changeFlags & QPinchGesture::ScaleFactorChanged )
|
||||
{
|
||||
currentStepScaleFactor = gesture->totalScaleFactor();
|
||||
}
|
||||
|
||||
if ( gesture->state() == Qt::GestureFinished )
|
||||
{
|
||||
if ( gesture->scaleFactor() > currentStepScaleFactor )
|
||||
{
|
||||
decreaseScale();
|
||||
}
|
||||
else
|
||||
{
|
||||
increaseScale();
|
||||
}
|
||||
|
||||
currentStepScaleFactor = 1;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::swipeTriggered( QSwipeGesture *swipe )
|
||||
{
|
||||
Q_UNUSED( swipe );
|
||||
|
||||
}
|
||||
|
||||
void MapWidget::panTriggered( QPanGesture *pan )
|
||||
{
|
||||
Q_UNUSED( pan );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MapWidget::updateBrightnessContrast( float br, float cn )
|
||||
{
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_brightness_contrast( disp_param, br, cn );
|
||||
brightness = br;
|
||||
contrast = cn;
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::updateLayerOrder( int idx, gis_render_sm_layer_type_t type )
|
||||
{
|
||||
layer_list[idx].layer_type = type;
|
||||
layer_list[idx].z_idx = idx;
|
||||
|
||||
gis_render_sm_set_layer_type( sm_ctx, idx, type );
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::updateDataSourcesForLayer( gis_render_sm_layer_type_t layer_type,
|
||||
int num_of_data_sources,
|
||||
gis_core_map_data_source_t *data_sources )
|
||||
{
|
||||
gis_render_sm_set_layer_data_sources( sm_ctx,
|
||||
layer_type,
|
||||
num_of_data_sources,
|
||||
data_sources );
|
||||
|
||||
gis_render_sm_update( sm_ctx, offscreen_ext_px, 0.5 );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::fillClassifierInfo()
|
||||
{
|
||||
if ( gis_data_engine_get_classifier_list( data_engine_ctx, classifiers ) != EOK )
|
||||
{
|
||||
qWarning( "Failed to fill classifier info" );
|
||||
}
|
||||
|
||||
if ( gis_data_engine_get_map_list( data_engine_ctx, maps ) != EOK )
|
||||
{
|
||||
qWarning( "Failed to fill map list" );
|
||||
}
|
||||
|
||||
if ( classifiers.empty() || maps.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<ClassifierInfo> new_classifiers;
|
||||
|
||||
for ( const auto &map : maps )
|
||||
{
|
||||
bool already_have = false;
|
||||
for ( const auto &new_classifier : new_classifiers )
|
||||
{
|
||||
if ( new_classifier.name.compare( map.classifierName ) == 0 )
|
||||
{
|
||||
already_have = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( already_have )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( const auto &classifier : classifiers )
|
||||
{
|
||||
if ( classifier.name.compare( map.classifierName ) == 0 )
|
||||
{
|
||||
new_classifiers.push_back( classifier );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classifiers = new_classifiers;
|
||||
}
|
||||
|
||||
void MapWidget::fillLayerTypeList()
|
||||
{
|
||||
layer_list.clear();
|
||||
|
||||
LayerInfo info;
|
||||
|
||||
for ( int i = 0; i < GIS_RENDER_SM_SURFACE_NUMBER; i++ )
|
||||
{
|
||||
info.layer_type = gis_render_sm_get_layer_type( sm_ctx, i );
|
||||
info.z_idx = i;
|
||||
layer_list.append( info );
|
||||
}
|
||||
}
|
||||
|
||||
void MapWidget::setAliasingMode( bool enable )
|
||||
{
|
||||
isAliasingEnabled = enable;
|
||||
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
if ( isAliasingEnabled )
|
||||
{
|
||||
int level = 1;
|
||||
gis_mdp_set_map_antialiasing_level( dp, level );
|
||||
}
|
||||
else
|
||||
{
|
||||
gis_mdp_set_map_antialiasing_level( dp, 0 );
|
||||
}
|
||||
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void MapWidget::setRasterPalette()
|
||||
{
|
||||
colorMap.clear();
|
||||
colorMap << 0x00004030 << 0x00186424 << 0x0048AC0C << 0x00ACC800
|
||||
<< 0x00D0E000 << 0x00F4F800 << 0x00E4C400 << 0x00D29A00
|
||||
<< 0x00C07000 << 0x00AE4600 << 0x00A22A00 << 0x00960E00;
|
||||
|
||||
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_raster_color_mode( dp, rasterDiscretePalette );
|
||||
|
||||
setRasterInvalidHeightMode( rasterInvalidHeightMode );
|
||||
|
||||
#if 0
|
||||
gis_mdp_set_raster_height_limits( dp, min_h, max_h );
|
||||
#else
|
||||
setAutoRasterHeightLimits( true );
|
||||
#endif
|
||||
|
||||
|
||||
gis_mdp_set_raster_palette( dp, colorMap.data(), colorMap.size() );
|
||||
}
|
||||
|
||||
void MapWidget::setRasterHeightLimits( double new_min, double new_max )
|
||||
{
|
||||
minRasterHeight = new_min;
|
||||
maxRasterHeight = new_max;
|
||||
|
||||
setAutoRasterHeightLimits( false );
|
||||
|
||||
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_raster_height_limits( dp, minRasterHeight, maxRasterHeight );
|
||||
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::setDiscretePalette( bool enabled )
|
||||
{
|
||||
rasterDiscretePalette = enabled;
|
||||
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_raster_color_mode( dp, rasterDiscretePalette );
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::setRasterInvalidHeightMode( bool show )
|
||||
{
|
||||
rasterInvalidHeightMode = show;
|
||||
gis_mdp_t dp = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
if ( rasterInvalidHeightMode )
|
||||
{
|
||||
gis_mdp_set_raster_invalid_height_color( dp, invalidRasterHeightColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t background_color = gis_mdp_get_background_color( dp );
|
||||
gis_mdp_set_raster_invalid_height_color( dp, background_color );
|
||||
}
|
||||
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MapWidget::showObjectInfo( QPoint px_click )
|
||||
{
|
||||
std::vector<gis_core_class_code_t> class_list;
|
||||
class_list.clear();
|
||||
|
||||
gis_data_engine_get_class_list( data_engine_ctx, classifiers, class_list );
|
||||
|
||||
if ( class_list.empty() )
|
||||
{
|
||||
class_list.push_back( GIS_CLASS_CODE_UNDEFINED );
|
||||
}
|
||||
|
||||
int result = -1;
|
||||
size_t step = 1;
|
||||
gis_object_t _obj;
|
||||
gis_object_init( &_obj );
|
||||
|
||||
do {
|
||||
|
||||
double_point_t deg_pos = { 0, 0 };
|
||||
|
||||
double_point_t east_south_box_point = { 0, 0 };
|
||||
double_point_t west_north_box_point = { 0, 0 };
|
||||
|
||||
int32_point_t px_pos = { px_click.x(), px_click.y() };
|
||||
|
||||
int32_point_t east_south_box_pos;
|
||||
east_south_box_pos.x = px_click.x() + step * objectSearchSideSizePx;
|
||||
east_south_box_pos.y = px_click.y() + step * objectSearchSideSizePx;
|
||||
|
||||
int32_point_t west_north_box_pos;
|
||||
west_north_box_pos.x = px_click.x() - step * objectSearchSideSizePx;
|
||||
west_north_box_pos.y = px_click.y() - step * objectSearchSideSizePx;
|
||||
|
||||
gis_render_sm_convert_px2degree( sm_ctx, px_pos, °_pos );
|
||||
gis_render_sm_convert_px2degree( sm_ctx, east_south_box_pos, &east_south_box_point );
|
||||
gis_render_sm_convert_px2degree( sm_ctx, west_north_box_pos, &west_north_box_point );
|
||||
|
||||
gis_borders_t region_of_interest;
|
||||
region_of_interest.degrees.west = west_north_box_point.x;
|
||||
region_of_interest.degrees.east = east_south_box_point.x;
|
||||
region_of_interest.degrees.south = east_south_box_point.y;
|
||||
region_of_interest.degrees.north = west_north_box_point.y;
|
||||
|
||||
object_point_t point_pos;
|
||||
|
||||
point_pos.degrees.x = deg_pos.x;
|
||||
point_pos.degrees.y = deg_pos.y;
|
||||
|
||||
GisObjectList list(®ion_of_interest, class_list);
|
||||
|
||||
int idx = list.find_nearest_object(point_pos);
|
||||
if ( idx < 0 )
|
||||
return;
|
||||
|
||||
result = list.get_object(idx, _obj);
|
||||
step++;
|
||||
} while ( result != EOK );
|
||||
|
||||
objInfo->updateInfo( &_obj );
|
||||
objInfo->move( mapToGlobal( px_click + QPoint( buttonBorderOffset, buttonBorderOffset ) ) );
|
||||
objInfo->show();
|
||||
gis_object_free( &_obj );
|
||||
}
|
||||
|
||||
void MapWidget::showObjectInfoWindow( gis_object_t current_object )
|
||||
{
|
||||
objInfo->updateInfo( ¤t_object );
|
||||
|
||||
int x = ( this->width() / 2 ) + buttonBorderOffset;
|
||||
int y = ( this->height() / 2 ) + buttonBorderOffset;
|
||||
|
||||
QPoint relative_pos = this->mapToGlobal( QPoint( x, y ) );
|
||||
objInfo->move( relative_pos );
|
||||
|
||||
objInfo->show();
|
||||
}
|
||||
|
||||
void MapWidget::showUserForm()
|
||||
{
|
||||
int x = ( this->width() - userForm->width() ) / 2;
|
||||
int y = ( this->height() - userForm->height() ) / 2;
|
||||
|
||||
QPoint relative_pos = this->mapToGlobal( QPoint( x, y ) );
|
||||
userForm->move( relative_pos );
|
||||
|
||||
userForm->show();
|
||||
}
|
||||
|
||||
void MapWidget::showMeter()
|
||||
{
|
||||
int x = this->width() - ( 15 + distance_meter->sizeHint().width() );
|
||||
int y = 10;
|
||||
|
||||
QPoint relative_pos = this->mapToGlobal( QPoint( x, y ) );
|
||||
distance_meter->move( relative_pos );
|
||||
|
||||
distance_meter->show();
|
||||
}
|
||||
void MapWidget::savePin()
|
||||
{
|
||||
QPushButton *button = static_cast<QPushButton*>( sender() );
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
if ( pin )
|
||||
{
|
||||
button->setToolTip( tr("Delete screen position") );
|
||||
button->setStyleSheet( "QPushButton { background-color: rgb( 162, 162, 162 ); }" );
|
||||
|
||||
pinned_scale = gis_mdp_get_phys_scale( disp_param );
|
||||
gis_mdp_get_center_point_deg(disp_param, &pinned_position);
|
||||
pin = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
button->setToolTip( tr("Save screen position") );
|
||||
button->setStyleSheet( "QPushButton { background-color: rgb( 239, 239, 239 ); }" );
|
||||
|
||||
pin = true;
|
||||
}
|
||||
}
|
||||
void MapWidget::showPin()
|
||||
{
|
||||
if ( !pin )
|
||||
{
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
|
||||
gis_mdp_set_phys_scale( disp_param, pinned_scale );
|
||||
gis_mdp_set_center_point(disp_param, pinned_position );
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MapWidget::updateMapDrawing()
|
||||
{
|
||||
gis_render_sm_update( sm_ctx, offscreen_ext_px, 0.5 );
|
||||
update();
|
||||
}
|
||||
|
||||
void MapWidget::setConstScalingMode( bool enabled )
|
||||
{
|
||||
isConstScalingEnabled = enabled;
|
||||
gis_mdp_t disp_param = gis_data_engine_get_display_parameters( data_engine_ctx );
|
||||
gis_mdp_set_scaling_mode( disp_param, isConstScalingEnabled );
|
||||
gis_render_sm_sync( sm_ctx, true );
|
||||
update();
|
||||
}
|
451
src/apps/gis-map-viewer/mapwidget.h
Обычный файл
@ -0,0 +1,451 @@
|
||||
/*
|
||||
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
|
145
src/apps/gis-map-viewer/objectinfo.cpp
Обычный файл
@ -0,0 +1,145 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "objectinfo.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
ObjectInfo::ObjectInfo( gis_render_sm_context_t sm_ctx, QWidget *parent ) :
|
||||
QTreeWidget( parent ),
|
||||
_sm_ctx( sm_ctx ),
|
||||
selectionLine( nullptr )
|
||||
{
|
||||
setColumnCount( 2 );
|
||||
setHeaderHidden( true );
|
||||
setWindowTitle( tr( "Object Info" ) );
|
||||
|
||||
setFixedSize( 400, 120 );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
}
|
||||
|
||||
|
||||
void ObjectInfo::showEvent( QShowEvent *event )
|
||||
{
|
||||
Q_UNUSED( event );
|
||||
emit widgetVisibilityChanged( true );
|
||||
}
|
||||
|
||||
void ObjectInfo::closeEvent( QCloseEvent *event )
|
||||
{
|
||||
Q_UNUSED( event );
|
||||
deleteSelectionLine();
|
||||
emit widgetVisibilityChanged( false );
|
||||
}
|
||||
|
||||
void ObjectInfo::updateInfo( gis_object_t *obj )
|
||||
{
|
||||
fillObjectInfo( obj );
|
||||
addSelectionLine( obj );
|
||||
}
|
||||
|
||||
void ObjectInfo::fillObjectInfo( gis_object_t *obj )
|
||||
{
|
||||
clear();
|
||||
QStringList list;
|
||||
|
||||
list << tr( "Class code:" ) << "0x" + QString::number( obj->class_code, 16 ).toUpper();
|
||||
addTopLevelItem( new QTreeWidgetItem( list ) );
|
||||
list.clear();
|
||||
|
||||
list << tr( "Class acronym:" ) << QString::fromUtf8( obj->class_acronym );
|
||||
addTopLevelItem( new QTreeWidgetItem( list ) );
|
||||
list.clear();
|
||||
|
||||
list << tr( "Type:" ) << QString::fromUtf8( gis_object_primitive_type_get_full_name( obj->type ) );
|
||||
addTopLevelItem( new QTreeWidgetItem( list ) );
|
||||
list.clear();
|
||||
|
||||
if ( obj->has_height )
|
||||
{
|
||||
list << tr( "Height:" ) << QString::number( obj->height );
|
||||
addTopLevelItem( new QTreeWidgetItem( list ) );
|
||||
list.clear();
|
||||
}
|
||||
|
||||
list << tr( "Number of points:" ) << QString::number( obj->point_count );
|
||||
addTopLevelItem( new QTreeWidgetItem( list ) );
|
||||
list.clear();
|
||||
|
||||
if ( strlen( obj->attributes ) )
|
||||
{
|
||||
list << tr( "Attributes:" ) << QString::fromUtf8( obj->attributes );
|
||||
addTopLevelItem( new QTreeWidgetItem( list ) );
|
||||
list.clear();
|
||||
}
|
||||
|
||||
resizeColumnToContents( 0 );
|
||||
resizeColumnToContents( 1 );
|
||||
|
||||
}
|
||||
|
||||
void ObjectInfo::addSelectionLine( gis_object_t *obj )
|
||||
{
|
||||
uint32_t color = 0xF0FF0000;
|
||||
uint32_t pen_width = 3;
|
||||
|
||||
QVector <double_point_t> points;
|
||||
for ( uint32_t i = 0; i < obj->point_count; i++ )
|
||||
{
|
||||
double_point_t tmp;
|
||||
tmp.x = obj->points[i].degrees.x;
|
||||
tmp.y = obj->points[i].degrees.y;
|
||||
points.push_back(tmp);
|
||||
}
|
||||
|
||||
if ( selectionLine )
|
||||
{
|
||||
gis_render_sm_userdata_edit_object_points( _sm_ctx,
|
||||
selectionLine,
|
||||
points.data(),
|
||||
obj->point_count );
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionLine = gis_render_sm_userdata_add_polyline( _sm_ctx,
|
||||
points.data(),
|
||||
obj->point_count,
|
||||
color, pen_width, 1 );
|
||||
}
|
||||
|
||||
gis_render_sm_redraw_userobject( _sm_ctx, true );
|
||||
}
|
||||
|
||||
void ObjectInfo::deleteSelectionLine()
|
||||
{
|
||||
if ( selectionLine )
|
||||
{
|
||||
gis_render_sm_userdata_delete_object( _sm_ctx, selectionLine );
|
||||
selectionLine = nullptr;
|
||||
gis_render_sm_redraw_userobject( _sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
}
|
58
src/apps/gis-map-viewer/objectinfo.h
Обычный файл
@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 OBJECTINFO_H
|
||||
#define OBJECTINFO_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include <gis/gis_objects.h>
|
||||
#include <gis/gis_math.h>
|
||||
#include <gis/gis_surfacemanager.h>
|
||||
|
||||
class ObjectInfo : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ObjectInfo( gis_render_sm_context_t sm_ctx,
|
||||
QWidget *parent = 0 );
|
||||
|
||||
void updateInfo( gis_object_t *obj );
|
||||
|
||||
private:
|
||||
void showEvent( QShowEvent *event );
|
||||
void closeEvent( QCloseEvent *event );
|
||||
|
||||
void fillObjectInfo( gis_object_t *obj );
|
||||
void addSelectionLine( gis_object_t *obj );
|
||||
void deleteSelectionLine();
|
||||
|
||||
|
||||
gis_render_sm_context_t _sm_ctx;
|
||||
gis_userobject_t selectionLine;
|
||||
|
||||
signals:
|
||||
void updateMapWidget();
|
||||
void widgetVisibilityChanged( bool );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
1695
src/apps/gis-map-viewer/objectsearch.cpp
Обычный файл
351
src/apps/gis-map-viewer/objectsearch.h
Обычный файл
@ -0,0 +1,351 @@
|
||||
/*
|
||||
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 OBJECTSEARCH_H
|
||||
#define OBJECTSEARCH_H
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QCompleter>
|
||||
#include <QPushButton>
|
||||
#include <QHeaderView>
|
||||
#include <QTableWidget>
|
||||
#include <QCloseEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QScrollArea>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gisrender.h>
|
||||
#include <gis/gis_objects.h>
|
||||
#include <gis/gis_surfacemanager.h>
|
||||
|
||||
#include "mapwidget.h"
|
||||
#include <mapstylelayerwindow.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t number;
|
||||
uint32_t obj_idx;
|
||||
QString class_acronym;
|
||||
QString attributes;
|
||||
|
||||
} search_result_t;
|
||||
|
||||
|
||||
class FilterLayout : public QGridLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
FilterLayout( QWidget *parent = nullptr );
|
||||
|
||||
QSize getSizeWithWidth();
|
||||
|
||||
void setFilterPosition( int pos );
|
||||
void setMyPosition( int pos );
|
||||
int getFilterPosition();
|
||||
int getMyPosition();
|
||||
|
||||
private:
|
||||
int filter_pos;
|
||||
int my_pos;
|
||||
};
|
||||
|
||||
|
||||
class FilterLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
FilterLabel( QWidget *parent = nullptr );
|
||||
|
||||
void setMyRowLayout( FilterLayout *layout );
|
||||
FilterLayout *getMyRowLayout();
|
||||
|
||||
private:
|
||||
FilterLayout *my_row_layout;
|
||||
};
|
||||
|
||||
|
||||
class ClassAttrConfig : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ClassAttrConfig( QString class_acr,
|
||||
QWidget *parent = nullptr );
|
||||
|
||||
void fillInfoTables( std::map<QString, std::map<QString, QStringList *> *> &class_attr_map );
|
||||
|
||||
private:
|
||||
QString class_acronym;
|
||||
|
||||
QStringList attrFilters;
|
||||
|
||||
QVBoxLayout *vlayout;
|
||||
QHBoxLayout *hlayout;
|
||||
QHBoxLayout *buttons_lay;
|
||||
QWidget *scroll_area_content;
|
||||
QScrollArea *scroll_area;
|
||||
|
||||
QTableWidget *attr_info_table;
|
||||
QStringList attr_info_header;
|
||||
|
||||
QPushButton *accept_btn;
|
||||
QPushButton *cancel_btn;
|
||||
|
||||
const int MIN_WIDTH = 600;
|
||||
const int MAX_HEIGHT = 900;
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
signals:
|
||||
|
||||
void giveAttrFilters( QString class_acr, QStringList attrFilters );
|
||||
|
||||
private slots:
|
||||
|
||||
void takeStoredAttrFilters( QStringList *storedAttrFilters );
|
||||
|
||||
void AddNewAttrFilter( int row );
|
||||
|
||||
void closeAndSave();
|
||||
|
||||
};
|
||||
|
||||
class WhereToSearchComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum Where
|
||||
{
|
||||
ON_SHOWN_MAPS,
|
||||
ON_ALL_MAPS
|
||||
};
|
||||
|
||||
WhereToSearchComboBox( QWidget *parent = nullptr ) : QComboBox( parent )
|
||||
{
|
||||
this->setEditable( false );
|
||||
this->setDuplicatesEnabled( false );
|
||||
this->setMaxCount( 2 );
|
||||
this->addItems( { tr( "On shown maps" ), tr( "On all maps" ) } );
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectSearch : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ObjectSearch( QWidget *parent = nullptr );
|
||||
~ObjectSearch();
|
||||
|
||||
void setCurrentTab( MapWidget *wgt );
|
||||
|
||||
MapWidget* getCurrentTab();
|
||||
|
||||
void updateLists( std::vector<ClassifierInfo> &classifier_list );
|
||||
|
||||
private:
|
||||
|
||||
QPointer<MapWidget> currentMapWidget;
|
||||
|
||||
QPointer<ClassAttrConfig> configWindow;
|
||||
|
||||
QStringList classAcronymList;
|
||||
QStringList classifiersList;
|
||||
QStringList searchResultsHeader;
|
||||
GisObjectList *ptr_gis_obj_list;
|
||||
|
||||
|
||||
QVBoxLayout *vlayout;
|
||||
QHBoxLayout *hlayout;
|
||||
QHBoxLayout *classifier_layout;
|
||||
QHBoxLayout *wts_layout;
|
||||
QHBoxLayout *class_key_layout;
|
||||
QHBoxLayout *key_layout;
|
||||
QVBoxLayout *tool_layout;
|
||||
QVBoxLayout *all_filters_layout;
|
||||
QWidget *scroll_area_content;
|
||||
QScrollArea *scroll_area;
|
||||
QVBoxLayout *scroll_with_btns;
|
||||
QSpacerItem *horizontal_spacer;
|
||||
FilterLayout *filter_layout;
|
||||
QList<FilterLayout *> filter_lays_list;
|
||||
QList<FilterLabel *> filter_label_list;
|
||||
QComboBox *classifier_combobox;
|
||||
QLineEdit *key_string;
|
||||
QLineEdit *class_key_string;
|
||||
QList<QTableWidgetItem *> cells_blocked;
|
||||
QStringList class_search_header;
|
||||
QTableWidget *class_search_table;
|
||||
QTableWidget *search_results;
|
||||
|
||||
WhereToSearchComboBox *wts_combobox;
|
||||
|
||||
QPushButton *attr_filter_btn;
|
||||
|
||||
QPushButton *stop_btn;
|
||||
QLabel *status_lbl;
|
||||
|
||||
gis_borders_t borders;
|
||||
MapStyleLayerContainer *ptr_layer_container;
|
||||
bool search_stopped;
|
||||
|
||||
bool search_stopped_by_button;
|
||||
bool configure_btn_pressed;
|
||||
int filter_pos;
|
||||
|
||||
static QString ALL_STR;
|
||||
|
||||
const int MIN_WIDTH = 640;
|
||||
const int MAX_HEIGHT = 900;
|
||||
|
||||
const int SA_FIXED_WIDTH = 320;
|
||||
|
||||
const int SPACER_WIDTH = 1;
|
||||
const int MARGIN = 10;
|
||||
|
||||
|
||||
std::vector<ClassifierInfo> all_classifiers_info;
|
||||
|
||||
std::map<int32_t, std::vector<gis_core_class_info_t> *> all_classes_info_map;
|
||||
|
||||
std::vector<search_result_t> internalSearchResults;
|
||||
|
||||
std::vector<search_result_t> attrFilteredSearchResults;
|
||||
|
||||
std::map<QString, std::map<QString, QStringList *> *> class_attr_map;
|
||||
|
||||
std::map<QString, QStringList *> stored_filters_map;
|
||||
|
||||
template<typename T1,typename T2>
|
||||
void clearMapWithPointers( std::map<T1, T2 *> &map )
|
||||
{
|
||||
for ( auto &pair : map )
|
||||
{
|
||||
delete pair.second;
|
||||
}
|
||||
map.clear();
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
void eraseFromMapWithPointers( std::map<T1, T2 *> &map,
|
||||
std::_Rb_tree_iterator<std::pair<const T1, T2 *>> &pair )
|
||||
{
|
||||
delete pair->second;
|
||||
map.erase( pair );
|
||||
}
|
||||
|
||||
void enableWidgets();
|
||||
void disableWidgets();
|
||||
|
||||
void clearSearchData_SOFT();
|
||||
|
||||
void clearSearchData_HARD();
|
||||
|
||||
QString wrapToQStringUTF8( const char *string );
|
||||
|
||||
void addToClassAttrMap( search_result_t search_result );
|
||||
|
||||
void clearFromClassAttrMap( QString class_acr );
|
||||
|
||||
void clearFromStoredFiltersMap( QString class_acr );
|
||||
|
||||
void drawResTableRow( search_result_t res_item );
|
||||
|
||||
bool updateBorders();
|
||||
|
||||
gis_core_map_data_source_t getClassifierMapSource( const ClassifierInfo &classifier );
|
||||
|
||||
bool checkObjFormat( gis_object_t &obj,
|
||||
int32_t classifier_idx,
|
||||
const std::vector<gis_core_class_info_t> &classes,
|
||||
gis_core_map_data_source_t format );
|
||||
|
||||
void searchInfoForLabel( QString class_acr );
|
||||
|
||||
void clearClassInfoFromResTable( QString class_acr );
|
||||
|
||||
void addInfoToResultTable( char *all_attributes_of_object,
|
||||
char* class_acronym,
|
||||
uint32_t idx );
|
||||
|
||||
void deleteFilterLabel( FilterLabel *label );
|
||||
|
||||
void mousePressEvent( QMouseEvent *event );
|
||||
|
||||
void showClassAttrConfig( FilterLabel *label );
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
void closeEvent( QCloseEvent *event );
|
||||
|
||||
signals:
|
||||
|
||||
void giveStoredAttrFilters( QStringList *storedAttrFilters );
|
||||
|
||||
void centerAtObject( double_point_t object_center );
|
||||
|
||||
void showInfoForFoundObject( gis_object_t current_object );
|
||||
|
||||
private slots:
|
||||
|
||||
void searchInfoForCurrentLabels();
|
||||
|
||||
void resizeResultTable();
|
||||
|
||||
void updateResultTable( QString key );
|
||||
|
||||
void stopSearch();
|
||||
|
||||
void configureAttr();
|
||||
|
||||
void rejectConfigureAttr();
|
||||
|
||||
void target_to_object( int row );
|
||||
|
||||
void fillClassesInfoMap( const ClassifierInfo &classifier );
|
||||
|
||||
void fillClassesAcrList( const ClassifierInfo &classifier );
|
||||
|
||||
void updateListsForClassifier( int classifier_combobox_idx );
|
||||
|
||||
void addNewFilterLabel( int row );
|
||||
|
||||
void searchClassTable( QString search_key );
|
||||
|
||||
void takeAttrFilters( QString class_acr, QStringList attrFilters );
|
||||
};
|
||||
|
||||
#endif
|
12
src/apps/gis-map-viewer/resources.qrc
Обычный файл
@ -0,0 +1,12 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/zoomin50.png</file>
|
||||
<file>icons/zoomout50.png</file>
|
||||
<file>icons/shutdown.png</file>
|
||||
<file>icons/ruler.png</file>
|
||||
<file>icons/pin.png</file>
|
||||
<file>icons/save_pin.png</file>
|
||||
<file>icons/swd_logo.png</file>
|
||||
<file>icons/undo.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
6
src/apps/gis-map-viewer/translations.qrc
Обычный файл
@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>translations/gis-map-viewer_ru.ts</file>
|
||||
<file>translations/gis-map-viewer_ru.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
571
src/apps/gis-map-viewer/translations/gis-map-viewer_ru.ts
Обычный файл
@ -0,0 +1,571 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="ru_RU">
|
||||
<context>
|
||||
<name>ClassAttrConfig</name>
|
||||
<message>
|
||||
<source>Class attributes filter</source>
|
||||
<translation>Фильтр атрибутов класса</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Accept</source>
|
||||
<translation>Применить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel</source>
|
||||
<translation>Отмена</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DepthEditor</name>
|
||||
<message>
|
||||
<source>Depth Editor</source>
|
||||
<translation>Редактор Глубин</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Safety Depth</source>
|
||||
<translation>Безопасная глубина</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Shallow Contour</source>
|
||||
<translation>Контур мелководья</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Safety Contour</source>
|
||||
<translation>Контур безопасной глубины</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Deep Contour</source>
|
||||
<translation>Контур большой глубины</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Two Color Depth</source>
|
||||
<translation>Два цвета области глубины</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Shallow Pattern</source>
|
||||
<translation>Выделить мелководье</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Accept</source>
|
||||
<translation>Применить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel</source>
|
||||
<translation>Отмена</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DistanceMeter</name>
|
||||
<message>
|
||||
<source>Distance (km):</source>
|
||||
<translation>Расстояние (км)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Area (sq km):</source>
|
||||
<translation>Площадь (кв. км):</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add </source>
|
||||
<translation>Добавить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete</source>
|
||||
<translation>Удалить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reset</source>
|
||||
<translation>Сброс</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Meter</source>
|
||||
<translation>Измеритель</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>lat:</source>
|
||||
<translation>ш:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source> lon:</source>
|
||||
<translation> д:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HeightScale</name>
|
||||
<message>
|
||||
<source>Min: </source>
|
||||
<translation>Мин: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Max: </source>
|
||||
<translation>Макс: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set</source>
|
||||
<translation>Установить</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LayerWindow</name>
|
||||
<message>
|
||||
<source>User objects</source>
|
||||
<translation>Польз. объекты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Raster maps</source>
|
||||
<translation>Растровые карты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Vector maps</source>
|
||||
<translation>Векторные карты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Surfaces and data formats</source>
|
||||
<translation>Поверхности и форматы карт</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<source>Map Viewer</source>
|
||||
<translation>Средство просмотра</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Center at cursor</source>
|
||||
<translation>Центр по курсору</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Main</source>
|
||||
<translation>Меню</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show only one map</source>
|
||||
<translation>Показывать одну карту</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>About</source>
|
||||
<translation>О программе</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Exit</source>
|
||||
<translation>Выход</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>View parameters</source>
|
||||
<translation>Вид</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Projections</source>
|
||||
<translation>Проекции</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Screen parameters</source>
|
||||
<translation>Параметры экрана</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Layers</source>
|
||||
<translation>Слои</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Brighntess / Contrast</source>
|
||||
<translation>Яркость/Констрастность</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New scaling mode</source>
|
||||
<translation>Чертёжный режим</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Aliasing</source>
|
||||
<translation>Сглаживание</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Scale by scroll</source>
|
||||
<translation>Масштабирование колёсиком мыши</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Vector</source>
|
||||
<translation>Вектор</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Palette</source>
|
||||
<translation>Палитра</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Language</source>
|
||||
<translation>Язык</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Format features</source>
|
||||
<translation>Особые настройки формата</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Raster</source>
|
||||
<translation>Растр</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Raster scale</source>
|
||||
<translation>Шкала высот</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Auto height mode</source>
|
||||
<translation>Автограницы высот</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show out of limits height</source>
|
||||
<translation>Показать высоты вне диапазона</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Discrete palette</source>
|
||||
<translation>Дискретная палитра</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Tools</source>
|
||||
<translation>Инструменты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Refresh</source>
|
||||
<translation>Обновить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>User objects</source>
|
||||
<translation>Польз. объекты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map ruler</source>
|
||||
<translation>Измеритель</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search</source>
|
||||
<translation>Поиск</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Depth editor</source>
|
||||
<translation>Редактор Глубин</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>National language</source>
|
||||
<translation>Национальный язык</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Filters</source>
|
||||
<translation>Фильтры</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map style layers</source>
|
||||
<translation>Слои классификатора</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Type of primitive</source>
|
||||
<translation>Тип примитива</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map type</source>
|
||||
<translation>Тип карты</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MapStyleLayerWindow</name>
|
||||
<message>
|
||||
<source>State</source>
|
||||
<translation>Состояние</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Layer name</source>
|
||||
<translation>Имя слоя</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Layer number</source>
|
||||
<translation>Номер слоя</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sequence number</source>
|
||||
<translation>Последовательный номер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select All</source>
|
||||
<translation>Выбрать все</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove All</source>
|
||||
<translation>Снять все</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Classifier name: </source>
|
||||
<translation>Классификатор: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Classifier layer management</source>
|
||||
<translation>Управление слоями классификатора</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MapWidget</name>
|
||||
<message>
|
||||
<source>Save screen position</source>
|
||||
<translation>Сохранить позицию на карте</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source> Lat: </source>
|
||||
<translation> Ш: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source> Long: </source>
|
||||
<translation> Д: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete screen position</source>
|
||||
<translation>Удалить сохраненную позицию</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ObjectInfo</name>
|
||||
<message>
|
||||
<source>Object Info</source>
|
||||
<translation>Сведения об объекте</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class code:</source>
|
||||
<translation>Код класса:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class acronym:</source>
|
||||
<translation>Акроним:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Type:</source>
|
||||
<translation>Тип:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Height:</source>
|
||||
<translation>Высота:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Number of points:</source>
|
||||
<translation>Кол-во точек:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Attributes:</source>
|
||||
<translation>Атрибуты:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ObjectSearch</name>
|
||||
<message>
|
||||
<source>Search objects</source>
|
||||
<translation>Поиск объектов</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Classifier:</source>
|
||||
<translation>Классификатор:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search class:</source>
|
||||
<translation>Поиск класса</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search attribute:</source>
|
||||
<translation>Поиск атрибута</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop Searching</source>
|
||||
<translation>Остановить поиск</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Configure class attributes</source>
|
||||
<translation>Выбрать атрибуты класса</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Objects found: 0</source>
|
||||
<translation>Найдено объектов: 0</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class</source>
|
||||
<translation>Класс</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Attributes</source>
|
||||
<translation>Атрибуты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class Filter</source>
|
||||
<translation>Фильтр по классам</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You must stop searching before exiting!</source>
|
||||
<translation>Вы должны остановить поиск перед выходом!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error</source>
|
||||
<translation>Ошибка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop the current search or wait for it to complete.</source>
|
||||
<translation>Остановите текущий поиск или дождитесь его завершения.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Warning</source>
|
||||
<translation>Предупреждение</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel</source>
|
||||
<translation>Отмена</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Searching...</source>
|
||||
<translation>Поиск...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Objects found: %1</source>
|
||||
<translation>Найдено объектов: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Where to search:</source>
|
||||
<translation>Где искать:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>All</source>
|
||||
<translation>Все</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>UserDialog</name>
|
||||
<message>
|
||||
<source>Dialog</source>
|
||||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Color</source>
|
||||
<translation>Цвет</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R:</source>
|
||||
<translation>R:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>0</source>
|
||||
<translation>0</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>G:</source>
|
||||
<translation>G:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>B:</source>
|
||||
<translation>B:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>A:</source>
|
||||
<translation>A:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>254</source>
|
||||
<translation>254</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Border Color</source>
|
||||
<translation>Цвет границы</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Line Width</source>
|
||||
<translation>Толщина линии</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pixels: </source>
|
||||
<translation>Пикселей:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Coordinates</source>
|
||||
<translation>Координаты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Longitude (x):</source>
|
||||
<translation>Долгота (х):</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Latitude (y): </source>
|
||||
<translation>Широта (у): </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add point</source>
|
||||
<translation>Добавить точку</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear list</source>
|
||||
<translation>Очистить список</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Object type</source>
|
||||
<translation>Тип объекта</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Po&lygon</source>
|
||||
<translation>Полигон</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pol&yline</source>
|
||||
<translation>Полилиния</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bit&map</source>
|
||||
<translation>Картинка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add object</source>
|
||||
<translation>Добавить объект</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>User Objects</source>
|
||||
<translation>Польз. объекты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>( </source>
|
||||
<translation>( </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>; </source>
|
||||
<translation>; </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source> )</source>
|
||||
<translation> )</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Additional Settings</source>
|
||||
<translation>Доп. настройки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Scale bitmap</source>
|
||||
<translation>Масштабировать картинку</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove All</source>
|
||||
<translation>Удалить все</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ViewParameters</name>
|
||||
<message>
|
||||
<source>Brightness</source>
|
||||
<translation>Яркость</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Contrast</source>
|
||||
<translation>Контрастность</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Brightness/Contrast</source>
|
||||
<translation>Яркость/Контрастность</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WhereToSearchComboBox</name>
|
||||
<message>
|
||||
<source>On shown maps</source>
|
||||
<translation>Отображенные карты</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>On all maps</source>
|
||||
<translation>Все карты</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
354
src/apps/gis-map-viewer/userdialog.cpp
Обычный файл
@ -0,0 +1,354 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "userdialog.h"
|
||||
#include "ui_userdialog.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
UserDialog::UserDialog( gis_render_sm_context_t external_sm_ctx,
|
||||
gis_mdp_t external_mdp_ctx,
|
||||
QVector<int> scale_vals,
|
||||
QWidget *parent) :
|
||||
QMainWindow( parent ),
|
||||
ui( new Ui::UserDialog ),
|
||||
sm_ctx( external_sm_ctx ),
|
||||
disp_param( external_mdp_ctx ),
|
||||
scales_v( scale_vals )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
setWindowTitle( tr( "User Objects" ) );
|
||||
|
||||
crutch_spacer = new QSpacerItem( 1, 158, QSizePolicy::Minimum, QSizePolicy::Minimum );
|
||||
|
||||
color = 0x8000FF00;
|
||||
|
||||
connect( ui->addObjectButton, SIGNAL( pressed() ),
|
||||
this, SLOT( addObject() ) );
|
||||
connect( ui->undoButton, SIGNAL( pressed() ),
|
||||
this, SLOT( removeLast() ) );
|
||||
connect( ui->removeAllButton, SIGNAL( pressed() ),
|
||||
this, SLOT( removeAll() ) );
|
||||
connect( ui->addPointBtn, SIGNAL( pressed() ),
|
||||
this, SLOT( addPoint() ) );
|
||||
connect( ui->clearPointList, SIGNAL( pressed() ),
|
||||
this, SLOT( slotEraseList() ) );
|
||||
|
||||
ui->PolygonButton->setChecked( true );
|
||||
v = new QIntValidator( 0, 255 );
|
||||
ui->redEdit->setValidator( v );
|
||||
ui->greenEdit->setValidator( v );
|
||||
ui->blueEdit->setValidator( v );
|
||||
ui->alphaEdit->setValidator( v );
|
||||
ui->redEdit_2->setValidator( v );
|
||||
ui->greenEdit_2->setValidator( v );
|
||||
ui->blueEdit_2->setValidator( v );
|
||||
ui->alphaEdit_2->setValidator( v );
|
||||
|
||||
ui->alphaEdit->setText( "255" );
|
||||
ui->alphaEdit_2->setText( "255" );
|
||||
|
||||
ui->cb_scaleBitmap->setChecked( true );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
}
|
||||
|
||||
UserDialog::~UserDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void UserDialog::showEvent( QShowEvent *event )
|
||||
{
|
||||
emit widgetVisibilityChanged( true );
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void UserDialog::closeEvent( QCloseEvent *event )
|
||||
{
|
||||
deleteContourData();
|
||||
emit widgetVisibilityChanged( false );
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void UserDialog::setColor()
|
||||
{
|
||||
color = ( ui->alphaEdit->text().toUInt() << 24 )
|
||||
+ ( ui->redEdit->text().toUInt() << 16 )
|
||||
+ ( ui->greenEdit->text().toUInt() << 8 )
|
||||
+ ( ui->blueEdit->text().toUInt() );
|
||||
|
||||
}
|
||||
|
||||
void UserDialog::setBorderColor()
|
||||
{
|
||||
border_color = ( ui->alphaEdit_2 ->text().toUInt() << 24 )
|
||||
+ ( ui->redEdit_2->text().toUInt() << 16 )
|
||||
+ ( ui->greenEdit_2->text().toUInt() << 8 )
|
||||
+ ( ui->blueEdit_2->text().toUInt() );
|
||||
|
||||
}
|
||||
|
||||
void UserDialog::setPenWidth()
|
||||
{
|
||||
pen_width = ui->lineWidthEdit->text().toInt();
|
||||
}
|
||||
|
||||
void UserDialog::addPoint()
|
||||
{
|
||||
point.x = ui->longitudeSpinBox->value();
|
||||
point.y = ui->latitudeSpinBox->value();
|
||||
|
||||
QString str;
|
||||
str = tr("( ") + ui->longitudeSpinBox->text() + tr("; ") +
|
||||
ui->latitudeSpinBox->text() + tr(" )");
|
||||
ui->pointList->addItem( str );
|
||||
obj_points.append( point );
|
||||
|
||||
uint32_t contour_color = 0xF0FF0000;
|
||||
uint32_t contour_pen_width = 5;
|
||||
|
||||
gis_userobject_t contour_obj = gis_render_sm_userdata_add_contour_object( sm_ctx,
|
||||
obj_points.data(),
|
||||
obj_points.size(),
|
||||
contour_color,
|
||||
contour_pen_width );
|
||||
|
||||
u_contour_v.push_back( contour_obj );
|
||||
|
||||
gis_render_sm_redraw_userobject( sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
void UserDialog::userObjListener( QPoint pos )
|
||||
{
|
||||
double_point_t degree_pnt;
|
||||
int32_point_t px_pos = { pos.x(), pos.y() };
|
||||
gis_render_sm_convert_px2degree( sm_ctx, px_pos, °ree_pnt );
|
||||
|
||||
ui->longitudeSpinBox->setValue( degree_pnt.x );
|
||||
ui->latitudeSpinBox->setValue( degree_pnt.y );
|
||||
}
|
||||
|
||||
void UserDialog::deleteObjectsData()
|
||||
{
|
||||
if ( u_objects_v.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( auto obj : u_objects_v )
|
||||
{
|
||||
gis_render_sm_userdata_delete_object( sm_ctx, obj );
|
||||
}
|
||||
|
||||
u_objects_v.clear();
|
||||
}
|
||||
|
||||
void UserDialog::deleteContourData()
|
||||
{
|
||||
if ( u_contour_v.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( auto obj : u_contour_v )
|
||||
{
|
||||
gis_render_sm_userdata_delete_contour_object( sm_ctx, obj );
|
||||
}
|
||||
|
||||
u_contour_v.clear();
|
||||
}
|
||||
|
||||
void UserDialog::slotEraseList()
|
||||
{
|
||||
ui->pointList->clear();
|
||||
obj_points.clear();
|
||||
|
||||
deleteContourData();
|
||||
gis_render_sm_redraw_userobject( sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
void UserDialog::addObject()
|
||||
{
|
||||
setColor();
|
||||
setBorderColor();
|
||||
setPenWidth();
|
||||
|
||||
if ( ui->PolylineButton->isChecked() )
|
||||
{
|
||||
addPolyline();
|
||||
}
|
||||
else if ( ui->PolygonButton->isChecked() )
|
||||
{
|
||||
addPolygon();
|
||||
}
|
||||
else if ( ui->BitmapButton->isChecked() )
|
||||
{
|
||||
addImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "toggled to unknown radio btn";
|
||||
return;
|
||||
}
|
||||
|
||||
slotEraseList();
|
||||
}
|
||||
|
||||
void UserDialog::removeLast()
|
||||
{
|
||||
if ( !u_contour_v.empty() )
|
||||
{
|
||||
ui->pointList->takeItem( ui->pointList->count() - 1 );
|
||||
gis_render_sm_userdata_delete_contour_object( sm_ctx, u_contour_v.back() );
|
||||
u_contour_v.pop_back();
|
||||
}
|
||||
else if ( !u_objects_v.empty() )
|
||||
{
|
||||
gis_render_sm_userdata_delete_object( sm_ctx, u_objects_v.back() );
|
||||
u_objects_v.pop_back();
|
||||
}
|
||||
gis_render_sm_redraw_userobject( sm_ctx, true );
|
||||
emit updateMapWidget();
|
||||
}
|
||||
|
||||
void UserDialog::removeAll()
|
||||
{
|
||||
deleteObjectsData();
|
||||
slotEraseList();
|
||||
}
|
||||
|
||||
void UserDialog::on_PolygonButton_toggled( bool checked )
|
||||
{
|
||||
if ( checked )
|
||||
{
|
||||
ui->widthBox_5->hide();
|
||||
ui->cb_scaleBitmap->hide();
|
||||
|
||||
ui->mainLayout->removeItem( crutch_spacer );
|
||||
|
||||
ui->colorBox->show();
|
||||
ui->borderColorBox->show();
|
||||
}
|
||||
}
|
||||
|
||||
void UserDialog::on_PolylineButton_toggled( bool checked )
|
||||
{
|
||||
if ( checked )
|
||||
{
|
||||
ui->borderColorBox->hide();
|
||||
ui->cb_scaleBitmap->hide();
|
||||
|
||||
ui->mainLayout->removeItem( crutch_spacer );
|
||||
|
||||
ui->colorBox->show();
|
||||
ui->widthBox_5->show();
|
||||
}
|
||||
}
|
||||
|
||||
void UserDialog::on_BitmapButton_toggled( bool checked )
|
||||
{
|
||||
if ( checked )
|
||||
{
|
||||
ui->mainLayout->insertItem( 0, crutch_spacer );
|
||||
|
||||
ui->borderColorBox->hide();
|
||||
ui->widthBox_5->hide();
|
||||
ui->colorBox->hide();
|
||||
ui->cb_scaleBitmap->show();
|
||||
}
|
||||
}
|
||||
|
||||
void UserDialog::addPolyline()
|
||||
{
|
||||
obj = gis_render_sm_userdata_add_polyline( sm_ctx,
|
||||
obj_points.data(),
|
||||
obj_points.size(),
|
||||
color,
|
||||
pen_width, 0 );
|
||||
|
||||
u_objects_v.push_back( obj );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void UserDialog::addPolygon()
|
||||
{
|
||||
obj = gis_render_sm_userdata_add_polygon( sm_ctx,
|
||||
obj_points.data(),
|
||||
obj_points.size(),
|
||||
color,
|
||||
border_color );
|
||||
|
||||
u_objects_v.push_back( obj );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void UserDialog::addImage()
|
||||
{
|
||||
if ( ui->cb_scaleBitmap->isChecked() )
|
||||
{
|
||||
int max_scale = scales_v.back();
|
||||
double scale_factor = (double)( gis_mdp_get_phys_scale( disp_param ) ) / max_scale;
|
||||
|
||||
QPixmap tmp_img( ":/icons/swd_logo.png" );
|
||||
|
||||
int scaled_width = tmp_img.width() * scale_factor;
|
||||
|
||||
image = new QPixmap( tmp_img.scaledToWidth( scaled_width ) );
|
||||
|
||||
if( image->isNull() )
|
||||
{
|
||||
int scaled_height = tmp_img.height() * scale_factor;
|
||||
qDebug() << "Can't create QPixmap (width =" << scaled_width << " height =" << scaled_height << ")";
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image = new QPixmap( ":/icons/swd_logo.png" );
|
||||
|
||||
if( image->isNull() )
|
||||
{
|
||||
qDebug() << "Can't create QPixmap from standart image!";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
obj = gis_render_sm_userdata_add_bitmap( sm_ctx,
|
||||
obj_points.data(),
|
||||
obj_points.size(),
|
||||
image );
|
||||
|
||||
u_objects_v.push_back( obj );
|
||||
|
||||
return;
|
||||
}
|
101
src/apps/gis-map-viewer/userdialog.h
Обычный файл
@ -0,0 +1,101 @@
|
||||
/*
|
||||
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 USERDIALOG_H
|
||||
#define USERDIALOG_H
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QMainWindow>
|
||||
#include <QValidator>
|
||||
#include <QSpacerItem>
|
||||
|
||||
#include <gis/gis_math.h>
|
||||
#include <gis/gis_surfacemanager.h>
|
||||
|
||||
namespace Ui {
|
||||
class UserDialog;
|
||||
}
|
||||
|
||||
class UserDialog : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UserDialog( gis_render_sm_context_t external_sm_ctx,
|
||||
gis_mdp_t external_mdp_ctx,
|
||||
QVector<int> scale_vals,
|
||||
QWidget *parent = 0 );
|
||||
~UserDialog();
|
||||
|
||||
void addPolyline();
|
||||
void addPolygon();
|
||||
void addImage();
|
||||
uint32_t getFillColor() { return color; }
|
||||
uint32_t getBorderColor() { return border_color; }
|
||||
uint32_t getPenWidth() { return pen_width; }
|
||||
|
||||
QVector <double_point_t> obj_points;
|
||||
QPixmap *image;
|
||||
|
||||
private:
|
||||
Ui::UserDialog *ui;
|
||||
uint32_t color;
|
||||
uint32_t border_color;
|
||||
QValidator *v;
|
||||
uint32_t pen_width;
|
||||
gis_userobject_t obj;
|
||||
gis_render_sm_context_t sm_ctx;
|
||||
gis_mdp_t disp_param;
|
||||
double_point_t point;
|
||||
|
||||
QVector<int> scales_v;
|
||||
|
||||
QSpacerItem *crutch_spacer;
|
||||
|
||||
std::vector<gis_userobject_t> u_objects_v;
|
||||
std::vector<gis_userobject_t> u_contour_v;
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
void closeEvent( QCloseEvent *event );
|
||||
|
||||
void deleteContourData();
|
||||
void deleteObjectsData();
|
||||
|
||||
private slots:
|
||||
void setColor();
|
||||
void setBorderColor();
|
||||
void setPenWidth();
|
||||
void addPoint();
|
||||
void userObjListener( QPoint pos );
|
||||
void addObject();
|
||||
void removeAll();
|
||||
void removeLast();
|
||||
void slotEraseList();
|
||||
void on_PolygonButton_toggled( bool checked );
|
||||
void on_PolylineButton_toggled( bool checked );
|
||||
void on_BitmapButton_toggled( bool checked );
|
||||
|
||||
signals:
|
||||
void updateMapWidget();
|
||||
void widgetVisibilityChanged( bool );
|
||||
};
|
||||
|
||||
#endif
|
761
src/apps/gis-map-viewer/userdialog.ui
Обычный файл
@ -0,0 +1,761 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UserDialog</class>
|
||||
<widget class="QMainWindow" name="UserDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>332</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>332</width>
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>332</width>
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>332</width>
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>0</y>
|
||||
<width>312</width>
|
||||
<height>591</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="mainLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="colorBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>291</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>R:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="redEdit">
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhNone</set>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>G:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="greenEdit">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>B:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="blueEdit">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>A:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="alphaEdit">
|
||||
<property name="text">
|
||||
<string>254</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="borderColorBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Border Color</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>291</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>R:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="redEdit_2">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>G:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="greenEdit_2">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>B:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="blueEdit_2">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>A:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="alphaEdit_2">
|
||||
<property name="text">
|
||||
<string>254</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="widthBox_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Line Width</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>292</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Pixels: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineWidthEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="coordinatesBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Coordinates</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>291</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Longitude (x):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="longitudeSpinBox">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>291</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Latitude (y): </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="latitudeSpinBox">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-90.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>90.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>90</y>
|
||||
<width>291</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="1,1">
|
||||
<item>
|
||||
<widget class="QListWidget" name="pointList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0,1">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addPointBtn">
|
||||
<property name="text">
|
||||
<string>Add point</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearPointList">
|
||||
<property name="text">
|
||||
<string>Clear list</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>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="objectTypeBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Object type</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>291</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="PolygonButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Po&lygon</string>
|
||||
</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>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="PolylineButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pol&yline</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>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="BitmapButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bit&map</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="additionalSettingsBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Additional Settings</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>11</x>
|
||||
<y>19</y>
|
||||
<width>291</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cb_scaleBitmap">
|
||||
<property name="text">
|
||||
<string>Scale bitmap</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<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>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10" stretch="0,1">
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addObjectButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add object</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="undoButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/icons/undo.png</normaloff>:/icons/undo.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeAllButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>310</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">
|
||||
QPushButton {
|
||||
background-color: qradialgradient( cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #FFFFFF, stop: 1 #ad2c23);
|
||||
color: rgb( 0, 0, 0 );
|
||||
border-radius: 2px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: rgb( 162, 162, 162 );
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
background-color: #ad463e;
|
||||
}
|
||||
|
||||
QPushButton:pressed {
|
||||
background-color: #b37c78;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>redEdit</tabstop>
|
||||
<tabstop>greenEdit</tabstop>
|
||||
<tabstop>blueEdit</tabstop>
|
||||
<tabstop>alphaEdit</tabstop>
|
||||
<tabstop>redEdit_2</tabstop>
|
||||
<tabstop>greenEdit_2</tabstop>
|
||||
<tabstop>blueEdit_2</tabstop>
|
||||
<tabstop>alphaEdit_2</tabstop>
|
||||
<tabstop>lineWidthEdit</tabstop>
|
||||
<tabstop>longitudeSpinBox</tabstop>
|
||||
<tabstop>latitudeSpinBox</tabstop>
|
||||
<tabstop>addPointBtn</tabstop>
|
||||
<tabstop>PolylineButton</tabstop>
|
||||
<tabstop>BitmapButton</tabstop>
|
||||
<tabstop>pointList</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
167
src/apps/gis-map-viewer/viewparameters.cpp
Обычный файл
@ -0,0 +1,167 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "viewparameters.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
void ViewSlider::init( int interval )
|
||||
{
|
||||
setRange( m_range_min, m_range_max );
|
||||
setTickPosition( QSlider::TicksBelow );
|
||||
setTracking( false );
|
||||
|
||||
m_interval = abs( interval );
|
||||
setTickInterval( interval );
|
||||
setPageStep( interval );
|
||||
}
|
||||
|
||||
ViewSlider::ViewSlider( int interval, QWidget *parent, int range_min, int range_max )
|
||||
: QSlider( parent ), m_range_min( range_min ), m_range_max( range_max )
|
||||
{
|
||||
init( interval );
|
||||
}
|
||||
|
||||
ViewSlider::ViewSlider( int interval, Qt::Orientation orientation, QWidget *parent, int range_min, int range_max )
|
||||
: QSlider( orientation, parent ), m_range_min( range_min ), m_range_max( range_max )
|
||||
{
|
||||
init( interval );
|
||||
}
|
||||
|
||||
void ViewSlider::updateTickValuesDisplay( QHBoxLayout *layout, size_t &tick_value_width )
|
||||
{
|
||||
QFont f( "monospace", 10 );
|
||||
QLabel value_label;
|
||||
size_t standart_w = 0;
|
||||
|
||||
int tick_count = (int)( abs( m_range_max - m_range_min ) / (float)m_interval + 0.5 ) + 1;
|
||||
|
||||
QLabel *last_value_label = new QLabel( QString::number( ( tick_count - 1 ) * m_interval ) );
|
||||
last_value_label->setFont( f );
|
||||
last_value_label->setAlignment( Qt::AlignCenter );
|
||||
last_value_label->adjustSize();
|
||||
last_value_label->setFixedSize( last_value_label->size() );
|
||||
standart_w = last_value_label->size().width();
|
||||
tick_value_width = standart_w;
|
||||
|
||||
for ( int i = 0; i < tick_count - 1; ++i )
|
||||
{
|
||||
QLabel *value_label = new QLabel( QString::number( i * m_interval ) );
|
||||
value_label->setFont( f );
|
||||
value_label->setAlignment( Qt::AlignCenter );
|
||||
value_label->setFixedWidth( standart_w );
|
||||
layout->addWidget( value_label );
|
||||
layout->insertStretch( -1,1 );
|
||||
}
|
||||
|
||||
layout->addWidget( last_value_label );
|
||||
}
|
||||
|
||||
|
||||
ViewParameters::ViewParameters( QWidget *parent ) : QWidget( parent, Qt::Window )
|
||||
{
|
||||
QGridLayout *main_lay = new QGridLayout();
|
||||
brightness_slider = new ViewSlider( 10, Qt::Horizontal, this, 0, 100 );
|
||||
contrast_slider = new ViewSlider( 10, Qt::Horizontal, this, 0, 100 );
|
||||
|
||||
br_slider_tick_val_hlay = new QHBoxLayout();
|
||||
cn_slider_tick_val_hlay = new QHBoxLayout();
|
||||
|
||||
QLabel *br_label = new QLabel( tr( "Brightness" ), this );
|
||||
QLabel *cn_label = new QLabel( tr( "Contrast" ), this );
|
||||
|
||||
size_t tick_value_width = 0;
|
||||
|
||||
brightness_slider->updateTickValuesDisplay( br_slider_tick_val_hlay, tick_value_width );
|
||||
|
||||
tick_value_width = tick_value_width / 2 - 5;
|
||||
|
||||
br_slider_hlay = new QHBoxLayout();
|
||||
br_slider_hlay->addSpacerItem( new QSpacerItem( tick_value_width, 0, QSizePolicy::Fixed, QSizePolicy::Minimum ) );
|
||||
br_slider_hlay->addWidget( brightness_slider );
|
||||
br_slider_hlay->addSpacerItem( new QSpacerItem( tick_value_width, 0, QSizePolicy::Fixed, QSizePolicy::Minimum ) );
|
||||
|
||||
contrast_slider->updateTickValuesDisplay( cn_slider_tick_val_hlay, tick_value_width );
|
||||
|
||||
tick_value_width = tick_value_width / 2 - 5;
|
||||
|
||||
cn_slider_hlay = new QHBoxLayout();
|
||||
cn_slider_hlay->addSpacerItem( new QSpacerItem( tick_value_width, 0, QSizePolicy::Fixed, QSizePolicy::Minimum ) );
|
||||
cn_slider_hlay->addWidget( contrast_slider );
|
||||
cn_slider_hlay->addSpacerItem( new QSpacerItem( tick_value_width, 0, QSizePolicy::Fixed, QSizePolicy::Minimum ) );
|
||||
|
||||
main_lay->addWidget( br_label, 0, 1 );
|
||||
main_lay->addLayout( br_slider_hlay, 1, 1, 1, 2 );
|
||||
main_lay->addLayout( br_slider_tick_val_hlay, 2, 1, 1, 2 );
|
||||
main_lay->addWidget( cn_label, 3, 1 );
|
||||
main_lay->addLayout( cn_slider_hlay, 4, 1, 1, 2 );
|
||||
main_lay->addLayout( cn_slider_tick_val_hlay, 5, 1, 1, 2 );
|
||||
|
||||
connect( brightness_slider, SIGNAL( valueChanged( int ) ),
|
||||
this, SLOT( slotGetNewBrightnessContrast( int ) ) );
|
||||
connect( contrast_slider, SIGNAL( valueChanged( int ) ),
|
||||
this, SLOT( slotGetNewBrightnessContrast( int ) ) );
|
||||
|
||||
auto flags = windowFlags();
|
||||
setWindowFlags( flags |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::CustomizeWindowHint |
|
||||
Qt::WindowCloseButtonHint );
|
||||
|
||||
setLayout( main_lay );
|
||||
setWindowTitle( tr( "Brightness/Contrast" ) );
|
||||
|
||||
main_lay->setSizeConstraint( QLayout::SetFixedSize );
|
||||
}
|
||||
|
||||
void ViewParameters::showEvent( QShowEvent *event )
|
||||
{
|
||||
if ( parentWidget() )
|
||||
{
|
||||
int x = 10;
|
||||
int y = ( 15 + height() );
|
||||
|
||||
QPoint relative_pos = parentWidget()->mapToGlobal( QPoint( x, y ) );
|
||||
move( relative_pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "ViewParameters: can't get pointer to parent Widget!";
|
||||
}
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void ViewParameters::updateBrightnessContrast( float brightness,
|
||||
float contrast )
|
||||
{
|
||||
brightness_slider->setValue( 50 + brightness * 50 );
|
||||
contrast_slider->setValue( 50 + contrast * 50 );
|
||||
}
|
||||
|
||||
void ViewParameters::slotGetNewBrightnessContrast( int value )
|
||||
{
|
||||
Q_UNUSED( value );
|
||||
emit signalNewBrightnessContrastValues( brightness_slider->value() / 50. - 1.,
|
||||
contrast_slider->value() / 50. - 1. );
|
||||
}
|
||||
|
81
src/apps/gis-map-viewer/viewparameters.h
Обычный файл
@ -0,0 +1,81 @@
|
||||
/*
|
||||
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 VIEWPARAMETERS_H
|
||||
#define VIEWPARAMETERS_H
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QSlider>
|
||||
#include <QWidget>
|
||||
#include <QShowEvent>
|
||||
|
||||
class ViewSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ViewSlider( int interval,
|
||||
QWidget *parent = 0,
|
||||
int range_min = 0,
|
||||
int range_max = 100 );
|
||||
|
||||
explicit ViewSlider( int interval,
|
||||
Qt::Orientation orientation,
|
||||
QWidget *parent = 0,
|
||||
int range_min = 0,
|
||||
int range_max = 100 );
|
||||
|
||||
void updateTickValuesDisplay( QHBoxLayout *layout, size_t &tick_value_width );
|
||||
|
||||
private:
|
||||
int m_interval;
|
||||
const int m_range_min;
|
||||
const int m_range_max;
|
||||
|
||||
void init( int interval );
|
||||
};
|
||||
|
||||
|
||||
class ViewParameters : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ViewParameters( QWidget *parent = 0 );
|
||||
void updateBrightnessContrast( float brightness, float contrast );
|
||||
|
||||
private:
|
||||
QHBoxLayout *br_slider_hlay;
|
||||
QHBoxLayout *cn_slider_hlay;
|
||||
QHBoxLayout *br_slider_tick_val_hlay;
|
||||
QHBoxLayout *cn_slider_tick_val_hlay;
|
||||
ViewSlider *brightness_slider;
|
||||
ViewSlider *contrast_slider;
|
||||
|
||||
void showEvent( QShowEvent *event );
|
||||
|
||||
private slots:
|
||||
void slotGetNewBrightnessContrast( int value );
|
||||
|
||||
signals:
|
||||
void signalNewBrightnessContrastValues( float br, float cn );
|
||||
};
|
||||
|
||||
#endif
|
79
src/apps/gis-monitor/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,79 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( gis-monitor LANGUAGES CXX )
|
||||
|
||||
set( CMAKE_AUTOMOC ON )
|
||||
set( CMAKE_AUTOUIC ON )
|
||||
set( CMAKE_AUTORCC ON )
|
||||
|
||||
add_compile_options( -std=gnu++11 )
|
||||
add_compile_options( -Wno-ignored-attributes )
|
||||
add_compile_options( -Wno-deprecated-declarations )
|
||||
|
||||
find_package( Qt5
|
||||
COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Svg
|
||||
Widgets
|
||||
REQUIRED )
|
||||
|
||||
file( GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
mainwindow.ui
|
||||
images.qrc
|
||||
translations.qrc )
|
||||
|
||||
add_executable( gis-monitor ${SOURCES} )
|
||||
|
||||
add_custom_command( OUTPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-monitor_ru.qm
|
||||
COMMAND
|
||||
$ENV{KPDA_HOST}/usr/lib/Qt/bin/lrelease -silent ${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts )
|
||||
|
||||
add_custom_target( generate_translations_monitor
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/gis-monitor_ru.qm )
|
||||
|
||||
target_include_directories( gis-monitor
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/public
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gisrender/api/public
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
||||
add_dependencies( gis-monitor generate_translations_monitor )
|
||||
|
||||
target_link_libraries( gis-monitor
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Svg
|
||||
Qt5::Widgets
|
||||
gishelper
|
||||
gisrender )
|
||||
|
||||
|
||||
install( TARGETS gis-monitor DESTINATION bin )
|
Двоичные данные
src/apps/gis-monitor/asserts/view.png
Обычный файл
После Ширина: | Высота: | Размер: 151 KiB |
876
src/apps/gis-monitor/background/mercator.svg
Обычный файл
После Ширина: | Высота: | Размер: 877 KiB |
724
src/apps/gis-monitor/drivermappage.cpp
Обычный файл
@ -0,0 +1,724 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "drivermappage.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include "engine.h"
|
||||
#include "mapcanvas.h"
|
||||
#include "mapview.h"
|
||||
|
||||
extern bool demo_mode;
|
||||
|
||||
int DriverMapPage::VIEWER_COUNTER = 0;
|
||||
|
||||
DriverMapPage::DriverMapPage( QObject *ext_e, gis_core_driver_info_t *i, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
scaling_point( { 0, 0 } ),
|
||||
scrollBarFlag( true ),
|
||||
gridFlag( false ),
|
||||
suffixFlag( false ),
|
||||
driver_info( *i ),
|
||||
viewerProcess( nullptr ),
|
||||
rasterViewProcess( nullptr )
|
||||
{
|
||||
e = static_cast<Engine*>( ext_e );
|
||||
|
||||
connect( e, SIGNAL( setStatusBusy() ),
|
||||
this, SLOT( setDriverStateBusy() ) );
|
||||
|
||||
connect( this, SIGNAL( updateSelectedMapInfo( gis_core_map_information_t* ) ),
|
||||
this, SLOT( fillAdditionalInfo( gis_core_map_information_t* ) ) );
|
||||
|
||||
connect( this, SIGNAL( updateSelectedMapInfo( gis_core_map_information_t* ) ),
|
||||
this, SLOT( fillClassList( gis_core_map_information_t* ) ) );
|
||||
|
||||
page_type = gis_helper_get_map_source_by_driver_id( getDriverId() );
|
||||
initializeWidgetAppearance();
|
||||
|
||||
loadMaps();
|
||||
}
|
||||
|
||||
DriverMapPage::~DriverMapPage()
|
||||
{
|
||||
if ( viewerProcess )
|
||||
{
|
||||
disconnect( viewerProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
|
||||
this, SLOT( processFinished( int, QProcess::ExitStatus ) ) );
|
||||
disconnect( viewerProcess, SIGNAL( started() ),
|
||||
this, SLOT( processStarted() ) );
|
||||
disconnect( viewerProcess, SIGNAL( error( QProcess::ProcessError ) ),
|
||||
this, SLOT( processErrorHandler( QProcess::ProcessError ) ) );
|
||||
|
||||
if ( ( viewerProcess->state() == QProcess::Running ) ||
|
||||
( viewerProcess->state() == QProcess::Starting) )
|
||||
{
|
||||
viewerProcess->terminate();
|
||||
viewerProcess->waitForFinished();
|
||||
}
|
||||
}
|
||||
|
||||
if ( rasterViewProcess )
|
||||
{
|
||||
disconnect( rasterViewProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
|
||||
this, SLOT( processFinished( int, QProcess::ExitStatus ) ) );
|
||||
disconnect( rasterViewProcess, SIGNAL( started() ),
|
||||
this, SLOT( processStarted() ) );
|
||||
disconnect( rasterViewProcess, SIGNAL( error( QProcess::ProcessError ) ),
|
||||
this, SLOT( processErrorHandler( QProcess::ProcessError ) ) );
|
||||
|
||||
if ( ( rasterViewProcess->state() == QProcess::Running ) ||
|
||||
( rasterViewProcess->state() == QProcess::Starting) )
|
||||
{
|
||||
rasterViewProcess->terminate();
|
||||
rasterViewProcess->waitForFinished();
|
||||
}
|
||||
}
|
||||
|
||||
delete actionScaleArea;
|
||||
delete gsView;
|
||||
delete gsCanvas;
|
||||
delete listMapInfo;
|
||||
delete listClasses;
|
||||
delete listMaps;
|
||||
|
||||
e->deleteMaps( mlist );
|
||||
}
|
||||
|
||||
gis_borders_t DriverMapPage::mapBordersTo_MERC_WGS84( gis_core_map_information_t *map_info )
|
||||
{
|
||||
gis_borders_t new_borders = map_info->borders;
|
||||
|
||||
switch ( map_info->meters_projection.projection_idx )
|
||||
{
|
||||
case GIS_PROJECTION_CONIC_CONFORMAL:
|
||||
{
|
||||
new_borders.degrees.north = GIS_MERC_WGS84_NORTH_BOUND;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new_borders;
|
||||
}
|
||||
|
||||
QString DriverMapPage::degrees2string( double d )
|
||||
{
|
||||
int degrees, minutes, seconds;
|
||||
QString info;
|
||||
|
||||
degrees = d;
|
||||
minutes = (d - degrees) * 60;
|
||||
seconds = ((d - degrees) * 60 - minutes) * 60;
|
||||
|
||||
minutes = minutes < 0 ? -minutes : minutes;
|
||||
seconds = seconds < 0 ? -seconds : seconds;
|
||||
|
||||
info = QString::number( degrees ) +
|
||||
QObject::trUtf8( "°" ) +
|
||||
QString::number( minutes ) + "\'" +
|
||||
QString::number( seconds ) + "\"";
|
||||
return info;
|
||||
}
|
||||
|
||||
void DriverMapPage::mapListItemChanged( QListWidgetItem *item, QListWidgetItem *prev )
|
||||
{
|
||||
Q_UNUSED( item );
|
||||
Q_UNUSED( prev );
|
||||
|
||||
int mapIndex = listMaps->currentIndex().row();
|
||||
if ( mapIndex >= 0 )
|
||||
{
|
||||
gis_core_map_information_t *map = &mlist->entry_list[mapIndex];
|
||||
|
||||
gsCanvas->addSelectionRectangle( mapBordersTo_MERC_WGS84( map ) );
|
||||
|
||||
emit updateSelectedMapInfo( map );
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::fillAdditionalInfo( gis_core_map_information_t *map )
|
||||
{
|
||||
QString info_name, info_value;
|
||||
QStringList listClassData;
|
||||
listMapInfo->clear();
|
||||
|
||||
if ( gis_map_projection_is_filled( &map->meters_projection ) )
|
||||
{
|
||||
if ( map->meters_projection.EPSG )
|
||||
{
|
||||
listClassData << "EPSG: " << QString::number( map->meters_projection.EPSG );
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
}
|
||||
|
||||
listClassData << tr( "Projection: " ) << tr( gis_map_projection_get_full_name( &map->meters_projection ) );
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
listClassData << tr( "Ellipsoid: " ) << tr( gis_map_ellipsoid_get_full_name( &map->meters_projection ) );
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
if ( map->meters_projection.height_system_idx != GIS_HEIGHT_SYSTEM_EMPTY )
|
||||
{
|
||||
listClassData << tr( "Height system: " )
|
||||
<< tr( gis_map_height_system_get_full_name( map->meters_projection.height_system_idx ) );
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
}
|
||||
|
||||
if ( gis_map_projection_has_zone( map->meters_projection.projection_idx ) )
|
||||
{
|
||||
listClassData << tr( "Zone: " ) << QString::number( map->meters_projection.zone );
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
gis_borders_t merc_borders = mapBordersTo_MERC_WGS84( map );
|
||||
QString origin_borders_N = fabs( merc_borders.degrees.north - map->borders.degrees.north ) > DBL_EPSILON ?
|
||||
" (" + degrees2string( map->borders.degrees.north ) + ")" : "";
|
||||
QString origin_borders_W = fabs( merc_borders.degrees.west - map->borders.degrees.west ) > DBL_EPSILON ?
|
||||
" (" + degrees2string( map->borders.degrees.west ) + ")" : "";
|
||||
QString origin_borders_S = fabs( merc_borders.degrees.south - map->borders.degrees.south ) > DBL_EPSILON ?
|
||||
" (" + degrees2string( map->borders.degrees.south ) + ")" : "";
|
||||
QString origin_borders_E = fabs( merc_borders.degrees.east - map->borders.degrees.east ) > DBL_EPSILON ?
|
||||
" (" + degrees2string( map->borders.degrees.east ) + ")" : "";
|
||||
|
||||
info_name = "N: ";
|
||||
info_value = degrees2string( merc_borders.degrees.north ) + origin_borders_N;
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
info_name = "S: ";
|
||||
info_value = degrees2string( merc_borders.degrees.south ) + origin_borders_S;
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
info_name = "W: ";
|
||||
info_value = degrees2string( merc_borders.degrees.west ) + origin_borders_W;
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
info_name = "E: ";
|
||||
info_value = degrees2string( merc_borders.degrees.east ) + origin_borders_E;
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
|
||||
if ( map->scale_denominator )
|
||||
{
|
||||
info_name = tr( "Scale: " );
|
||||
info_value = "1:" + QString::number( map->scale_denominator );
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
}
|
||||
|
||||
|
||||
if ( e->isVectorMap( getDriverId() ) )
|
||||
{
|
||||
info_name = tr( "Class count: " );
|
||||
info_value = QString::number( map->class_count );
|
||||
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
info_name = tr( "Object count: " );
|
||||
info_value = QString::number(map->object_count);
|
||||
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
info_name = tr( "Classifier: " );
|
||||
info_value = QString( map->formats.vector.classifier_filename );
|
||||
info_value = QString::fromUtf8( info_value.toLatin1().constData() );
|
||||
listClassData << info_name << info_value;
|
||||
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
|
||||
if ( map->data_source == GIS_CORE_MAP_DATA_SOURCE_S57 )
|
||||
{
|
||||
info_name = tr( "Update: " );
|
||||
info_value = QString( map->src_version );
|
||||
info_value = QString::fromUtf8( info_value.toLatin1().constData() );
|
||||
listClassData << info_name << info_value;
|
||||
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
info_name = tr("Height: ");
|
||||
|
||||
if ( fabs( map->formats.raster.min_height - GIS_INVALID_HEIGHT_VALUE ) > DBL_EPSILON &&
|
||||
fabs( map->formats.raster.max_height - GIS_INVALID_HEIGHT_VALUE ) > DBL_EPSILON )
|
||||
{
|
||||
info_value = QString::number( map->formats.raster.min_height ) + " - "
|
||||
+ QString::number( map->formats.raster.max_height ) + tr( " m" );
|
||||
listClassData << info_name << info_value;
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
listClassData.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::fillClassList( gis_core_map_information_t *actual_map )
|
||||
{
|
||||
listClasses->clear();
|
||||
if ( e->isVectorMap( getDriverId() ) )
|
||||
{
|
||||
gis_core_class_list_t *clist = e->getClassList( actual_map );
|
||||
if ( clist )
|
||||
{
|
||||
for ( uint32_t i = 0; i < clist->entry_count; i++ )
|
||||
{
|
||||
QStringList listClassData;
|
||||
gis_core_class_info_t *actual_class = &clist->entry_list[i];
|
||||
listClassData << QString::number( actual_class->class_data.code, 16 );
|
||||
listClassData << QString::fromUtf8( actual_class->acronym );
|
||||
listClassData << QString::number( actual_class->object_count );
|
||||
listClasses->addTopLevelItem( new QTreeWidgetItem( listClassData ) );
|
||||
}
|
||||
|
||||
e->deleteClassList( clist );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::slotSelectMapRect( QPointF p )
|
||||
{
|
||||
int min_rect_index = gsCanvas->getMapIndexFromClickedRect( p );
|
||||
if ( min_rect_index < 0 || min_rect_index > (int)mlist->entry_count )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gis_core_map_information_t *map = &mlist->entry_list[min_rect_index];
|
||||
|
||||
gsCanvas->addSelectionRectangle( mapBordersTo_MERC_WGS84( map ) );
|
||||
listMaps->setCurrentRow( min_rect_index );
|
||||
}
|
||||
|
||||
void DriverMapPage::setScrollBarsEnabled( bool enabled )
|
||||
{
|
||||
scrollBarFlag = enabled;
|
||||
if( scrollBarFlag )
|
||||
{
|
||||
gsView->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
gsView->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
}
|
||||
else
|
||||
{
|
||||
gsView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
gsView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::scaleAreaTriggered( bool checked )
|
||||
{
|
||||
Q_UNUSED( checked );
|
||||
if ( gsCanvas->scalingAreaFlag )
|
||||
{
|
||||
actionScaleArea->setChecked( false );
|
||||
gsView->setDragMode( QGraphicsView::ScrollHandDrag );
|
||||
gsCanvas->scalingAreaFlag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionScaleArea->setChecked( true );
|
||||
gsView->setDragMode( QGraphicsView::NoDrag );
|
||||
gsCanvas->scalingAreaFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::changeGridState( bool flag )
|
||||
{
|
||||
gridFlag = flag;
|
||||
emit showGrid( flag );
|
||||
}
|
||||
|
||||
void DriverMapPage::changeSuffixState( bool flag )
|
||||
{
|
||||
suffixFlag = flag;
|
||||
updatePage();
|
||||
}
|
||||
|
||||
void DriverMapPage::startViewer( double_point_t degree_center )
|
||||
{
|
||||
QString program = QCoreApplication::applicationDirPath() + "/gis-map-viewer";
|
||||
QStringList arguments;
|
||||
arguments << "-x" << QString::number( degree_center.x );
|
||||
arguments << "-y" << QString::number( degree_center.y );
|
||||
|
||||
|
||||
if ( demo_mode )
|
||||
arguments << "-D" << QString::number( getDriverId() );
|
||||
|
||||
arguments << "-i" << QString::number( driver_info.driver_id + DriverMapPage::VIEWER_COUNTER++ );
|
||||
|
||||
if ( viewerProcess )
|
||||
{
|
||||
viewerProcess->kill();
|
||||
delete viewerProcess;
|
||||
}
|
||||
|
||||
viewerProcess = new QProcess( this );
|
||||
connect( viewerProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
|
||||
this, SLOT( processFinished( int, QProcess::ExitStatus ) ) );
|
||||
connect( viewerProcess, SIGNAL( started() ),
|
||||
this, SLOT( processStarted() ) );
|
||||
connect( viewerProcess, SIGNAL( error( QProcess::ProcessError ) ),
|
||||
this, SLOT( processErrorHandler( QProcess::ProcessError ) ) );
|
||||
|
||||
viewerProcess->setProcessChannelMode( QProcess::ForwardedChannels );
|
||||
viewerProcess->start( program, arguments );
|
||||
|
||||
gsView->setDragMode( QGraphicsView::ScrollHandDrag );
|
||||
}
|
||||
|
||||
void DriverMapPage::processErrorHandler( QProcess::ProcessError err )
|
||||
{
|
||||
QString appName;
|
||||
if ( sender() == viewerProcess )
|
||||
{
|
||||
appName = "gis-map-viewer";
|
||||
}
|
||||
else if ( sender() == rasterViewProcess )
|
||||
{
|
||||
appName = "gis-raster-preview";
|
||||
}
|
||||
|
||||
switch( err )
|
||||
{
|
||||
case QProcess::ProcessError::FailedToStart:
|
||||
qDebug() << "Failed to start " << appName;
|
||||
break;
|
||||
case QProcess::ProcessError::Crashed:
|
||||
qDebug() << "Crashed" << appName;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::initializeWidgetAppearance()
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout;
|
||||
QSplitter *vspl = new QSplitter( Qt::Vertical );
|
||||
QSplitter *hspl2 = new QSplitter( Qt::Horizontal );
|
||||
QSplitter *hspl3 = new QSplitter( Qt::Horizontal );
|
||||
listMaps = new QListWidget( this );
|
||||
listClasses = new QTreeWidget;
|
||||
listMapInfo = new QTreeWidget;
|
||||
gsCanvas = new MapCanvas;
|
||||
gsView = new MapView( static_cast<QGraphicsScene*>( gsCanvas ), static_cast<QWidget*>( this ) );
|
||||
QToolBar *tools = new QToolBar;
|
||||
|
||||
listMaps->setMaximumWidth( 200 );
|
||||
listMaps->setMinimumWidth( 110 );
|
||||
|
||||
listClasses->setColumnCount( 3 );
|
||||
QStringList listClassesHeaders;
|
||||
listClassesHeaders << tr( "Class code" ) << tr( "Acronym" ) << tr( "Object count" );
|
||||
listClasses->setHeaderLabels( listClassesHeaders );
|
||||
listClasses->setColumnWidth( 0, 120 );
|
||||
listClasses->setColumnWidth( 1, 170 );
|
||||
listClasses->setMaximumHeight( 350 );
|
||||
|
||||
labelMaps.setText( tr( "Maps:" ) );
|
||||
QString str;
|
||||
str.clear();
|
||||
str.append( "N-W:\n" );
|
||||
str.append( "S-E: \n" );
|
||||
str.append( tr( "Scale:\n" ) );
|
||||
str.append( tr( "Class count:\n" ) );
|
||||
str.append( tr( "Object count:" ) );
|
||||
labelAdditionalInfo.setText( str );
|
||||
|
||||
listMapInfo->setColumnCount( 2 );
|
||||
listMapInfo->setColumnWidth( 0, 111 );
|
||||
QStringList headerLabels;
|
||||
headerLabels << tr( "Map property" ) << tr( "Value" );
|
||||
listMapInfo->setHeaderLabels( headerLabels );
|
||||
QStringList listMapData;
|
||||
listMapData << labelAdditionalInfo.text();
|
||||
listMapInfo->setMaximumSize( 300, 350 );
|
||||
listMapInfo->setMinimumSize( 300, 130 );
|
||||
listMapInfo->addTopLevelItem( new QTreeWidgetItem( listMapData ) );
|
||||
|
||||
gsView->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
|
||||
gsView->setMinimumSize( 400, 200 );
|
||||
|
||||
layout->addWidget( &labelMaps, 0, 0, 1, 1 );
|
||||
layout->addWidget( tools, 0, 7, 1, 1 );
|
||||
|
||||
labelSubStatus.setContentsMargins( 0,0,6,0 );
|
||||
labelMainStatus.setMaximumHeight( 20 );
|
||||
labelSubStatus.setMaximumHeight( 20 );
|
||||
|
||||
layout->addWidget( &labelMainStatus, 5, 0, 1, 4 );
|
||||
layout->addWidget( &labelSubStatus, 5, 4, 1, 4 );
|
||||
|
||||
hspl2->addWidget( listMaps );
|
||||
hspl2->addWidget( gsView );
|
||||
|
||||
gsView->slotFitScale( true );
|
||||
|
||||
hspl2->setCollapsible( 0, false );
|
||||
hspl2->setCollapsible( 1, false );
|
||||
|
||||
hspl3->addWidget( listMapInfo );
|
||||
hspl3->addWidget( listClasses );
|
||||
hspl3->setCollapsible( 0, false );
|
||||
hspl3->setCollapsible( 1, false );
|
||||
|
||||
vspl->addWidget( hspl2 );
|
||||
vspl->addWidget( hspl3 );
|
||||
vspl->setCollapsible( 0, false );
|
||||
vspl->setCollapsible( 1, false );
|
||||
|
||||
layout->addWidget( vspl, 1, 0, 4, 8 );
|
||||
layout->setRowMinimumHeight( 1, 400 );
|
||||
|
||||
setLayout( layout );
|
||||
|
||||
connect( listMaps, SIGNAL( currentItemChanged( QListWidgetItem*, QListWidgetItem* ) ),
|
||||
this, SLOT( mapListItemChanged( QListWidgetItem*, QListWidgetItem* ) ) );
|
||||
connect( listMaps, SIGNAL( itemDoubleClicked( QListWidgetItem* ) ),
|
||||
this, SLOT( mapItemDblClicked( QListWidgetItem* ) ) );
|
||||
|
||||
connect( gsCanvas, SIGNAL( scalingAreaFlagChanged( bool ) ),
|
||||
this, SLOT( scaleAreaTriggered( bool ) ) );
|
||||
connect( gsCanvas, SIGNAL( getDoubleClick( double_point_t ) ),
|
||||
this, SLOT( startViewer( double_point_t ) ) );
|
||||
|
||||
QAction *actionIncreaseScale = new QAction( QIcon( ":/icons/zoomin50.png" ), "+", this );
|
||||
actionIncreaseScale->setShortcuts( QList<QKeySequence>() << QKeySequence( Qt::CTRL + Qt::Key_Equal ) << QKeySequence::ZoomIn );
|
||||
QAction *actionReduceScale = new QAction( QIcon( ":/icons/zoomout50.png" ), "-", this );
|
||||
actionReduceScale->setShortcut( QKeySequence::ZoomOut );
|
||||
QAction *actionFitScale = new QAction( QIcon( ":/icons/fit50.png" ), tr( "Fit" ), this );
|
||||
actionScaleArea = new QAction( QIcon( ":/icons/area.png" ), tr( "Area" ), this );
|
||||
actionScaleArea->setCheckable( true );
|
||||
|
||||
connect( actionScaleArea, SIGNAL( triggered( bool ) ), this, SLOT( scaleAreaTriggered( bool ) ) );
|
||||
connect( actionIncreaseScale, SIGNAL( triggered( bool ) ), gsView, SLOT( slotIncreaseScale( bool ) ) );
|
||||
connect( actionReduceScale, SIGNAL( triggered( bool ) ), gsView, SLOT( slotDecreaseScale( bool ) ) );
|
||||
connect( actionFitScale, SIGNAL( triggered( bool ) ), gsView, SLOT( slotFitScale( bool ) ) );
|
||||
|
||||
QActionGroup *actionGroup = new QActionGroup( this );
|
||||
actionGroup->addAction( actionIncreaseScale );
|
||||
actionGroup->addAction( actionReduceScale );
|
||||
actionGroup->addAction( actionFitScale );
|
||||
actionGroup->addAction( actionScaleArea );
|
||||
tools->addActions( actionGroup->actions() );
|
||||
|
||||
gsView->setDragMode( QGraphicsView::ScrollHandDrag );
|
||||
gsView->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
gsView->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
|
||||
connect( gsCanvas, SIGNAL( increaseScale( bool ) ),
|
||||
gsView, SLOT( slotIncreaseScale( bool ) ) );
|
||||
connect( gsCanvas, SIGNAL( decreaseScale( bool ) ),
|
||||
gsView, SLOT( slotDecreaseScale( bool ) ) );
|
||||
connect( gsCanvas, SIGNAL( scalingAreaByRect( QRectF ) ),
|
||||
gsView, SLOT( scaleAreaByRect( QRectF ) ) );
|
||||
|
||||
connect( this, SIGNAL( showGrid( bool ) ),
|
||||
gsCanvas, SLOT( slotShowGrid( bool ) ) );
|
||||
|
||||
geometry_rect = QApplication::desktop()->screenGeometry( this );
|
||||
}
|
||||
|
||||
void DriverMapPage::setScaleFilter( int lower_limit, int upper_limit )
|
||||
{
|
||||
scaling_point.x = lower_limit;
|
||||
scaling_point.y = upper_limit;
|
||||
|
||||
gsCanvas->removeAllSelection();
|
||||
|
||||
if ( lower_limit == 0 && upper_limit == 0 )
|
||||
{
|
||||
for ( uint32_t i = 0; i < mlist->entry_count; i++ )
|
||||
{
|
||||
listMaps->item( i )->setHidden( false );
|
||||
gsCanvas->setMapRectEnabled( i, true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( unsigned int i = 0; i < mlist->entry_count; i++ )
|
||||
{
|
||||
listMaps->item( i )->setHidden( true );
|
||||
gsCanvas->setMapRectEnabled( i, false );
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < mlist->entry_count; i++ )
|
||||
{
|
||||
int scale = mlist->entry_list[i].scale_denominator;
|
||||
if ( ( scale >= lower_limit ) && ( ( scale < upper_limit ) || ( upper_limit == 10000000 ) ) )
|
||||
{
|
||||
listMaps->item( i )->setHidden( false );
|
||||
gsCanvas->setMapRectEnabled( i, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::loadMaps()
|
||||
{
|
||||
mlist = e->getMaps( getDriverId() );
|
||||
if ( mlist )
|
||||
{
|
||||
for ( unsigned int i = 0; i < mlist->entry_count; i++ )
|
||||
{
|
||||
gis_core_map_information_t *map = &mlist->entry_list[i];
|
||||
|
||||
QString display_string;
|
||||
if ( suffixFlag )
|
||||
{
|
||||
display_string = QString( map->gcm_fname );
|
||||
display_string = QString::fromUtf8( display_string.toLatin1().constData() );
|
||||
listMaps->addItem( new QListWidgetItem( display_string ));
|
||||
}
|
||||
else
|
||||
{
|
||||
display_string = QString( map->src_fname );
|
||||
display_string = QString::fromUtf8( display_string.toLatin1().constData() );
|
||||
listMaps->addItem( new QListWidgetItem( display_string ));
|
||||
}
|
||||
|
||||
gsCanvas->addMapRectangle( i, mapBordersTo_MERC_WGS84( map ), this );
|
||||
}
|
||||
|
||||
listMaps->setSelectionMode( QAbstractItemView::SingleSelection );
|
||||
|
||||
QString substatusString;
|
||||
substatusString = tr( "Number of loaded maps: " )
|
||||
+ QString::number( mlist->entry_count );
|
||||
labelSubStatus.setText( substatusString );
|
||||
labelSubStatus.setAlignment( Qt::AlignRight );
|
||||
setDriverStateReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
setDisabled(true);
|
||||
QPalette palette = labelSubStatus.palette();
|
||||
palette.setColor( labelSubStatus.foregroundRole(), Qt::red );
|
||||
labelSubStatus.setPalette( palette );
|
||||
setDriverStateReady();
|
||||
labelSubStatus.setText( tr( "Connection status: request failed" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void DriverMapPage::updatePage()
|
||||
{
|
||||
listMaps->clear();
|
||||
listMaps->setSelectionMode( QAbstractItemView::NoSelection );
|
||||
listClasses->clear();
|
||||
listMapInfo->clear();
|
||||
|
||||
gsCanvas->removeAllRects();
|
||||
|
||||
e->deleteMaps( mlist );
|
||||
|
||||
loadMaps();
|
||||
update();
|
||||
}
|
||||
|
||||
void DriverMapPage::setDriverStateBusy()
|
||||
{
|
||||
QPalette palette = labelMainStatus.palette();
|
||||
palette.setColor( labelMainStatus.foregroundRole(), Qt::red );
|
||||
labelMainStatus.setPalette( palette );
|
||||
labelMainStatus.setText( tr( "Driver status: " ) + tr( "busy" ) );
|
||||
}
|
||||
|
||||
void DriverMapPage::setDriverStateReady()
|
||||
{
|
||||
QPalette palette = labelMainStatus.palette();
|
||||
palette.setColor( labelMainStatus.foregroundRole(), Qt::black );
|
||||
labelMainStatus.setPalette( palette );
|
||||
labelMainStatus.setText( tr( "Driver status: " ) + tr( "ready" ) );
|
||||
}
|
||||
|
||||
void DriverMapPage::mapItemDblClicked( QListWidgetItem* item )
|
||||
{
|
||||
int map_idx = listMaps->row( item );
|
||||
gis_core_map_information_t *map = &mlist->entry_list[map_idx];
|
||||
|
||||
gsView->centerOn( gsCanvas->getMapRectItemToCenter( map_idx ) );
|
||||
|
||||
if ( GIS_IS_CORE_MAP_DATA_SOURCE_VECTOR( map->data_source ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QString program = QCoreApplication::applicationDirPath() + "/gis-raster-preview";
|
||||
QStringList arguments;
|
||||
|
||||
QString map_path = gis_helper_env_get_maps_cache_directory();
|
||||
map_path += "/gcm/";
|
||||
map_path += map->gcm_fname;
|
||||
|
||||
QRect r = listMaps->visualItemRect( item );
|
||||
QPoint selected_item_position( r.x() + 10, r.y() + r.height() );
|
||||
QRect mw_rect = parentWidget()->parentWidget()->parentWidget()->window()->geometry();
|
||||
arguments << "-x" << QString::number(selected_item_position.x() + 10 + mw_rect.x());
|
||||
arguments << "-y" << QString::number(selected_item_position.y() + 125 + mw_rect.y());;
|
||||
arguments << "-f" << map_path;
|
||||
|
||||
if ( rasterViewProcess )
|
||||
{
|
||||
rasterViewProcess->kill();
|
||||
delete rasterViewProcess;
|
||||
}
|
||||
|
||||
rasterViewProcess = new QProcess( this );
|
||||
connect( rasterViewProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
|
||||
this, SLOT( processFinished( int, QProcess::ExitStatus ) ) );
|
||||
connect( rasterViewProcess, SIGNAL( started() ),
|
||||
this, SLOT( processStarted() ) );
|
||||
connect( rasterViewProcess, SIGNAL( error( QProcess::ProcessError ) ),
|
||||
this, SLOT( processErrorHandler( QProcess::ProcessError ) ) );
|
||||
|
||||
rasterViewProcess->setProcessChannelMode( QProcess::ForwardedChannels );
|
||||
rasterViewProcess->start( program, arguments );
|
||||
}
|
||||
|
126
src/apps/gis-monitor/drivermappage.h
Обычный файл
@ -0,0 +1,126 @@
|
||||
/*
|
||||
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 DRIVERMAPPAGE_H
|
||||
#define DRIVERMAPPAGE_H
|
||||
|
||||
#include <QAction>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QPointer>
|
||||
#include <QProcess>
|
||||
#include <QSplitter>
|
||||
#include <QToolBar>
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include <gis/gis_databuffer.h>
|
||||
#include <gis/gis_math.h>
|
||||
#include <gis/gis_path.h>
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
class MapCanvas;
|
||||
class MapView;
|
||||
|
||||
class DriverMapPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DriverMapPage( QObject *e, gis_core_driver_info_t *i, QWidget *parent = 0 );
|
||||
~DriverMapPage();
|
||||
|
||||
gis_core_driver_id_t getDriverId() { return driver_info.driver_id; }
|
||||
gis_core_map_data_source_t getPageType() { return page_type; }
|
||||
|
||||
void changeGridState( bool );
|
||||
void changeSuffixState( bool );
|
||||
|
||||
void setScrollBarsEnabled( bool enabled );
|
||||
void setScaleFilter( int lower_limit, int upper_limit );
|
||||
|
||||
void updatePage();
|
||||
|
||||
int32_point_t scaling_point;
|
||||
bool scrollBarFlag;
|
||||
bool gridFlag;
|
||||
bool suffixFlag;
|
||||
|
||||
private:
|
||||
void initializeWidgetAppearance();
|
||||
void loadMaps();
|
||||
gis_borders_t mapBordersTo_MERC_WGS84( gis_core_map_information_t *map_info );
|
||||
QString degrees2string( double d );
|
||||
|
||||
QPointer <Engine> e;
|
||||
gis_core_map_data_source_t page_type;
|
||||
gis_core_driver_info_t driver_info;
|
||||
gis_core_map_list_t *mlist;
|
||||
|
||||
static int VIEWER_COUNTER;
|
||||
|
||||
QRect geometry_rect;
|
||||
|
||||
QProcess *viewerProcess;
|
||||
QProcess *rasterViewProcess;
|
||||
QListWidget *listMaps;
|
||||
QTreeWidget *listMapInfo;
|
||||
QTreeWidget *listClasses;
|
||||
MapCanvas *gsCanvas;
|
||||
MapView *gsView;
|
||||
|
||||
QLabel labelMaps;
|
||||
QLabel labelAdditionalInfo;
|
||||
QLabel labelMainStatus;
|
||||
QLabel labelSubStatus;
|
||||
QAction *actionScaleArea;
|
||||
QAction *actionGrid;
|
||||
|
||||
public slots:
|
||||
void startViewer( double_point_t center );
|
||||
|
||||
private slots:
|
||||
void fillAdditionalInfo( gis_core_map_information_t *actual_map );
|
||||
void fillClassList( gis_core_map_information_t *actual_map );
|
||||
|
||||
void mapItemDblClicked( QListWidgetItem* );
|
||||
void mapListItemChanged( QListWidgetItem*, QListWidgetItem* );
|
||||
void scaleAreaTriggered( bool checked );
|
||||
void slotSelectMapRect( QPointF point );
|
||||
|
||||
void processErrorHandler(QProcess::ProcessError);
|
||||
void processStarted() { setEnabled( false ); }
|
||||
void processFinished( int exitCode, QProcess::ExitStatus exitStatus )
|
||||
{
|
||||
Q_UNUSED( exitCode ); Q_UNUSED( exitStatus );
|
||||
setEnabled( true );
|
||||
}
|
||||
|
||||
void setDriverStateBusy();
|
||||
void setDriverStateReady();
|
||||
|
||||
signals:
|
||||
void showGrid( bool flag );
|
||||
void updateSelectedMapInfo( gis_core_map_information_t *map );
|
||||
void scalingAreaByRect( QRectF );
|
||||
|
||||
};
|
||||
#endif
|
89
src/apps/gis-monitor/drivertabs.cpp
Обычный файл
@ -0,0 +1,89 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "drivertabs.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QKeySequence>
|
||||
|
||||
#include "drivermappage.h"
|
||||
|
||||
DriverTabs::DriverTabs( QWidget *parent ) :
|
||||
QTabWidget( parent )
|
||||
{
|
||||
setMovable( true );
|
||||
}
|
||||
|
||||
DriverTabs::~DriverTabs()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DriverTabs::closeTab( int index )
|
||||
{
|
||||
QWidget *d = widget( index );
|
||||
this->removeTab( index );
|
||||
delete( d );
|
||||
}
|
||||
|
||||
void DriverTabs::addTab( gis_core_driver_info_t *info, QString acronym )
|
||||
{
|
||||
DriverMapPage *page;
|
||||
|
||||
try
|
||||
{
|
||||
page = new DriverMapPage( sender(), info, this );
|
||||
}
|
||||
catch( const std::bad_alloc & )
|
||||
{
|
||||
qDebug() << "Failed to create DriverMapPage";
|
||||
return;
|
||||
}
|
||||
|
||||
QTabWidget::addTab( page, acronym );
|
||||
}
|
||||
|
||||
DriverMapPage * DriverTabs::getCurrentPage()
|
||||
{
|
||||
DriverMapPage *current_page = static_cast <DriverMapPage*>( currentWidget() );
|
||||
|
||||
if ( !current_page )
|
||||
{
|
||||
qDebug() << "No current driver tab";
|
||||
}
|
||||
|
||||
return current_page;
|
||||
}
|
||||
|
||||
void DriverTabs::keyPressEvent( QKeyEvent *event )
|
||||
{
|
||||
if ( event->matches( QKeySequence::StandardKey::MoveToNextWord ) )
|
||||
{
|
||||
setCurrentIndex( currentIndex() + 1 );
|
||||
}
|
||||
|
||||
if ( event->matches( QKeySequence::StandardKey::MoveToPreviousWord ) )
|
||||
{
|
||||
setCurrentIndex( currentIndex() - 1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
46
src/apps/gis-monitor/drivertabs.h
Обычный файл
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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 DRIVERTABS_H
|
||||
#define DRIVERTABS_H
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QTabWidget>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
|
||||
class DriverMapPage;
|
||||
|
||||
class DriverTabs : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DriverTabs( QWidget *parent );
|
||||
~DriverTabs();
|
||||
DriverMapPage * getCurrentPage();
|
||||
virtual void keyPressEvent( QKeyEvent *event );
|
||||
public slots:
|
||||
void addTab( gis_core_driver_info_t *info, QString acronym );
|
||||
void closeTab( int tabIndex );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
221
src/apps/gis-monitor/engine.cpp
Обычный файл
@ -0,0 +1,221 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
|
||||
gis_core_driver_info_t Engine::drivers[GIS_CORE_DRIVER_COUNT];
|
||||
|
||||
Engine::Engine( QObject *parent ) : QObject( parent ),
|
||||
connection( nullptr ),
|
||||
m_isConnected( false )
|
||||
{}
|
||||
|
||||
Engine::~Engine()
|
||||
{
|
||||
disconnectCore();
|
||||
}
|
||||
|
||||
int Engine::connectCore()
|
||||
{
|
||||
connection = new gis_core_connection_t;
|
||||
|
||||
gis_core_link_init( connection );
|
||||
int status = gis_core_link_connect( connection, SHID_NULL );
|
||||
|
||||
if ( status != EOK )
|
||||
{
|
||||
QMessageBox box;
|
||||
box.setText("GIS Core connection failed");
|
||||
box.exec();
|
||||
m_isConnected = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_isConnected = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void Engine::disconnectCore()
|
||||
{
|
||||
if ( connection )
|
||||
{
|
||||
gis_core_link_destroy( connection, false );
|
||||
delete connection;
|
||||
m_isConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::getDrivers()
|
||||
{
|
||||
if ( isCoreConnected() )
|
||||
{
|
||||
int id;
|
||||
GIS_CORE_DRIVER_FOR_LOOP_HEAD( id )
|
||||
{
|
||||
getDriver( id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::getDriver( int id )
|
||||
{
|
||||
gis_core_driver_info_t *info = &drivers[id];
|
||||
|
||||
info->driver_id = (gis_core_driver_id_t)id;
|
||||
gis_core_request_driver_info( connection, info );
|
||||
|
||||
char acronym[GIS_MAX_ACRONYM_LENGTH];
|
||||
gis_core_request_driver_acronym( connection, info->driver_id, acronym );
|
||||
|
||||
if ( info->initialized )
|
||||
{
|
||||
emit createDriverTab( info, QString( acronym ) );
|
||||
}
|
||||
}
|
||||
|
||||
gis_core_map_list_t * Engine::getMaps( gis_core_driver_id_t driver_id )
|
||||
{
|
||||
gis_core_map_list_t *mlist = new gis_core_map_list_t;
|
||||
gis_core_map_list_init( mlist );
|
||||
gis_core_request_parameters_t map_desc;
|
||||
gis_core_request_parameters_init( &map_desc );
|
||||
|
||||
int result = gis_core_request_maps_list( connection, &map_desc, driver_id, mlist );
|
||||
|
||||
if ( result != EOK )
|
||||
{
|
||||
if ( result != ENODATA )
|
||||
{
|
||||
fprintf( stderr,
|
||||
"GIS Core request maps list failed - driver_id = %d (e:%d) [%s()]\n",
|
||||
driver_id, result, __FUNCTION__ );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return mlist;
|
||||
}
|
||||
|
||||
void Engine::deleteMaps( gis_core_map_list_t *mlist )
|
||||
{
|
||||
gis_core_map_list_free( mlist );
|
||||
delete mlist;
|
||||
}
|
||||
|
||||
gis_core_class_list_t *Engine::getClassList( gis_core_map_information_t *map )
|
||||
{
|
||||
gis_core_class_list_t *list = new gis_core_class_list_t;
|
||||
gis_core_class_list_init( list );
|
||||
|
||||
int result = gis_core_request_map_class_list( connection, map, list );
|
||||
|
||||
if ( result != EOK )
|
||||
{
|
||||
if ( result != ENODATA )
|
||||
{
|
||||
fprintf( stderr,
|
||||
"GIS Core request class list failed - map id = %d [%s()]\n",
|
||||
map->id, __FUNCTION__ );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void Engine::deleteClassList( gis_core_class_list_t *clist )
|
||||
{
|
||||
gis_core_class_list_free( clist );
|
||||
delete clist;
|
||||
}
|
||||
|
||||
bool Engine::isVectorMap( gis_core_driver_id_t driver_id )
|
||||
{
|
||||
return GIS_IS_CORE_MAP_DATA_SOURCE_VECTOR( gis_helper_get_map_source_by_driver_id( driver_id ) );
|
||||
}
|
||||
|
||||
void Engine::updateCache()
|
||||
{
|
||||
emit setStatusBusy();
|
||||
|
||||
if ( isCoreConnected() )
|
||||
{
|
||||
int i;
|
||||
GIS_CORE_DRIVER_FOR_LOOP_HEAD(i)
|
||||
{
|
||||
if ( drivers[i].initialized )
|
||||
gis_core_request_update_cache( connection,
|
||||
drivers[i].driver_id,
|
||||
GIS_CORE_UPDATE_CACHE_MODE_SYNC_UPDATE );
|
||||
}
|
||||
}
|
||||
|
||||
emit cacheProcessingFinished();
|
||||
}
|
||||
|
||||
void Engine::updateCacheSoft()
|
||||
{
|
||||
emit setStatusBusy();
|
||||
|
||||
if ( isCoreConnected() )
|
||||
{
|
||||
int i;
|
||||
GIS_CORE_DRIVER_FOR_LOOP_HEAD(i)
|
||||
{
|
||||
if ( drivers[i].initialized )
|
||||
gis_core_request_update_cache( connection,
|
||||
drivers[i].driver_id,
|
||||
GIS_CORE_UPDATE_CACHE_MODE_SOFT_UPDATE );
|
||||
}
|
||||
}
|
||||
|
||||
emit cacheProcessingFinished();
|
||||
}
|
||||
|
||||
void Engine::overwriteCache()
|
||||
{
|
||||
emit setStatusBusy();
|
||||
|
||||
if ( isCoreConnected() )
|
||||
{
|
||||
int i;
|
||||
GIS_CORE_DRIVER_FOR_LOOP_HEAD(i)
|
||||
{
|
||||
if ( drivers[i].initialized )
|
||||
gis_core_request_update_cache( connection,
|
||||
drivers[i].driver_id,
|
||||
GIS_CORE_UPDATE_CACHE_MODE_HARD_RESET );
|
||||
}
|
||||
}
|
||||
|
||||
emit cacheProcessingFinished();
|
||||
}
|
||||
|
||||
bool Engine::isCoreConnected()
|
||||
{
|
||||
return m_isConnected;
|
||||
}
|
||||
|
92
src/apps/gis-monitor/engine.h
Обычный файл
@ -0,0 +1,92 @@
|
||||
/*
|
||||
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 ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gis_databuffer.h>
|
||||
|
||||
class Engine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Engine( QObject *parent = nullptr );
|
||||
~Engine();
|
||||
|
||||
int connectCore();
|
||||
void disconnectCore();
|
||||
bool isCoreConnected();
|
||||
|
||||
gis_core_map_list_t * getMaps( gis_core_driver_id_t driver_id );
|
||||
gis_core_class_list_t * getClassList( gis_core_map_information_t *map );
|
||||
|
||||
void deleteMaps( gis_core_map_list_t *mlist );
|
||||
void deleteClassList( gis_core_class_list_t *clist );
|
||||
|
||||
bool isVectorMap(gis_core_driver_id_t driver_id);
|
||||
|
||||
gis_core_connection_t *connection;
|
||||
|
||||
private:
|
||||
static gis_core_driver_info_t drivers[GIS_CORE_DRIVER_COUNT];
|
||||
bool m_isConnected;
|
||||
|
||||
public slots:
|
||||
void getDrivers();
|
||||
void getDriver( int id );
|
||||
void overwriteCache();
|
||||
void updateCache();
|
||||
void updateCacheSoft();
|
||||
|
||||
signals:
|
||||
void createDriverTab( gis_core_driver_info_t *, QString );
|
||||
void cacheProcessingFinished();
|
||||
void setStatusBusy();
|
||||
};
|
||||
|
||||
class EngineController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QThread workerThread;
|
||||
public:
|
||||
EngineController( QObject *parent = nullptr ) : QObject( parent )
|
||||
{
|
||||
e = new Engine;
|
||||
workerThread.setObjectName( "Engine" );
|
||||
e->moveToThread(&workerThread);
|
||||
workerThread.start();
|
||||
}
|
||||
|
||||
~EngineController()
|
||||
{
|
||||
workerThread.quit();
|
||||
workerThread.wait();
|
||||
}
|
||||
|
||||
Engine *e;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Двоичные данные
src/apps/gis-monitor/icons/area.png
Обычный файл
После Ширина: | Высота: | Размер: 1.4 KiB |
Двоичные данные
src/apps/gis-monitor/icons/area55.png
Обычный файл
После Ширина: | Высота: | Размер: 7.9 KiB |
Двоичные данные
src/apps/gis-monitor/icons/eye.png
Обычный файл
После Ширина: | Высота: | Размер: 2.2 KiB |
Двоичные данные
src/apps/gis-monitor/icons/fit50.png
Обычный файл
После Ширина: | Высота: | Размер: 841 B |
Двоичные данные
src/apps/gis-monitor/icons/request.png
Обычный файл
После Ширина: | Высота: | Размер: 21 KiB |
Двоичные данные
src/apps/gis-monitor/icons/request2.png
Обычный файл
После Ширина: | Высота: | Размер: 4.5 KiB |
Двоичные данные
src/apps/gis-monitor/icons/select-area.png
Обычный файл
После Ширина: | Высота: | Размер: 4.8 KiB |
Двоичные данные
src/apps/gis-monitor/icons/zoomin50.png
Обычный файл
После Ширина: | Высота: | Размер: 1.0 KiB |
Двоичные данные
src/apps/gis-monitor/icons/zoomout50.png
Обычный файл
После Ширина: | Высота: | Размер: 1021 B |
10
src/apps/gis-monitor/images.qrc
Обычный файл
@ -0,0 +1,10 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/fit50.png</file>
|
||||
<file>icons/zoomin50.png</file>
|
||||
<file>icons/zoomout50.png</file>
|
||||
<file>icons/area.png</file>
|
||||
<file>icons/eye.png</file>
|
||||
<file>background/mercator.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
111
src/apps/gis-monitor/main.cpp
Обычный файл
@ -0,0 +1,111 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QLocale>
|
||||
#include <QSettings>
|
||||
#include <QMenu>
|
||||
#include <QTranslator>
|
||||
|
||||
#include <gis/gis_databuffer.h>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "engine.h"
|
||||
|
||||
bool demo_mode = false;
|
||||
int window_x = 0,
|
||||
window_y = 0,
|
||||
window_width = 0,
|
||||
window_height = 0;
|
||||
|
||||
void gis_map_viewer_config_edit()
|
||||
{
|
||||
QString config_dir( gis_helper_env_get_config_directory() );
|
||||
QSettings settings( config_dir + "gis-map-viewer.conf", QSettings::IniFormat);
|
||||
|
||||
settings.setValue( "MainWindow/oneMapMode", true );
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gis_helper_debug_mode_setmask( GIS_DEBUG_MODE_STD | GIS_DEBUG_MODE_FD );
|
||||
gis_helper_debug_file_setname( "gis-monitor.log" );
|
||||
|
||||
int opt = 0;
|
||||
extern char *optarg;
|
||||
while ( ( opt = getopt( argc, argv,"x:y:w:h:D" ) ) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'x':
|
||||
window_x = atoi( optarg );
|
||||
break;
|
||||
case 'y':
|
||||
window_y = atoi( optarg );
|
||||
break;
|
||||
case 'w':
|
||||
window_width = atoi( optarg );
|
||||
break;
|
||||
case 'h':
|
||||
window_height = atoi( optarg );
|
||||
break;
|
||||
case 'D':
|
||||
demo_mode = true;
|
||||
break;
|
||||
case '?':
|
||||
printf( "Error: unknown option\n" );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
CleanExit cleanExit;
|
||||
|
||||
QApplication a( argc, argv );
|
||||
|
||||
const char *lang = getenv( "ABLANG" );
|
||||
QString locale = "en_EN";
|
||||
|
||||
if ( lang )
|
||||
{
|
||||
locale = QString( lang );
|
||||
}
|
||||
|
||||
QTranslator myTranslator;
|
||||
myTranslator.load( ":/translations/gis-monitor_" + locale );
|
||||
a.installTranslator( &myTranslator );
|
||||
|
||||
gis_map_viewer_config_edit();
|
||||
|
||||
EngineController *ctrl = new EngineController;
|
||||
MainWindow w( ctrl->e );
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
|
439
src/apps/gis-monitor/mainwindow.cpp
Обычный файл
@ -0,0 +1,439 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include "mapadder.h"
|
||||
|
||||
extern int window_x, window_y, window_width, window_height;
|
||||
|
||||
MainWindow::MainWindow( Engine *ext_e, QWidget *parent ) :
|
||||
QMainWindow( parent ),
|
||||
ui( new Ui::MainWindow ),
|
||||
linkerProcess( nullptr ),
|
||||
linkerProcessBlockingFlag( false ),
|
||||
loaderProcess( nullptr ),
|
||||
min_height( 550 ),
|
||||
min_width( 750 )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
tabs = new DriverTabs( this );
|
||||
|
||||
e = ext_e;
|
||||
|
||||
initializeMenu();
|
||||
setCentralWidget( tabs );
|
||||
connect( tabs, SIGNAL( currentChanged( int ) ),
|
||||
this, SLOT( slotChangeTabAnalyzer( int ) ) );
|
||||
e->connectCore();
|
||||
|
||||
connect( e, SIGNAL( createDriverTab( gis_core_driver_info_t *, QString ) ),
|
||||
tabs, SLOT( addTab( gis_core_driver_info_t *, QString ) ) );
|
||||
|
||||
connect( e, SIGNAL( cacheProcessingFinished() ),
|
||||
this, SLOT( slotSoftReset() ) );
|
||||
|
||||
e->getDrivers();
|
||||
|
||||
window_x = window_x < 0 ? 0 : window_x;
|
||||
window_y = window_y < 0 ? 0 : window_y;
|
||||
|
||||
setGeometry( window_x, window_y, window_width, window_height );
|
||||
emit endInit();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if ( linkerProcess )
|
||||
{
|
||||
disconnect( linkerProcess, SIGNAL( finished( int ) ),
|
||||
this, SLOT( slotResetPage( int ) ) );
|
||||
disconnect( linkerProcess, SIGNAL( finished( int ) ),
|
||||
this, SLOT(slotLinkerFlag( int ) ) );
|
||||
disconnect( linkerProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
|
||||
this, SLOT( slotLinkerDebug( int, QProcess::ExitStatus ) ) );
|
||||
|
||||
if ( ( linkerProcess->state() == QProcess::Running ) ||
|
||||
( linkerProcess->state() == QProcess::Starting ) )
|
||||
{
|
||||
linkerProcess->terminate();
|
||||
linkerProcess->waitForFinished();
|
||||
}
|
||||
}
|
||||
|
||||
if ( loaderProcess )
|
||||
loaderProcess->terminate();
|
||||
|
||||
delete menuMain;
|
||||
delete tabs;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::slotHardReset()
|
||||
{
|
||||
e->disconnectCore();
|
||||
int size = tabs->count();
|
||||
|
||||
for ( int j = 0; j < size; j++)
|
||||
{
|
||||
tabs->closeTab( 0 );
|
||||
}
|
||||
|
||||
if ( e->connectCore() == EOK )
|
||||
{
|
||||
e->getDrivers();
|
||||
qDebug() << "Successful reset";
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Failed to connect in reset";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::slotSoftReset()
|
||||
{
|
||||
int size = tabs->count();
|
||||
|
||||
for ( int j = 0; j < size; j++)
|
||||
{
|
||||
tabs->setCurrentIndex(j);
|
||||
slotResetPage( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
QMainWindow::resizeEvent( event );
|
||||
|
||||
if ( event->size().width() < min_width ||
|
||||
event->size().height() < min_height )
|
||||
{
|
||||
resize( event->size().width() < min_width ? min_width : event->size().width(),
|
||||
event->size().height() < min_height ? min_height : event->size().height() );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::initializeMenu()
|
||||
{
|
||||
menuMain = new QMenu( tr( "Main" ), this );
|
||||
menuMain->addAction( tr( "Reset" ), this, SLOT( slotHardReset() ), QKeySequence( Qt::CTRL | Qt::Key_R ) );
|
||||
menuMain->addSeparator();
|
||||
menuMain->addAction( tr( "Add map" ), this, SLOT( slotAddMap() ), QKeySequence( Qt::CTRL | Qt::Key_O ) );
|
||||
linkerAction = new QAction( tr( "Maps and Styles" ), menuMain );
|
||||
connect( linkerAction, SIGNAL( triggered(bool) ), this, SLOT( slotStartLinker( bool ) ) );
|
||||
menuMain->addAction( linkerAction );
|
||||
menuMain->addSeparator();
|
||||
menuMain->addAction( tr( "About" ), this, SLOT( showAboutDialog() ) );
|
||||
menuMain->addAction( tr( "Exit" ), QApplication::instance(), SLOT( quit() ), QKeySequence( Qt::CTRL | Qt::Key_Q ) );
|
||||
|
||||
QMenu *menuView = new QMenu( tr("View"), this );
|
||||
|
||||
scaleVector.append( { 0, 0 } );
|
||||
scaleVector.append( { 1, 5000 } );
|
||||
scaleVector.append( { 5000, 10000 } );
|
||||
scaleVector.append( { 10000, 25000 } );
|
||||
scaleVector.append( { 25000, 50000 } );
|
||||
scaleVector.append( { 50000, 100000 } );
|
||||
scaleVector.append( { 100000, 200000 } );
|
||||
scaleVector.append( { 200000, 500000 } );
|
||||
scaleVector.append( { 500000, 1000000 } );
|
||||
scaleVector.append( { 1000000, 10000000 } );
|
||||
|
||||
QMenu *menuScales = new QMenu( tr( "Scales" ), this );
|
||||
menuView->addMenu( menuScales );
|
||||
menuView->addSeparator();
|
||||
|
||||
scaleGroup = new QActionGroup( menuScales );
|
||||
QAction *allScales = new QAction( tr( "All scales" ), menuScales );
|
||||
allScales->setCheckable( true );
|
||||
scaleGroup->addAction( allScales );
|
||||
allScales->setChecked( true );
|
||||
menuScales->addAction( allScales );
|
||||
actionVector.append( allScales );
|
||||
connect( allScales , SIGNAL( triggered( bool ) ), this, SLOT( slotGetScaleIndex( bool ) ) );
|
||||
|
||||
for( int i = 1; i < scaleVector.size(); ++i )
|
||||
{
|
||||
QString str;
|
||||
int j;
|
||||
|
||||
if ( ( i != 1 ) && ( i != scaleVector.size() - 1 ) )
|
||||
{
|
||||
str.append( " [" );
|
||||
for ( j = 0; j < ( 6 - QString::number( scaleVector.at( i ).x ).length() ); ++j )
|
||||
str.append( " " );
|
||||
}
|
||||
if ( i == scaleVector.size() - 1 )
|
||||
str.append( QChar( 0x2265 ) );
|
||||
|
||||
if ( i != 1)
|
||||
str.append( QString::number( scaleVector.at( i ).x ) );
|
||||
|
||||
if ( ( i != 1 ) && ( i != scaleVector.size() - 1 ) )
|
||||
str.append( ";" );
|
||||
|
||||
if ( i != 1 )
|
||||
{
|
||||
for ( j = 0; j < ( 8 - QString::number( scaleVector.at( i ).y ).length() ); ++j )
|
||||
str.append( " " );
|
||||
}
|
||||
|
||||
if ( i == 1 )
|
||||
{
|
||||
str.append( " < " );
|
||||
}
|
||||
|
||||
if ( i != scaleVector.size() - 1 )
|
||||
{
|
||||
str.append( QString::number( scaleVector.at( i ).y ) );
|
||||
}
|
||||
|
||||
if ( ( i != 1 ) && ( i != scaleVector.size() - 1 ) )
|
||||
{
|
||||
str.append( ") " );
|
||||
}
|
||||
|
||||
QAction *scales = new QAction( str , menuScales );
|
||||
scales->setCheckable( true );
|
||||
menuScales->addAction( scales );
|
||||
actionVector.append( scales );
|
||||
connect( scales , SIGNAL( triggered( bool ) ), this, SLOT( slotGetScaleIndex( bool ) ) );
|
||||
|
||||
scaleGroup->addAction( scales );
|
||||
}
|
||||
connect( this, SIGNAL( actionScaleIndex(int) ), this, SLOT( slotFilterMap( int ) ) );
|
||||
|
||||
scrollBarAction = new QAction( tr( "Scroll Bars" ), menuView );
|
||||
scrollBarAction->setCheckable( true );
|
||||
scrollBarAction->setChecked( true );
|
||||
menuView->addAction( scrollBarAction );
|
||||
connect( scrollBarAction, SIGNAL( triggered(bool) ), this, SLOT( slotScrollBarsView( bool ) ) );
|
||||
|
||||
gridAction = new QAction( tr( "Grid"), menuView );
|
||||
gridAction->setCheckable( true );
|
||||
gridAction->setChecked( false );
|
||||
menuView->addAction( gridAction );
|
||||
connect( gridAction, SIGNAL( triggered( bool ) ), this, SLOT( slotGrid( bool ) ) );
|
||||
|
||||
suffixAction = new QAction( tr( "Show GCM name" ), menuView );
|
||||
suffixAction->setCheckable( true );
|
||||
suffixAction->setChecked( false );
|
||||
menuView->addAction( suffixAction );
|
||||
connect( suffixAction, SIGNAL( triggered( bool ) ), this, SLOT( slotShowSuffix( bool ) ) );
|
||||
|
||||
QMenu* menuControl = new QMenu( tr( "Control" ), this );
|
||||
menuControl->addAction( tr( "Download maps" ), this, SLOT( slotDownloadMaps() ) );
|
||||
menuControl->addSeparator();
|
||||
menuControl->addAction( tr( "Overwrite cache" ), e, SLOT( overwriteCache() ) );
|
||||
menuControl->addAction( tr( "Syncronize cache" ), e, SLOT( updateCache() ) );
|
||||
menuControl->addAction( tr( "Update cache" ), e, SLOT( updateCacheSoft() ) );
|
||||
|
||||
ui->mainMenu->addMenu( menuMain );
|
||||
ui->mainMenu->addMenu( menuView );
|
||||
ui->mainMenu->addMenu( menuControl );
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::slotScrollBarsView( bool flag )
|
||||
{
|
||||
DriverMapPage *w = tabs->getCurrentPage();
|
||||
|
||||
if ( w )
|
||||
{
|
||||
w->setScrollBarsEnabled( flag );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::slotGrid( bool flag )
|
||||
{
|
||||
DriverMapPage *w = tabs->getCurrentPage();
|
||||
|
||||
if ( w )
|
||||
{
|
||||
w->changeGridState( flag );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::slotShowSuffix( bool flag )
|
||||
{
|
||||
DriverMapPage *w = tabs->getCurrentPage();
|
||||
|
||||
if ( w )
|
||||
{
|
||||
w->changeSuffixState( flag );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::slotFilterMap( int index )
|
||||
{
|
||||
DriverMapPage *w = tabs->getCurrentPage();
|
||||
|
||||
if ( w )
|
||||
{
|
||||
int32_point_t tmp = scaleVector.value( index );
|
||||
int lower_limit = tmp.x;
|
||||
int upper_limit = tmp.y;
|
||||
|
||||
w->setScaleFilter( lower_limit, upper_limit );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::slotSetFullScreenGeometry()
|
||||
{
|
||||
geometry_rect = QApplication::desktop()->screenGeometry( this );
|
||||
setGeometry( 0, 0, geometry_rect.width() - 9, geometry_rect.height() - menuBar()->height() );
|
||||
}
|
||||
|
||||
void MainWindow::slotGetScaleIndex( bool flag )
|
||||
{
|
||||
if ( flag )
|
||||
{
|
||||
emit actionScaleIndex( actionVector.indexOf( dynamic_cast <QAction*>( sender() ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::slotChangeTabAnalyzer( int index )
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
DriverMapPage *current_page = tabs->getCurrentPage();
|
||||
|
||||
if ( current_page )
|
||||
{
|
||||
int scale_index = 0;
|
||||
for( int i = 0; i < scaleVector.size(); i++ )
|
||||
{
|
||||
if ( ( scaleVector.value( i ).x == current_page->scaling_point.x ) &&
|
||||
( scaleVector.value( i ).y == current_page->scaling_point.y ) )
|
||||
{
|
||||
scale_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
actionVector.at( scale_index )->setChecked( true );
|
||||
scrollBarAction->setChecked( current_page->scrollBarFlag );
|
||||
gridAction->setChecked( current_page->gridFlag );
|
||||
suffixAction->setChecked( current_page->suffixFlag );
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::slotStartLinker( bool flag )
|
||||
{
|
||||
Q_UNUSED(flag);
|
||||
|
||||
if ( !linkerProcessBlockingFlag )
|
||||
{
|
||||
linkerProcessBlockingFlag = true;
|
||||
|
||||
DriverMapPage *current_page = tabs->getCurrentPage();
|
||||
if ( current_page )
|
||||
{
|
||||
const char *gis_root = gis_helper_env_get_gis_root_directory();
|
||||
QString program = QString( gis_root ) + "/" + QString( GIS_EXEC_PATH_SXF_LINKER );
|
||||
|
||||
linkerProcess = new QProcess( this );
|
||||
connect( linkerProcess, SIGNAL( finished( int ) ), this, SLOT( slotResetPage( int ) ) );
|
||||
connect( linkerProcess, SIGNAL( finished( int ) ), this, SLOT( slotLinkerFlag( int ) ) );
|
||||
connect( linkerProcess, SIGNAL( finished( int, QProcess::ExitStatus ) ),
|
||||
this, SLOT(slotLinkerDebug( int, QProcess::ExitStatus ) ) );
|
||||
|
||||
linkerProcess->setProcessChannelMode( QProcess::ForwardedChannels );
|
||||
|
||||
QPoint pos = this->mapToGlobal( QPoint( 0,0 ) );
|
||||
linkerProcess->start( program, { "-x" + QString::number( pos.x() ),
|
||||
"-y" + QString::number( pos.y() ) } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::slotLinkerFlag( int exitCode )
|
||||
{
|
||||
Q_UNUSED( exitCode );
|
||||
linkerProcessBlockingFlag = false;
|
||||
linkerProcess = nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::slotLinkerDebug( int exitCode, QProcess::ExitStatus status )
|
||||
{
|
||||
qDebug() << "exitcode" << exitCode << "status" << status;
|
||||
}
|
||||
|
||||
void MainWindow::slotResetPage( int flag )
|
||||
{
|
||||
Q_UNUSED( flag );
|
||||
DriverMapPage *current_page = tabs->getCurrentPage();
|
||||
|
||||
if ( current_page )
|
||||
{
|
||||
current_page->updatePage();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::slotAddMap()
|
||||
{
|
||||
MapAdder add( this );
|
||||
add.exec();
|
||||
|
||||
e->updateCache();
|
||||
}
|
||||
|
||||
void MainWindow::slotDownloadMaps()
|
||||
{
|
||||
if ( !loaderProcessBlockingFlag )
|
||||
{
|
||||
loaderProcessBlockingFlag = true;
|
||||
|
||||
DriverMapPage *current_page = tabs->getCurrentPage();
|
||||
if ( current_page )
|
||||
{
|
||||
const char *gis_root = gis_helper_env_get_gis_root_directory();
|
||||
QString program = QString( gis_root ) + "/" + QString( GIS_EXEC_PATH_MAP_LOADER );
|
||||
QStringList arguments;
|
||||
arguments << "-d" << QString::number( current_page->getDriverId() );
|
||||
|
||||
loaderProcess = new QProcess( this );
|
||||
connect( loaderProcess, SIGNAL( finished( int ) ), this, SLOT( slotResetPage( int ) ) );
|
||||
connect( loaderProcess, SIGNAL( finished( int ) ), this, SLOT( slotLoaderFlag( int ) ) );
|
||||
loaderProcess->setProcessChannelMode( QProcess::ForwardedChannels );
|
||||
loaderProcess->start( program, arguments );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::slotLoaderFlag( int exitCode )
|
||||
{
|
||||
Q_UNUSED(exitCode);
|
||||
loaderProcessBlockingFlag = false;
|
||||
}
|
128
src/apps/gis-monitor/mainwindow.h
Обычный файл
@ -0,0 +1,128 @@
|
||||
/*
|
||||
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 MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QPointer>
|
||||
|
||||
#include "drivermappage.h"
|
||||
#include "drivertabs.h"
|
||||
#include "engine.h"
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <gis/gisrender.h>
|
||||
|
||||
struct CleanExit
|
||||
{
|
||||
CleanExit()
|
||||
{
|
||||
signal( SIGINT, &CleanExit::exitQt );
|
||||
signal( SIGTERM, &CleanExit::exitQt );
|
||||
}
|
||||
|
||||
static void exitQt( int sig )
|
||||
{
|
||||
Q_UNUSED( sig );
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
};
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow( Engine *en, QWidget *parent = 0 );
|
||||
~MainWindow();
|
||||
|
||||
QPointer <Engine> e;
|
||||
|
||||
private:
|
||||
void initializeMenu();
|
||||
void scalesInitialize();
|
||||
QRect geometry_rect;
|
||||
QVector <QAction*> actionVector;
|
||||
QVector <int32_point_t> scaleVector;
|
||||
Ui::MainWindow *ui;
|
||||
QMenu *menuMain;
|
||||
DriverTabs *tabs;
|
||||
QAction *scrollBarAction;
|
||||
QAction *gridAction;
|
||||
QAction *suffixAction;
|
||||
QAction *controlAction;
|
||||
QAction *scalesAction;
|
||||
QAction *linkerAction;
|
||||
QActionGroup *scaleGroup;
|
||||
|
||||
QProcess *linkerProcess;
|
||||
bool linkerProcessBlockingFlag;
|
||||
|
||||
QProcess *loaderProcess;
|
||||
bool loaderProcessBlockingFlag;
|
||||
|
||||
const int min_height;
|
||||
const int min_width;
|
||||
|
||||
protected:
|
||||
void resizeEvent( QResizeEvent * event );
|
||||
|
||||
private slots:
|
||||
void slotChangeTabAnalyzer( int index );
|
||||
|
||||
void slotHardReset();
|
||||
void slotSoftReset();
|
||||
void slotResetPage( int flag );
|
||||
|
||||
void slotScrollBarsView( bool );
|
||||
void slotGrid( bool );
|
||||
void slotSetFullScreenGeometry();
|
||||
void slotGetScaleIndex( bool );
|
||||
void slotFilterMap( int );
|
||||
void slotStartLinker( bool flag );
|
||||
void slotLinkerFlag( int );
|
||||
void slotShowSuffix( bool );
|
||||
void slotDownloadMaps();
|
||||
void slotAddMap();
|
||||
void slotLoaderFlag( int exitCode );
|
||||
|
||||
void showAboutDialog() { gis_gui_about( e->connection, this ); }
|
||||
|
||||
void slotLinkerDebug( int exitCode, QProcess::ExitStatus status );
|
||||
|
||||
signals:
|
||||
void endInit();
|
||||
void actionScaleIndex( int );
|
||||
void closeDriverMapPage(int);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
49
src/apps/gis-monitor/mainwindow.ui
Обычный файл
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>731</width>
|
||||
<height>599</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>615</width>
|
||||
<height>460</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>GIS Monitor</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget"/>
|
||||
<widget class="QMenuBar" name="mainMenu">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>731</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="defaultUp">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="nativeMenuBar">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
222
src/apps/gis-monitor/mapadder.cpp
Обычный файл
@ -0,0 +1,222 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mapadder.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gis_types.h>
|
||||
|
||||
MapAdder::MapAdder( QWidget *parent ) :
|
||||
QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
|
||||
mapNames( new QTextEdit(this) )
|
||||
{
|
||||
mapNames->setReadOnly( true );
|
||||
|
||||
QPushButton *applyBtn = new QPushButton( tr( "Apply" ) );
|
||||
connect( applyBtn, SIGNAL( clicked( bool ) ), this, SLOT( applyBtnClicked( bool ) ) );
|
||||
|
||||
QPushButton *openMapBtn = new QPushButton( tr( "Add file" ) );
|
||||
connect( openMapBtn, SIGNAL( clicked( bool ) ), this, SLOT( mapOpenDialog( bool ) ) );
|
||||
|
||||
QPushButton *openMapFolderButton = new QPushButton( tr( "Add folder (SHP only)" ) );
|
||||
connect( openMapFolderButton, SIGNAL( clicked( bool ) ), this, SLOT( mapFolderOpenDialog( bool ) ) );
|
||||
|
||||
QGridLayout *mainLayout = new QGridLayout;
|
||||
|
||||
mainLayout->addWidget( new QLabel( tr( "Files to copy:" ) ), 0, 0, 1, 6 );
|
||||
mainLayout->addWidget( mapNames, 1, 0, 3, 6 );
|
||||
mainLayout->addWidget( openMapBtn, 1, 6, 1, 1 );
|
||||
mainLayout->addWidget( openMapFolderButton, 2, 6, 1, 1 );
|
||||
mainLayout->addWidget( applyBtn, 3, 6, 1, 1 );
|
||||
|
||||
setLayout( mainLayout );
|
||||
setWindowTitle( tr( "Add map" ) );
|
||||
|
||||
setMaximumSize( 400, 200 );
|
||||
}
|
||||
|
||||
void MapAdder::applyBtnClicked( bool clicked )
|
||||
{
|
||||
Q_UNUSED( clicked );
|
||||
|
||||
QString format_folder;
|
||||
|
||||
for ( auto path : mapPaths )
|
||||
{
|
||||
QFileInfo fi( path );
|
||||
QString cached_copy_path;
|
||||
|
||||
bool isDir = false;
|
||||
QString map_name = fi.fileName();
|
||||
|
||||
if ( map_name.contains( ".000", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/S-57/";
|
||||
}
|
||||
else if ( map_name.contains( ".sxf", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/sxf/";
|
||||
}
|
||||
else if ( map_name.contains( ".rsc", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/sxf/rsc/";
|
||||
}
|
||||
else if ( map_name.contains( ".shp", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/Shapefile/";
|
||||
isDir = true;
|
||||
}
|
||||
else if ( map_name.contains( ".mtw", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/mtw/";
|
||||
}
|
||||
else if ( map_name.contains( ".tif", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/GeoTIFF/";
|
||||
}
|
||||
else if ( map_name.contains( ".jp2", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".j2k", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".jpf", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".jpm", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".jpg2", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".j2c", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".jpc", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".jpx", Qt::CaseInsensitive ) ||
|
||||
map_name.contains( ".mj2", Qt::CaseInsensitive ) )
|
||||
{
|
||||
format_folder = "/JPEG2000/";
|
||||
}
|
||||
|
||||
cached_copy_path += gis_helper_env_get_maps_cache_directory() +
|
||||
QString( "/" ) + format_folder + QString( "/" ) + fi.fileName();
|
||||
|
||||
bool isCopied = false;
|
||||
|
||||
if ( !isDir )
|
||||
{
|
||||
isCopied = QFile::copy( path, cached_copy_path );
|
||||
}
|
||||
else
|
||||
{
|
||||
isCopied = MapAdder::cpDir( path, cached_copy_path );
|
||||
}
|
||||
|
||||
if ( !isCopied )
|
||||
{
|
||||
QMessageBox box;
|
||||
box.setText( tr( "Failed to copy file:" ) + path + "\n" + tr( "File exists" ) );
|
||||
box.setIcon( QMessageBox::Warning );
|
||||
box.exec();
|
||||
}
|
||||
}
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
void MapAdder::mapOpenDialog( bool unused )
|
||||
{
|
||||
Q_UNUSED( unused );
|
||||
|
||||
QFileDialog dialog( this );
|
||||
dialog.setFileMode( QFileDialog::ExistingFiles );
|
||||
dialog.setViewMode( QFileDialog::Detail );
|
||||
|
||||
if ( dialog.exec() )
|
||||
{
|
||||
for ( auto path : dialog.selectedFiles() )
|
||||
{
|
||||
mapNames->append( path );
|
||||
mapPaths.append( path );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapAdder::mapFolderOpenDialog( bool unused )
|
||||
{
|
||||
Q_UNUSED( unused );
|
||||
|
||||
QFileDialog dialog( this );
|
||||
dialog.setFileMode( QFileDialog::Directory );
|
||||
dialog.setViewMode( QFileDialog::Detail );
|
||||
|
||||
if ( dialog.exec() )
|
||||
{
|
||||
for ( auto path : dialog.selectedFiles() )
|
||||
{
|
||||
mapNames->append( path );
|
||||
mapPaths.append( path );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MapAdder::cpDir( const QString &srcPath, const QString &dstPath )
|
||||
{
|
||||
QFileInfo dstDir( dstPath );
|
||||
|
||||
if ( dstDir.exists() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir parentDstDir( dstDir.path() );
|
||||
|
||||
if ( !parentDstDir.mkdir( dstDir.fileName() ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir srcDir( srcPath );
|
||||
foreach ( const QFileInfo &info, srcDir.entryInfoList( QDir::Dirs |
|
||||
QDir::Files |
|
||||
QDir::NoDotAndDotDot ) )
|
||||
{
|
||||
QString srcItemPath = srcPath + "/" + info.fileName();
|
||||
QString dstItemPath = dstPath + "/" + info.fileName();
|
||||
|
||||
if ( info.isDir() )
|
||||
{
|
||||
if ( !cpDir( srcItemPath, dstItemPath ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( info.isFile() )
|
||||
{
|
||||
if ( !QFile::copy( srcItemPath, dstItemPath ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Unhandled item" << info.filePath() << "in cpDir";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
47
src/apps/gis-monitor/mapadder.h
Обычный файл
@ -0,0 +1,47 @@
|
||||
/*
|
||||
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 MAPADDER_H
|
||||
#define MAPADDER_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTextEdit>
|
||||
#include <QWidget>
|
||||
|
||||
class MapAdder : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MapAdder( QWidget *parent = NULL );
|
||||
private:
|
||||
static bool cpDir( const QString &srcPath, const QString &dstPath );
|
||||
|
||||
QStringList mapPaths;
|
||||
QTextEdit *mapNames;
|
||||
|
||||
private slots:
|
||||
void applyBtnClicked( bool clicked );
|
||||
void mapOpenDialog( bool unused );
|
||||
void mapFolderOpenDialog( bool unused );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
640
src/apps/gis-monitor/mapcanvas.cpp
Обычный файл
@ -0,0 +1,640 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mapcanvas.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define GIS_MONITOR_MAP_CANVAS_PREFIX "[MapCanvas] "
|
||||
|
||||
double MapCanvas::SVG_W_PIXELS = 1049;
|
||||
double MapCanvas::SVG_H_PIXELS = 898;
|
||||
|
||||
MapCanvas::MapCanvas( QObject *parent ) : QGraphicsScene( parent ),
|
||||
current_rect( nullptr ),
|
||||
svgMap( nullptr ),
|
||||
scalingRectItem( nullptr ),
|
||||
brush( QColor( 150, 150, 150, 127 ) ),
|
||||
pen( QBrush( QColor( 60, 60, 60, 255 ) ), 0,
|
||||
Qt::SolidLine,
|
||||
Qt::SquareCap,
|
||||
Qt::MiterJoin ),
|
||||
mousePressedFlag( false ),
|
||||
scalingAreaFlag( false )
|
||||
{
|
||||
|
||||
svg_width_m = 20026376.39 - (-20026376.39);
|
||||
svg_height_m = 18764656.23 - (-15496570.74);
|
||||
svg_width = 180.0 - (-180.0);
|
||||
svg_height = 84.0 - (-80.0);
|
||||
|
||||
view_scale.x = svg_width_m / MapCanvas::SVG_W_PIXELS;
|
||||
view_scale.y = svg_height_m / MapCanvas::SVG_H_PIXELS;
|
||||
|
||||
connect( this, SIGNAL( getMousePress( QPointF ) ),
|
||||
this, SLOT( slotScalingRectangle( QPointF ) ) );
|
||||
|
||||
gis_map_projection_init( &projection );
|
||||
gis_helper_math_init_ctx( &math_ctx );
|
||||
projection.projection_idx = GIS_PROJECTION_MERC_PSEUDO;
|
||||
projection.ellipsoid_idx = GIS_ELLIPSOID_WGS84;
|
||||
gis_helper_math_generate_meters_projection( math_ctx, &projection );
|
||||
|
||||
if ( svgMap == NULL )
|
||||
{
|
||||
svgMap = new QGraphicsSvgItem( QString(":/background/mercator.svg") );
|
||||
addItem( svgMap );
|
||||
}
|
||||
|
||||
setSceneRect( svgMap->boundingRect() );
|
||||
}
|
||||
|
||||
MapCanvas::~MapCanvas()
|
||||
{
|
||||
foreach ( QGraphicsItem *it, items() )
|
||||
removeItem( it );
|
||||
|
||||
if ( svgMap )
|
||||
delete svgMap;
|
||||
|
||||
for ( auto ¤t_selected : selected_rects_v )
|
||||
{
|
||||
delete current_selected;
|
||||
}
|
||||
|
||||
selected_rects_v.clear();
|
||||
|
||||
removeAllRects();
|
||||
|
||||
gis_helper_math_free_ctx( &math_ctx );
|
||||
}
|
||||
|
||||
void MapCanvas::removeAllRects()
|
||||
{
|
||||
for ( const auto &pair : map_rects_qmap )
|
||||
{
|
||||
std::vector<MapRectItem*> &gr_item_rects_vector = *pair.second;
|
||||
|
||||
for ( auto &rect : gr_item_rects_vector )
|
||||
{
|
||||
delete rect;
|
||||
}
|
||||
|
||||
gr_item_rects_vector.clear();
|
||||
}
|
||||
|
||||
clearMapWithPointers<int, std::vector<MapRectItem*>>( map_rects_qmap );
|
||||
}
|
||||
|
||||
QGraphicsItem *MapCanvas::getMapRectItemToCenter( int map_idx )
|
||||
{
|
||||
std::vector<MapRectItem*> *gr_item_rects_vector;
|
||||
|
||||
auto pair_map_rects = map_rects_qmap.find( map_idx );
|
||||
if ( pair_map_rects != map_rects_qmap.end() )
|
||||
{
|
||||
gr_item_rects_vector = pair_map_rects->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( gr_item_rects_vector->empty() )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return gr_item_rects_vector->at( 0 );
|
||||
}
|
||||
|
||||
void MapCanvas::addSelectionRectangle( gis_borders_t borders )
|
||||
{
|
||||
static QPen selPen( QBrush( QColor( 60, 0, 0, 255) ), 0,
|
||||
Qt::SolidLine,
|
||||
Qt::SquareCap,
|
||||
Qt::MiterJoin );
|
||||
|
||||
removeAllSelection();
|
||||
|
||||
QVector<QRectF> rects_v;
|
||||
gis_convert_deg2px( borders, rects_v );
|
||||
|
||||
for ( const auto &rect: rects_v )
|
||||
{
|
||||
QGraphicsRectItem *current = addRect( rect, selPen, QColor( 150, 0, 0, 127 ) );
|
||||
selected_rects_v.push_back( current );
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void MapCanvas::addMapRectangle( int map_idx, gis_borders_t borders, QObject* w )
|
||||
{
|
||||
removeAllSelection();
|
||||
|
||||
QVector<QRectF> rects_v;
|
||||
|
||||
MapRectItem::RectType rect_type;
|
||||
gis_convert_deg2px( borders, rects_v, &rect_type );
|
||||
|
||||
std::vector<MapRectItem*> *gr_item_rects_vector;
|
||||
|
||||
auto pair_map_rects = map_rects_qmap.find( map_idx );
|
||||
if ( pair_map_rects != map_rects_qmap.end() )
|
||||
{
|
||||
gr_item_rects_vector = pair_map_rects->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
gr_item_rects_vector = new std::vector<MapRectItem*>;
|
||||
map_rects_qmap.emplace( map_idx, gr_item_rects_vector );
|
||||
}
|
||||
|
||||
for ( const auto &rect : rects_v )
|
||||
{
|
||||
current_rect = new MapRectItem( rect.x(), rect.y(), rect.width(), rect.height(), rect_type );
|
||||
current_rect->setBrush( brush );
|
||||
current_rect->setPen( pen );
|
||||
|
||||
QObject *o = dynamic_cast<QObject *>( this );
|
||||
o->connect( current_rect, SIGNAL( getRectClick( QPointF ) ),
|
||||
w, SLOT( slotSelectMapRect( QPointF ) ) );
|
||||
|
||||
o->connect( current_rect, SIGNAL( getRectDoubleClick( QPointF ) ),
|
||||
this, SLOT( rectDoubleClick( QPointF ) ) );
|
||||
|
||||
gr_item_rects_vector->push_back( current_rect );
|
||||
addItem( current_rect );
|
||||
}
|
||||
}
|
||||
|
||||
void MapCanvas::slotScalingRectangle( QPointF point )
|
||||
{
|
||||
if ( scalingRectItem )
|
||||
{
|
||||
removeItem( scalingRectItem );
|
||||
delete scalingRectItem;
|
||||
scalingRectItem = nullptr;
|
||||
}
|
||||
|
||||
scalingRectItem = new QGraphicsRectItem( 0, 0, 1, 1 );
|
||||
scalingRectItem->setBrush( brush );
|
||||
scalingRectItem->setPen( pen );
|
||||
addItem( scalingRectItem );
|
||||
scalingRectItem->setPos( point );
|
||||
|
||||
}
|
||||
|
||||
void MapCanvas::gis_convert_deg2px( gis_borders_t borders, QVector<QRectF> &rects_v,
|
||||
MapRectItem::RectType *type )
|
||||
{
|
||||
rects_v.clear();
|
||||
|
||||
double_point_t upper_left, lower_right, svg_ul;
|
||||
double_point_t nw_point = { borders.degrees.west, borders.degrees.north };
|
||||
double_point_t se_point = { borders.degrees.east, borders.degrees.south };
|
||||
double_point_t ul_point = { -180, 84 };
|
||||
|
||||
if ( gis_helper_convert_point_degrees_2_meters( math_ctx, &ul_point, &svg_ul ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
if ( gis_helper_convert_point_degrees_2_meters( math_ctx, &nw_point, &upper_left ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
if ( gis_helper_convert_point_degrees_2_meters( math_ctx, &se_point, &lower_right ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
QRectF base_rect;
|
||||
QRectF odd_rect;
|
||||
|
||||
bool flag_need_odd = false;
|
||||
|
||||
double top, odd_top = 0;
|
||||
double bottom, odd_bottom = 0;
|
||||
double right, odd_right = 0;
|
||||
double left, odd_left = 0;
|
||||
|
||||
left = ( upper_left.x - svg_ul.x ) / view_scale.x;
|
||||
|
||||
odd_right = ( lower_right.x - svg_ul.x ) / view_scale.x;
|
||||
odd_bottom = -1 * ( lower_right.y - svg_ul.y ) / view_scale.y;
|
||||
|
||||
MapRectItem::RectType tmp_type = MapRectItem::RectType::COMMON;
|
||||
|
||||
if ( upper_left.x > lower_right.x )
|
||||
{
|
||||
tmp_type = MapRectItem::RectType::COMPOSITE_HORIZONTAL;
|
||||
right = MapCanvas::SVG_W_PIXELS;
|
||||
flag_need_odd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
odd_left = left;
|
||||
right = odd_right;
|
||||
}
|
||||
|
||||
top = -1 * ( upper_left.y - svg_ul.y ) / view_scale.y;
|
||||
|
||||
if ( lower_right.y > upper_left.y )
|
||||
{
|
||||
tmp_type = MapRectItem::RectType::COMPOSITE_VERTICAL;
|
||||
bottom = MapCanvas::SVG_H_PIXELS;
|
||||
flag_need_odd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
odd_top = top;
|
||||
bottom = odd_bottom;
|
||||
}
|
||||
|
||||
if ( type )
|
||||
{
|
||||
*type = tmp_type;
|
||||
}
|
||||
|
||||
base_rect.setTopLeft( QPointF( left, top ) );
|
||||
base_rect.setBottomRight( QPointF( right, bottom ) );
|
||||
|
||||
rects_v.push_back( base_rect );
|
||||
|
||||
if ( flag_need_odd )
|
||||
{
|
||||
odd_rect.setTopLeft( QPointF( odd_left, odd_top ) );
|
||||
odd_rect.setBottomRight( QPointF( odd_right, odd_bottom ) );
|
||||
rects_v.push_back( odd_rect );
|
||||
}
|
||||
}
|
||||
|
||||
double_point_t MapCanvas::gis_convert_deg2px( double_point_t *point )
|
||||
{
|
||||
double_point_t m_pnt, svg_ul;
|
||||
double_point_t ul_point = { -180, 84 };
|
||||
if ( gis_helper_convert_point_degrees_2_meters( math_ctx, &ul_point, &svg_ul ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
if ( gis_helper_convert_point_degrees_2_meters( math_ctx, point, &m_pnt ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
m_pnt.x = ( m_pnt.x - svg_ul.x ) / view_scale.x;
|
||||
m_pnt.y = ( m_pnt.y + svg_ul.y ) / view_scale.y;
|
||||
|
||||
return m_pnt;
|
||||
}
|
||||
|
||||
double_point_t MapCanvas::gis_convert_px2deg( double_point_t *point )
|
||||
{
|
||||
double_point_t m_pnt, deg_pnt, svg_center;
|
||||
double_point_t center_point = { -180, 84 };
|
||||
|
||||
if ( gis_helper_convert_point_degrees_2_meters( math_ctx, ¢er_point, &svg_center ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
m_pnt.x = point->x * view_scale.x - svg_center.x;
|
||||
m_pnt.y = -( point->y * view_scale.y - svg_center.y );
|
||||
|
||||
if ( gis_helper_convert_point_meters_2_degrees( math_ctx, °_pnt, &m_pnt ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, GIS_MONITOR_MAP_CANVAS_PREFIX,
|
||||
"Calculation failed [%s()]", __FUNCTION__ );
|
||||
}
|
||||
|
||||
return deg_pnt;
|
||||
}
|
||||
|
||||
void MapCanvas::rectDoubleClick( QPointF point )
|
||||
{
|
||||
double_point_t px_pnt;
|
||||
px_pnt.x = point.x();
|
||||
px_pnt.y = point.y();
|
||||
|
||||
emit getDoubleClick( gis_convert_px2deg( &px_pnt ) );
|
||||
|
||||
}
|
||||
|
||||
void MapCanvas::slotShowGrid( bool flag )
|
||||
{
|
||||
double_point_t point, px_point;
|
||||
|
||||
if ( flag )
|
||||
{
|
||||
QPen grid_pen( Qt::darkGray );
|
||||
for ( int i = 0; i < 37; i++ )
|
||||
{
|
||||
point.x = -180 + 10 * i;
|
||||
point.y = 0;
|
||||
px_point = gis_convert_deg2px( &point );
|
||||
if ( i == 18 )
|
||||
grid_pen.setColor( Qt::black );
|
||||
else
|
||||
grid_pen.setColor( Qt::darkGray );
|
||||
|
||||
addLine( px_point.x, 0, px_point.x, height(), grid_pen );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < 17; i++ )
|
||||
{
|
||||
point.x = 0;
|
||||
point.y = -80 + 10 * i;
|
||||
px_point = gis_convert_deg2px( &point );
|
||||
if ( i == 8 )
|
||||
grid_pen.setColor( Qt::black );
|
||||
else
|
||||
grid_pen.setColor( Qt::darkGray );
|
||||
|
||||
addLine( 0, px_point.y, width(), px_point.y, grid_pen );
|
||||
}
|
||||
update( 0, 0, width(), height() );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int k = 0; k < items().length(); k++ )
|
||||
{
|
||||
QGraphicsItem *item = items().at( k );
|
||||
if ( item->type() == QGraphicsLineItem::Type )
|
||||
{
|
||||
removeItem( item );
|
||||
delete item;
|
||||
k--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapRectItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
|
||||
{
|
||||
if ( m_rect_type == MapRectItem::RectType::COMMON )
|
||||
{
|
||||
QGraphicsRectItem::paint( painter, option, widget );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QRectF rect = this->rect();
|
||||
QPen saved_pen = painter->pen();
|
||||
QBrush saved_brush = painter->brush();
|
||||
|
||||
painter->setPen( this->pen() );
|
||||
|
||||
if ( m_rect_type == MapRectItem::RectType::COMPOSITE_HORIZONTAL )
|
||||
{
|
||||
painter->drawLine( rect.topLeft(), rect.topRight() );
|
||||
painter->drawLine( rect.bottomLeft(), rect.bottomRight() );
|
||||
|
||||
if ( rect.left() > 0 )
|
||||
{
|
||||
painter->drawLine( rect.topLeft(), rect.bottomLeft() );
|
||||
}
|
||||
|
||||
if ( rect.right() < MapCanvas::SVG_W_PIXELS )
|
||||
{
|
||||
painter->drawLine( rect.topRight(), rect.bottomRight() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_rect_type == MapRectItem::RectType::COMPOSITE_VERTICAL )
|
||||
{
|
||||
painter->drawLine( rect.topLeft(), rect.bottomLeft() );
|
||||
painter->drawLine( rect.topRight(), rect.bottomRight() );
|
||||
|
||||
if ( rect.top( ) > 0 )
|
||||
{
|
||||
painter->drawLine( rect.topLeft(), rect.topRight() );
|
||||
}
|
||||
|
||||
if ( rect.bottom( ) < MapCanvas::SVG_H_PIXELS )
|
||||
{
|
||||
painter->drawLine( rect.bottomLeft(), rect.bottomRight() );
|
||||
}
|
||||
}
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( this->brush() );
|
||||
|
||||
painter->drawRect( rect );
|
||||
|
||||
painter->setPen( saved_pen );
|
||||
painter->setBrush( saved_brush );
|
||||
}
|
||||
|
||||
void MapRectItem::mousePressEvent( QGraphicsSceneMouseEvent *event )
|
||||
{
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
{
|
||||
emit getRectClick( event->pos() );
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void MapRectItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
|
||||
{
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
{
|
||||
emit getRectDoubleClick( event->pos() );
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
|
||||
}
|
||||
|
||||
void MapCanvas::wheelEvent( QGraphicsSceneWheelEvent *event )
|
||||
{
|
||||
event->accept();
|
||||
if ( event->delta() > 0 )
|
||||
{
|
||||
emit increaseScale( true );
|
||||
}
|
||||
else if ( event->delta() < 0 )
|
||||
{
|
||||
emit decreaseScale( true );
|
||||
}
|
||||
}
|
||||
|
||||
void MapCanvas::mousePressEvent( QGraphicsSceneMouseEvent *event )
|
||||
{
|
||||
if ( event->button() == Qt::RightButton )
|
||||
{
|
||||
mousePressedFlag = true;
|
||||
bool unused = false;
|
||||
|
||||
emit scalingAreaFlagChanged( unused );
|
||||
|
||||
slotScalingRectangle( event->lastScenePos() );
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
else if ( scalingAreaFlag && ( event->button() == Qt::LeftButton ) )
|
||||
{
|
||||
mousePressedFlag = true;
|
||||
slotScalingRectangle( event->lastScenePos() );
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsScene::mousePressEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
void MapCanvas::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
|
||||
{
|
||||
if ( scalingAreaFlag )
|
||||
{
|
||||
if ( scalingRectItem )
|
||||
{
|
||||
QPointF pos = scalingRectItem->pos();
|
||||
QRectF r;
|
||||
r.setTopLeft( QPointF( 0,0 ) );
|
||||
r.setWidth( event->scenePos().x() - scalingRectItem->x() );
|
||||
r.setHeight( event->scenePos().y() - scalingRectItem->y() );
|
||||
|
||||
scalingRectItem->setRect( r );
|
||||
scalingRectItem->setPos( pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapCanvas::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
|
||||
{
|
||||
if ( scalingAreaFlag && mousePressedFlag )
|
||||
{
|
||||
mousePressedFlag = false;
|
||||
bool unused = false;
|
||||
emit scalingAreaFlagChanged( unused );
|
||||
|
||||
if ( scalingRectItem != nullptr )
|
||||
{
|
||||
|
||||
QRectF r;
|
||||
r.setTopLeft( scalingRectItem->pos() );
|
||||
r.setWidth( scalingRectItem->boundingRect().width() );
|
||||
r.setHeight( scalingRectItem->boundingRect().height() );
|
||||
|
||||
emit scalingAreaByRect( r.normalized() );
|
||||
|
||||
removeItem( scalingRectItem );
|
||||
delete scalingRectItem;
|
||||
scalingRectItem = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "mouseReleaseEvent(): scalingRectItem == nullptr!";
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void MapCanvas::removeAllSelection()
|
||||
{
|
||||
for ( auto ¤t_selected : selected_rects_v )
|
||||
{
|
||||
removeItem( current_selected );
|
||||
delete current_selected;
|
||||
}
|
||||
selected_rects_v.clear();
|
||||
}
|
||||
|
||||
void MapCanvas::setMapRectEnabled( int index, bool enabled )
|
||||
{
|
||||
std::vector<MapRectItem*> *gr_item_rects_vector;
|
||||
|
||||
auto pair_map_rects = map_rects_qmap.find( index );
|
||||
if ( pair_map_rects != map_rects_qmap.end() )
|
||||
{
|
||||
gr_item_rects_vector = pair_map_rects->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( const auto &rect : *gr_item_rects_vector )
|
||||
{
|
||||
if ( enabled )
|
||||
{
|
||||
rect->show();
|
||||
rect->setEnabled( enabled );
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->hide();
|
||||
rect->setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int MapCanvas::getMapIndexFromClickedRect( QPointF p )
|
||||
{
|
||||
qreal min_width = MapCanvas::SVG_W_PIXELS;
|
||||
qreal min_height = MapCanvas::SVG_H_PIXELS;
|
||||
|
||||
int min_clicked_rect_map_idx = -1;
|
||||
|
||||
for ( const auto &pair : map_rects_qmap )
|
||||
{
|
||||
std::vector<MapRectItem*> &gr_item_rects_vector = *pair.second;
|
||||
|
||||
for ( const auto &rect_gr_item : gr_item_rects_vector )
|
||||
{
|
||||
if ( rect_gr_item->contains( p ) && rect_gr_item->isEnabled() )
|
||||
{
|
||||
QRectF rect = rect_gr_item->rect();
|
||||
|
||||
if ( rect.width() < min_width )
|
||||
{
|
||||
min_width = rect.width();
|
||||
min_clicked_rect_map_idx = pair.first;
|
||||
}
|
||||
|
||||
if ( rect.height() < min_height )
|
||||
{
|
||||
min_height = rect.height();
|
||||
min_clicked_rect_map_idx = pair.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return min_clicked_rect_map_idx;
|
||||
}
|
||||
|
153
src/apps/gis-monitor/mapcanvas.h
Обычный файл
@ -0,0 +1,153 @@
|
||||
/*
|
||||
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 MAPCANVAS_H
|
||||
#define MAPCANVAS_H
|
||||
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsSvgItem>
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
#include <gis/gis_math.h>
|
||||
|
||||
class MapRectItem : public QObject, public QGraphicsRectItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum RectType
|
||||
{
|
||||
COMMON,
|
||||
COMPOSITE_HORIZONTAL,
|
||||
COMPOSITE_VERTICAL
|
||||
};
|
||||
|
||||
MapRectItem( qreal x, qreal y, qreal width, qreal height, RectType rect_type, QGraphicsItem *parent = nullptr ) :
|
||||
QGraphicsRectItem( x, y, width, height, parent ), QObject( nullptr ),
|
||||
m_rect_type( rect_type )
|
||||
{}
|
||||
|
||||
void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr );
|
||||
|
||||
void mousePressEvent( QGraphicsSceneMouseEvent * );
|
||||
void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * );
|
||||
|
||||
signals:
|
||||
void getRectClick( QPointF point );
|
||||
void getRectDoubleClick( QPointF point );
|
||||
void getMousePress( QPointF point );
|
||||
|
||||
private:
|
||||
RectType m_rect_type;
|
||||
};
|
||||
|
||||
|
||||
class QGraphicsSvgItem;
|
||||
class DriverMapPage;
|
||||
|
||||
class MapCanvas : public QGraphicsScene
|
||||
{
|
||||
friend DriverMapPage;
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MapCanvas( QObject *parent = nullptr );
|
||||
~MapCanvas();
|
||||
|
||||
void addMapRectangle( int map_idx, gis_borders_t borders, QObject* w );
|
||||
|
||||
void addSelectionRectangle( gis_borders_t borders );
|
||||
|
||||
int getMapIndexFromClickedRect( QPointF p );
|
||||
QGraphicsItem *getMapRectItemToCenter( int map_idx );
|
||||
void removeAllSelection();
|
||||
void setMapRectEnabled( int index, bool enabled );
|
||||
void removeAllRects();
|
||||
|
||||
void gis_convert_deg2px( gis_borders_t borders, QVector<QRectF> &rects_v,
|
||||
MapRectItem::RectType *type = nullptr );
|
||||
double_point_t gis_convert_deg2px( double_point_t* point );
|
||||
double_point_t gis_convert_px2deg( double_point_t* point );
|
||||
|
||||
static double SVG_W_PIXELS;
|
||||
static double SVG_H_PIXELS;
|
||||
|
||||
private:
|
||||
void setPen(QPen newPen) { pen = newPen; }
|
||||
void mousePressEvent( QGraphicsSceneMouseEvent * );
|
||||
void mouseMoveEvent( QGraphicsSceneMouseEvent * );
|
||||
void mouseReleaseEvent( QGraphicsSceneMouseEvent * );
|
||||
void wheelEvent( QGraphicsSceneWheelEvent * );
|
||||
|
||||
template<typename T1,typename T2>
|
||||
void clearMapWithPointers( std::map<T1, T2 *> &map )
|
||||
{
|
||||
for ( auto &pair : map )
|
||||
{
|
||||
delete pair.second;
|
||||
}
|
||||
map.clear();
|
||||
}
|
||||
|
||||
QVector<QGraphicsRectItem*> selected_rects_v;
|
||||
MapRectItem *current_rect;
|
||||
std::map<int, std::vector<MapRectItem*>*> map_rects_qmap;
|
||||
QGraphicsSvgItem *svgMap;
|
||||
QGraphicsRectItem *scalingRectItem;
|
||||
|
||||
gis_map_projection_t projection;
|
||||
gis_helper_math_ctx_t math_ctx;
|
||||
|
||||
double svg_width_m;
|
||||
double svg_height_m;
|
||||
double svg_width;
|
||||
double svg_height;
|
||||
double_point_t view_scale;
|
||||
|
||||
QBrush brush;
|
||||
QPen pen;
|
||||
|
||||
bool mousePressedFlag;
|
||||
bool scalingAreaFlag;
|
||||
|
||||
public slots:
|
||||
void rectDoubleClick( QPointF );
|
||||
|
||||
private slots:
|
||||
void slotScalingRectangle( QPointF );
|
||||
void slotShowGrid( bool flag );
|
||||
|
||||
signals:
|
||||
void increaseScale( bool );
|
||||
void decreaseScale( bool );
|
||||
void getMousePress( QPointF );
|
||||
void getMouseRelease( QPointF );
|
||||
void getDoubleClick( double_point_t );
|
||||
void scalingAreaFlagChanged( bool );
|
||||
void scalingAreaByRect( QRectF );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
163
src/apps/gis-monitor/mapview.cpp
Обычный файл
@ -0,0 +1,163 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mapview.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
MapView::MapView( QGraphicsScene *scene, QWidget *parent ):
|
||||
QGraphicsView( scene, parent ),
|
||||
totalScaleFactor(1),
|
||||
_scale(1),
|
||||
fit( true )
|
||||
{
|
||||
setAttribute( Qt::WA_AcceptTouchEvents, true );
|
||||
}
|
||||
|
||||
void MapView::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
if ( fit )
|
||||
slotFitScale(true);
|
||||
}
|
||||
|
||||
bool MapView::viewportEvent( QEvent *event )
|
||||
{
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::TouchBegin:
|
||||
case QEvent::TouchUpdate:
|
||||
case QEvent::TouchEnd:
|
||||
{
|
||||
QTouchEvent *touchEvent = static_cast<QTouchEvent *>( event );
|
||||
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
|
||||
|
||||
if ( touchPoints.count() == 2 )
|
||||
{
|
||||
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
|
||||
const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
|
||||
qreal currentScaleFactor =
|
||||
QLineF( touchPoint0.pos(), touchPoint1.pos() ).length() /
|
||||
QLineF( touchPoint0.startPos(), touchPoint1.startPos() ).length();
|
||||
|
||||
if ( touchEvent->touchPointStates() & Qt::TouchPointReleased )
|
||||
{
|
||||
totalScaleFactor *= currentScaleFactor;
|
||||
currentScaleFactor = 1;
|
||||
}
|
||||
|
||||
setTransform(QTransform().scale( totalScaleFactor * currentScaleFactor,
|
||||
totalScaleFactor * currentScaleFactor ) );
|
||||
|
||||
_scale = totalScaleFactor * currentScaleFactor;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QGraphicsView::viewportEvent(event);
|
||||
}
|
||||
|
||||
void MapView::slotFitScale( bool flag )
|
||||
{
|
||||
Q_UNUSED(flag);
|
||||
|
||||
fit = true;
|
||||
|
||||
qreal w, h;
|
||||
double sw, sh;
|
||||
double factor;
|
||||
|
||||
fitInView( sceneRect(), Qt::KeepAspectRatio );
|
||||
centerOn( sceneRect().center() );
|
||||
|
||||
w = scene()->width() * _scale;
|
||||
h = scene()->height() * _scale;
|
||||
|
||||
sw = (double)geometry().width() / w;
|
||||
sh = (double)geometry().height() / h;
|
||||
factor = sw < sh ? sw : sh;
|
||||
|
||||
_scale *= factor;
|
||||
}
|
||||
|
||||
void MapView::slotIncreaseScale( bool flag )
|
||||
{
|
||||
Q_UNUSED( flag );
|
||||
|
||||
fit = false;
|
||||
|
||||
if ( _scale > 660 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scale *= 1.20;
|
||||
scale( 1.20, 1.20 );
|
||||
}
|
||||
|
||||
void MapView::slotDecreaseScale( bool flag )
|
||||
{
|
||||
Q_UNUSED( flag );
|
||||
|
||||
fit = false;
|
||||
|
||||
if ( ( scene()->height() * _scale < height() ) &&
|
||||
( scene()->width() * _scale < width() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scale *= 0.8;
|
||||
scale( 0.8, 0.8 );
|
||||
}
|
||||
|
||||
void MapView::scaleAreaByRect( QRectF rect )
|
||||
{
|
||||
uint dx = fabs( rect.width() );
|
||||
uint dy = fabs( rect.height() );
|
||||
|
||||
if ( (dx == 0) || (dy == 0) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fit = false;
|
||||
|
||||
double sw, sh;
|
||||
double factor;
|
||||
|
||||
sw = (double)geometry().width() / dx;
|
||||
sh = (double)geometry().height() / dy;
|
||||
factor = sw < sh ? sw : sh;
|
||||
|
||||
_scale = factor;
|
||||
if ( _scale > 660 )
|
||||
{
|
||||
_scale = 660;
|
||||
}
|
||||
|
||||
resetMatrix();
|
||||
scale( _scale, _scale );
|
||||
centerOn( rect.center() );
|
||||
}
|
52
src/apps/gis-monitor/mapview.h
Обычный файл
@ -0,0 +1,52 @@
|
||||
/*
|
||||
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 MAPVIEW_H
|
||||
#define MAPVIEW_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QTouchEvent>
|
||||
#include <QWidget>
|
||||
|
||||
class MapView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MapView( QGraphicsScene *scene, QWidget *parent );
|
||||
protected:
|
||||
bool viewportEvent( QEvent *event );
|
||||
void resizeEvent( QResizeEvent *event );
|
||||
private:
|
||||
qreal totalScaleFactor;
|
||||
qreal _scale;
|
||||
bool fit;
|
||||
|
||||
public slots:
|
||||
void slotFitScale( bool );
|
||||
private slots:
|
||||
void slotIncreaseScale( bool );
|
||||
void slotDecreaseScale( bool );
|
||||
void scaleAreaByRect( QRectF );
|
||||
};
|
||||
|
||||
#endif
|
6
src/apps/gis-monitor/translations.qrc
Обычный файл
@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>translations/gis-monitor_ru.ts</file>
|
||||
<file>translations/gis-monitor_ru.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
233
src/apps/gis-monitor/translations/gis-monitor_ru.ts
Обычный файл
@ -0,0 +1,233 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="ru_RU">
|
||||
<context>
|
||||
<name>DriverMapPage</name>
|
||||
<message>
|
||||
<source>Scale: </source>
|
||||
<translation>Масштаб: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class count: </source>
|
||||
<translation>Классы: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Object count: </source>
|
||||
<translation>Объекты: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Height: </source>
|
||||
<translation>Высоты: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source> m</source>
|
||||
<translation> м</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Projection: </source>
|
||||
<translation>Проекция: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ellipsoid: </source>
|
||||
<translation>Эллипсоид: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Height system: </source>
|
||||
<translation>Система высот: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Zone: </source>
|
||||
<translation>Зона: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Classifier: </source>
|
||||
<translation>Классификатор: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class code</source>
|
||||
<translation>Код класса</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Acronym</source>
|
||||
<translation>Акроним</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Object count</source>
|
||||
<translation>Число объектов</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Maps:</source>
|
||||
<translation>Карты:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Scale:
|
||||
</source>
|
||||
<translation>Масштаб:
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Class count:
|
||||
</source>
|
||||
<translation>Классы:
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Object count:</source>
|
||||
<translation>Объекты:
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Map property</source>
|
||||
<translation>Параметр</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Value</source>
|
||||
<translation>Значение</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Fit</source>
|
||||
<translation>Подогнать</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Area</source>
|
||||
<translation>Область</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Number of loaded maps: </source>
|
||||
<translation>Количество загруженных карт:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connection status: request failed</source>
|
||||
<translation>Статус соединения: запрос не выполнен</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Driver status: </source>
|
||||
<translation>Статус драйвера: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ready</source>
|
||||
<translation>готов</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>busy</source>
|
||||
<translation>занят</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update: </source>
|
||||
<translation>Корректура: </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<source>GIS Monitor</source>
|
||||
<translation>ГИС Монитор</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Main</source>
|
||||
<translation>Меню</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reset</source>
|
||||
<translation>Сброс</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add map</source>
|
||||
<translation>Добавить карту</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Maps and Styles</source>
|
||||
<translation>Карты и стили</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>About</source>
|
||||
<translation>О программе</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Exit</source>
|
||||
<translation>Выход</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>View</source>
|
||||
<translation>Вид</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Scales</source>
|
||||
<translation>Масштаб</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>All scales</source>
|
||||
<translation>Все масштабы</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Scroll Bars</source>
|
||||
<translation>Полосы прокрутки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Grid</source>
|
||||
<translation>Сетка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show GCM name</source>
|
||||
<translation>Полное имя GCM</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Control</source>
|
||||
<translation>Управление</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Overwrite cache</source>
|
||||
<translation>Переписать кэш</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Syncronize cache</source>
|
||||
<translation>Синхронизировать кэш</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update cache</source>
|
||||
<translation>Обновить кэш</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Download maps</source>
|
||||
<translation>Загрузка карт</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MapAdder</name>
|
||||
<message>
|
||||
<source>Apply</source>
|
||||
<translation>Применить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add file</source>
|
||||
<translation>Добавить файл</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add folder (SHP only)</source>
|
||||
<translation>Добавить папку с картой (Shapefile)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Files to copy:</source>
|
||||
<translation>Список файлов для копирования:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add map</source>
|
||||
<translation>Добавление карт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to copy file:</source>
|
||||
<translation>Не удалось скопировать файл:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>File exists</source>
|
||||
<translation>Файл уже существует</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<source>°</source>
|
||||
<translation>°</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
68
src/apps/gis-raster-preview/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,68 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( gis-raster-preview LANGUAGES CXX )
|
||||
|
||||
set( CMAKE_AUTOMOC ON )
|
||||
set( CMAKE_AUTOUIC ON )
|
||||
set( CMAKE_AUTORCC ON )
|
||||
|
||||
add_compile_options( -std=gnu++11 )
|
||||
add_compile_options( -enable-checking )
|
||||
add_compile_options( -Wno-ignored-attributes )
|
||||
|
||||
add_definitions( -DQT_DEPRECATED_WARNINGS )
|
||||
|
||||
find_package( Qt5
|
||||
COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
REQUIRED )
|
||||
|
||||
file( GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
images.qrc )
|
||||
|
||||
add_executable( gis-raster-preview ${SOURCES} )
|
||||
|
||||
target_include_directories( gis-raster-preview
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/public
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/private
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/formats/gcm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gisrender/qt_render/private )
|
||||
|
||||
target_link_libraries( gis-raster-preview
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
gishelper
|
||||
gisrender )
|
||||
|
||||
|
||||
install( TARGETS gis-raster-preview DESTINATION bin )
|
64
src/apps/gis-raster-preview/main.cpp
Обычный файл
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "rasterwidget.h"
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
gis_helper_debug_mode_setmask( GIS_DEBUG_MODE_STD );
|
||||
|
||||
const char *filepath = NULL;
|
||||
uint32_t x_pos = 0;
|
||||
uint32_t y_pos = 0;
|
||||
|
||||
int opt = 0;
|
||||
extern char *optarg;
|
||||
|
||||
while ( ( opt = getopt( argc, argv,"x:y:f:" ) ) != -1 )
|
||||
{
|
||||
switch ( opt )
|
||||
{
|
||||
case 'x':
|
||||
x_pos = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'y':
|
||||
y_pos = strtoul( optarg, NULL, 0 );
|
||||
break;
|
||||
case 'f':
|
||||
filepath = strdup( optarg );
|
||||
break;
|
||||
case '?':
|
||||
printf( "Error: unknown option\n" );
|
||||
exit(1);
|
||||
};
|
||||
};
|
||||
|
||||
CleanExit cleanExit;
|
||||
QApplication a( argc, argv );
|
||||
QString path( filepath );
|
||||
RasterWidget wgt( path );
|
||||
wgt.show();
|
||||
wgt.setGeometry( x_pos, y_pos, 0, 0 );
|
||||
|
||||
return a.exec();
|
||||
}
|
242
src/apps/gis-raster-preview/rastertab.cpp
Обычный файл
@ -0,0 +1,242 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "rastertab.h"
|
||||
|
||||
#include <raster_render.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define RASTER_VIEWER_PREFIX "[gis-raster-preview] "
|
||||
|
||||
extern bool reduce_copy;
|
||||
extern double prev_scale;
|
||||
extern int side_size;
|
||||
|
||||
RasterTab::RasterTab( const QString &filepath, QWidget *parent ) :
|
||||
QGraphicsView( new QGraphicsScene(), parent ),
|
||||
image_size( 0,0 ),
|
||||
ll( 0,0 ),
|
||||
ctx( NULL )
|
||||
{
|
||||
setDragMode( QGraphicsView::ScrollHandDrag );
|
||||
setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
|
||||
ctx = (gcm_raster_map_ctx_t*)calloc( 1, sizeof(*ctx) );
|
||||
|
||||
if ( !ctx )
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gcm_map_header_t head;
|
||||
gcm_read_file_header( filepath.toStdString().c_str(), &head );
|
||||
|
||||
if ( GIS_IS_CORE_MAP_DATA_SOURCE_VECTOR(head.data_source) )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, RASTER_VIEWER_PREFIX,
|
||||
"Got vector map [%s()]", __FUNCTION__ );
|
||||
|
||||
free( ctx );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if ( gcm_raster_parse_map( ctx, &head ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, RASTER_VIEWER_PREFIX,
|
||||
"Failed to parse raster map [%s()]", __FUNCTION__ );
|
||||
|
||||
free( ctx );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if ( gcm_raster_set_header_by_scale( ctx, prev_scale + 0.01 ) != EOK )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, RASTER_VIEWER_PREFIX,
|
||||
"Failed to set raster header [%s()]", __FUNCTION__ );
|
||||
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
gcm_raster_header_t *r_header = &ctx->r_headers[ctx->active_header_idx];
|
||||
m_px = r_header->meters_per_element;
|
||||
|
||||
if ( r_header->has_reduced_copy )
|
||||
{
|
||||
reduce_copy = true;
|
||||
prev_scale = ctx->r_headers[ctx->active_header_idx + 1].meters_per_element;
|
||||
}
|
||||
else
|
||||
{
|
||||
reduce_copy = false;
|
||||
}
|
||||
|
||||
const static double epsilon = 1e-9;
|
||||
min_height = r_header->min_value - epsilon;
|
||||
max_height = r_header->max_value + epsilon;
|
||||
|
||||
ll = QPointF( r_header->lower_left.x, r_header->lower_left.y );
|
||||
|
||||
image = new QImage( r_header->width_in_elements, r_header->height_in_elements, QImage::Format_ARGB32 );
|
||||
image_size = image->size();
|
||||
|
||||
gis_color_t color;
|
||||
color.full = 0xFF228B22;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFADFF2F;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFF7CFC00;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFF90EE90;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFF8B6508;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFEE7621;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFCD950C;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFEEAD0E;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFFFB90F;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFFFEBCD;
|
||||
colorMap.push_back( color );
|
||||
color.full = 0xFFFFFFE0;
|
||||
colorMap.push_back( color );
|
||||
|
||||
const double delta = ( max_height - min_height ) / ( colorMap.size() - 1 );
|
||||
|
||||
for ( int i = 0; i < colorMap.size(); ++i )
|
||||
{
|
||||
valueMap << min_height + delta * i;
|
||||
}
|
||||
|
||||
uint32_t block_x, block_y;
|
||||
for ( block_y = 0; block_y < r_header->height_in_blocks; ++block_y )
|
||||
{
|
||||
for ( block_x = 0; block_x < r_header->width_in_blocks; ++block_x )
|
||||
{
|
||||
draw_block( r_header, block_x, block_y );
|
||||
}
|
||||
}
|
||||
|
||||
scene()->addPixmap( QPixmap::fromImage( *image ) );
|
||||
|
||||
qreal sf = min( static_cast<qreal>( side_size - 50 ) / image->width(),
|
||||
static_cast<qreal>( side_size - 100 ) / image->height() );
|
||||
|
||||
scale( sf, sf );
|
||||
|
||||
setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
setDragMode( QGraphicsView::NoDrag );
|
||||
|
||||
}
|
||||
|
||||
RasterTab::~RasterTab()
|
||||
{
|
||||
free( ctx );
|
||||
delete image;
|
||||
}
|
||||
|
||||
void RasterTab::draw_block( gcm_raster_header_t *r_header, const uint32_t index_x, const uint32_t index_y )
|
||||
{
|
||||
const bool isCroppedWidth = index_x == r_header->width_in_blocks - 1;
|
||||
const bool isCroppedHeight = index_y == r_header->height_in_blocks - 1;
|
||||
|
||||
const uint32_t block_width = (isCroppedWidth) ? r_header->cropped_block_width : r_header->block_width;
|
||||
const uint32_t block_height = (isCroppedHeight) ? r_header->cropped_block_height : r_header->block_height;
|
||||
|
||||
const uint32_t index = index_x + index_y * r_header->width_in_blocks;
|
||||
|
||||
uint32_t draw_x, draw_y,
|
||||
offset_x = 0,
|
||||
offset_y = 0;
|
||||
|
||||
offset_x = r_header->block_width * index_x;
|
||||
offset_y = r_header->block_height * index_y;
|
||||
|
||||
gis_raster_value_t *block_data = (gis_raster_value_t *)calloc( block_width * block_height, sizeof(*block_data) );
|
||||
if ( !block_data )
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, RASTER_VIEWER_PREFIX,
|
||||
"Failed to allocate block_data memory [%s()]", __FUNCTION__ );
|
||||
return;
|
||||
}
|
||||
|
||||
gcm_raster_read_block_data( ctx, block_data, index );
|
||||
|
||||
uint32_t element_offset, str, col, color;
|
||||
uint32_t invalid_color = 0x00FF0000;
|
||||
gis_raster_value_t value, element_data;
|
||||
for ( str = 0; str < block_height; ++str )
|
||||
{
|
||||
for ( col = 0; col < block_width; ++col )
|
||||
{
|
||||
element_offset = str * block_width + col;
|
||||
value = block_data[element_offset];
|
||||
|
||||
switch( r_header->drawing_style )
|
||||
{
|
||||
case GIS_DRAWING_STYLE_MATRIX:
|
||||
{
|
||||
element_data = gishelper_raster_data_get_meters( value );
|
||||
|
||||
if ( fabs( element_data - r_header->no_data_value ) <
|
||||
DBL_EPSILON * fmax( fabs( element_data ), fabs( r_header->no_data_value ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( element_data > max_height || element_data < min_height )
|
||||
{
|
||||
color = invalid_color;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = gisrender_raster_get_gradient_color( colorMap.data(), valueMap.data(), colorMap.size(),
|
||||
invalid_color, element_data );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GIS_DRAWING_STYLE_RGB:
|
||||
{
|
||||
color = value | 0xFF000000;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
gis_helper_debug_write_lvl( GIS_DEBUG_LEVEL_ERROR, RASTER_VIEWER_PREFIX,
|
||||
"Got unknown drawing style [%s()]", __FUNCTION__ );
|
||||
color = invalid_color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
draw_x = offset_x + col;
|
||||
draw_y = offset_y + str;
|
||||
image->setPixel( draw_x, draw_y, QRgb( color ) );
|
||||
}
|
||||
}
|
||||
|
||||
free( block_data );
|
||||
}
|
53
src/apps/gis-raster-preview/rastertab.h
Обычный файл
@ -0,0 +1,53 @@
|
||||
/*
|
||||
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 RASTERTAB_H
|
||||
#define RASTERTAB_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
|
||||
#include <gis/gishelper.h>
|
||||
|
||||
#include <gcm_raster.h>
|
||||
#include <gis_types_internal.h>
|
||||
|
||||
class RasterTab : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RasterTab( const QString &filepath, QWidget *parent = 0 );
|
||||
~RasterTab();
|
||||
|
||||
QSize image_size;
|
||||
QPointF ll;
|
||||
double m_px;
|
||||
private:
|
||||
void draw_block( gcm_raster_header_t* r_header, const uint32_t index_x, const uint32_t index_y );
|
||||
|
||||
gcm_raster_map_ctx_t* ctx;
|
||||
QVector <gis_color_t> colorMap;
|
||||
QVector <gis_raster_value_t> valueMap;
|
||||
QImage* image;
|
||||
double max_height;
|
||||
double min_height;
|
||||
};
|
||||
|
||||
#endif
|
71
src/apps/gis-raster-preview/rasterwidget.cpp
Обычный файл
@ -0,0 +1,71 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "rasterwidget.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QStatusBar>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
bool reduce_copy = false;
|
||||
double prev_scale = 0;
|
||||
int side_size = 400;
|
||||
|
||||
RasterWidget::RasterWidget( const QString filepath, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
size_label( new QLabel() ),
|
||||
tabwgt( new QTabWidget() )
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
QStatusBar *bar = new QStatusBar();
|
||||
RasterTab *raster_tab;
|
||||
|
||||
if ( !QFile::exists( filepath ) )
|
||||
{
|
||||
qFatal( "File does not exist" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
layout->addWidget( tabwgt );
|
||||
layout->addWidget( bar );
|
||||
setLayout( layout );
|
||||
setWindowTitle( filepath );
|
||||
setFixedSize( side_size, side_size );
|
||||
setWindowFlags( Qt::WindowStaysOnTopHint );
|
||||
|
||||
do
|
||||
{
|
||||
raster_tab = new RasterTab( filepath, this );
|
||||
|
||||
if ( tabwgt->currentIndex() == -1)
|
||||
{
|
||||
bar->addWidget( new QLabel( doImageLLString( raster_tab->ll ) ) );
|
||||
size_label->setText( doImageSizeString( raster_tab->image_size ) );
|
||||
bar->addWidget( size_label );
|
||||
}
|
||||
|
||||
tabwgt->addTab( raster_tab, QString::number( raster_tab->m_px, 'f', 3 ) + " m/px" );
|
||||
|
||||
} while ( reduce_copy );
|
||||
|
||||
connect( tabwgt, SIGNAL( currentChanged( int ) ), this, SLOT( updateImageSizeLabel( int ) ) );
|
||||
}
|
78
src/apps/gis-raster-preview/rasterwidget.h
Обычный файл
@ -0,0 +1,78 @@
|
||||
/*
|
||||
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 RASTERWIDGET_H
|
||||
#define RASTERWIDGET_H
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLabel>
|
||||
#include <QTabWidget>
|
||||
#include <QWidget>
|
||||
|
||||
#include "rastertab.h"
|
||||
|
||||
struct CleanExit
|
||||
{
|
||||
CleanExit()
|
||||
{
|
||||
signal( SIGINT, &CleanExit::exitQt );
|
||||
signal( SIGTERM, &CleanExit::exitQt );
|
||||
}
|
||||
|
||||
static void exitQt( int sig )
|
||||
{
|
||||
Q_UNUSED( sig );
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
};
|
||||
|
||||
class RasterWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RasterWidget( const QString filepath, QWidget *parent = 0 );
|
||||
private:
|
||||
QLabel *size_label;
|
||||
QTabWidget *tabwgt;
|
||||
|
||||
QString doImageSizeString( QSize size )
|
||||
{
|
||||
return QString( "W: " + QString::number( size.width() ) +
|
||||
" H: " + QString::number( size.height() ) + " px" );
|
||||
}
|
||||
|
||||
QString doImageLLString( QPointF lower_left )
|
||||
{
|
||||
return QString( "Lower left X: " + QString::number( lower_left.x(), 'f', 3 ) +
|
||||
" Y: " + QString::number( lower_left.y(), 'f', 3 ) + " meters" );
|
||||
}
|
||||
|
||||
public slots:
|
||||
void updateImageSizeLabel( int )
|
||||
{
|
||||
RasterTab *cur = static_cast<RasterTab*> ( tabwgt->currentWidget() );
|
||||
size_label->setText( doImageSizeString( cur->image_size ) );
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
65
src/apps/gis-rb-viewer/CMakeLists.txt
Исполняемый файл
@ -0,0 +1,65 @@
|
||||
#[[
|
||||
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.
|
||||
]]
|
||||
|
||||
|
||||
cmake_minimum_required( VERSION 3.23 FATAL_ERROR )
|
||||
|
||||
project( gis-rb-viewer LANGUAGES CXX )
|
||||
|
||||
set( CMAKE_AUTOMOC ON )
|
||||
set( CMAKE_AUTOUIC ON )
|
||||
set( CMAKE_AUTORCC ON )
|
||||
|
||||
add_compile_options( -std=gnu++11 )
|
||||
add_compile_options( -Wno-ignored-attributes )
|
||||
|
||||
find_package( Qt5
|
||||
COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
REQUIRED )
|
||||
|
||||
file( GLOB SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
images.qrc )
|
||||
|
||||
add_executable( gis-rb-viewer ${SOURCES} )
|
||||
|
||||
target_include_directories( gis-rb-viewer
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/public
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gisrender/api/public
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/renderbuffer/public
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/gishelper/private )
|
||||
|
||||
target_link_libraries( gis-rb-viewer
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
gishelper
|
||||
gisrender
|
||||
renderbuffer )
|
||||
|
||||
install( TARGETS gis-rb-viewer DESTINATION bin )
|
Двоичные данные
src/apps/gis-rb-viewer/icons/zoomin50.png
Обычный файл
После Ширина: | Высота: | Размер: 1.0 KiB |