From 4244f998d9ab1481d4ab10aad67615fd963b1e40 Mon Sep 17 00:00:00 2001 From: ptulp Date: Sat, 14 Feb 2015 16:53:38 +0100 Subject: [PATCH] Updates for out of OpenCPN tree build Update for OSX build Update from 8 to 5 degree layout Changed original OCPN saved layout as I could not find a layout compatible with this. Now OCPN layout is the same as QTVlm layout. All layouts can be read by Weather_routing plugin --- .gitignore | 3 + CMakeLists.txt | 211 +--- README.md | 134 ++- VERSION.cmake | 4 + buildosx/InstallOSX/pkg_background.jpg | Bin 0 -> 63481 bytes buildosx/InstallOSX/polar_pi.pkgproj.in | 1350 +++++++++++++++++++++++ buildwin/NSIS.template.in | 977 ++++++++++++++++ cmake/PluginConfigure.cmake | 80 ++ cmake/PluginInstall.cmake | 91 ++ cmake/PluginLocalization.cmake | 123 +++ cmake/PluginPackage.cmake | 183 +++ cmake/gpl.txt | 413 +++++++ cmake/version.h.in | 3 + de.mo | Bin 529 -> 0 bytes default.mo | Bin 472 -> 0 bytes po/POTFILES.in | 12 + po/de.mo | Bin 3487 -> 0 bytes po/de.po | 431 ++++---- po/default.mo | Bin 438 -> 0 bytes po/default.po | 147 ++- po/default.pot | 14 - po/polar_pi.pot | 380 +++++-- src/Options.cpp | 30 +- src/Polar.cpp | 316 ++++-- src/Polar.h | 12 +- src/PolarGui.cpp | 161 +-- src/PolarGui.h | 3 +- src/{wxJSON => }/json_defs.h | 26 +- src/{wxJSON => }/jsonreader.cpp | 42 +- src/{wxJSON => }/jsonreader.h | 4 +- src/{wxJSON => }/jsonval.cpp | 198 ++-- src/{wxJSON => }/jsonval.h | 4 +- src/{wxJSON => }/jsonwriter.cpp | 12 +- src/{wxJSON => }/jsonwriter.h | 4 +- src/nmea0183/RMB.hpp | 4 +- src/nmea0183/RMC.HPP | 2 +- src/nmea0183/Response.hpp | 6 +- src/nmea0183/Sentence.hpp | 6 +- src/nmea0183/gll.cpp | 2 +- src/nmea0183/gll.hpp | 2 +- src/nmea0183/mwv.hpp | 2 +- src/nmea0183/nmea0183.cpp | 20 +- src/nmea0183/nmea0183.h | 6 +- src/nmea0183/nmea0183.hpp | 12 +- src/nmea0183/response.cpp | 2 +- src/nmea0183/rmb.cpp | 4 +- src/nmea0183/rmc.cpp | 2 +- src/nmea0183/rsa.hpp | 4 +- src/nmea0183/sentence.cpp | 6 +- src/nmea0183/vtg.cpp | 2 +- src/nmea0183/vwt.cpp | 139 +++ src/nmea0183/vwt.hpp | 77 ++ src/ocpn_plugin.h | 558 ++++++++++ src/polar_pi.cpp | 3 +- src/polar_pi.h | 10 +- 55 files changed, 5313 insertions(+), 924 deletions(-) create mode 100644 .gitignore create mode 100644 VERSION.cmake create mode 100644 buildosx/InstallOSX/pkg_background.jpg create mode 100755 buildosx/InstallOSX/polar_pi.pkgproj.in create mode 100644 buildwin/NSIS.template.in create mode 100644 cmake/PluginConfigure.cmake create mode 100644 cmake/PluginInstall.cmake create mode 100644 cmake/PluginLocalization.cmake create mode 100644 cmake/PluginPackage.cmake create mode 100644 cmake/gpl.txt create mode 100644 cmake/version.h.in delete mode 100644 de.mo delete mode 100644 default.mo create mode 100644 po/POTFILES.in delete mode 100644 po/de.mo delete mode 100644 po/default.mo delete mode 100644 po/default.pot rename src/{wxJSON => }/json_defs.h (92%) rename src/{wxJSON => }/jsonreader.cpp (99%) rename src/{wxJSON => }/jsonreader.h (99%) rename src/{wxJSON => }/jsonval.cpp (96%) rename src/{wxJSON => }/jsonval.h (99%) rename src/{wxJSON => }/jsonwriter.cpp (96%) rename src/{wxJSON => }/jsonwriter.h (96%) create mode 100644 src/nmea0183/vwt.cpp create mode 100644 src/nmea0183/vwt.hpp create mode 100644 src/ocpn_plugin.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17c860d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/ +src/version.h +.directory diff --git a/CMakeLists.txt b/CMakeLists.txt index 3872126..ebd5b99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,77 +1,31 @@ ##--------------------------------------------------------------------------- -## Author: Dave Register -##*************************************************************************** -## * Copyright (C) 2010 by David S. Register * -## * This program is free software; you can redistribute it and/or modify * -## * it under the terms of the GNU General Public License as published by * -## * the Free Software Foundation; either version 2 of the License, or * -## * (at your option) any later version. * -## * * -## * This program is distributed in the hope that it will be useful, * -## * but WITHOUT ANY WARRANTY; without even the implied warranty of * -## * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -## * GNU General Public License for more details. * -## * * -## * You should have received a copy of the GNU General Public License * -## * along with this program; if not, write to the * -## * Free Software Foundation, Inc., * -## * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * -## *************************************************************************** - +## Author: nohal aka. Pavel Kalian +## Copyright: +## License: wxWidgets License +##--------------------------------------------------------------------------- + # define minimum cmake version CMAKE_MINIMUM_REQUIRED(VERSION 2.6.2) -# This should be 2.8.0 to have FindGTK2 module -IF (COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 OLD) - CMAKE_POLICY(SET CMP0005 OLD) - CMAKE_POLICY(SET CMP0011 OLD) -ENDIF (COMMAND cmake_policy) PROJECT(polar_pi) SET(PACKAGE_NAME polar_pi) -SET(PLUGIN_SOURCE_DIR .) -MESSAGE (STATUS "*** Staging to build ${PACKAGE_NAME} ***") - -#SET(CMAKE_BUILD_TYPE Debug) -#SET(CMAKE_VERBOSE_MAKEFILE ON) - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src) - -# require proper c++ -#ADD_DEFINITIONS( "-Wall -ansi -pedantic -Wno-variadic-macros" ) -#TODO: Should we use -fno-stack-protector -# IF NOT DEBUGGING CFLAGS="-O2 -march=native" -IF(NOT WIN32) - ADD_DEFINITIONS( "-Wall -O0 -fexceptions -fvisibility=hidden" ) - - IF(NOT APPLE) - SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic") - ELSE(NOT APPLE) - SET(CMAKE_SHARED_LINKER_FLAGS "-Wl -undefined dynamic_lookup") - ENDIF(NOT APPLE) - -ENDIF(NOT WIN32) +SET(VERBOSE_NAME Polar) +SET(TITLE_NAME POLAR) +SET(CPACK_PACKAGE_CONTACT "Peter Tulp") -# Add some definitions to satisfy MS -IF(WIN32) - ADD_DEFINITIONS(-D__MSVC__) - ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_DEPRECATE) -ENDIF(WIN32) +SET(BUNDLE_DATA FALSE) -IF(NOT DEFINED wxWidgets_USE_FILE) - SET(wxWidgets_USE_LIBS base core net xml html adv) - SET(BUILD_SHARED_LIBS TRUE) - FIND_PACKAGE(wxWidgets REQUIRED) -ENDIF(NOT DEFINED wxWidgets_USE_FILE) +INCLUDE( VERSION.cmake ) +SET(PLUGIN_VERSION "${PLUGIN_VERSION_MAJOR}.${PLUGIN_VERSION_MINOR}.${PLUGIN_VERSION_PATCH}" ) - INCLUDE(${wxWidgets_USE_FILE}) +SET(VERSION_MAJOR ${PLUGIN_VERSION_MAJOR}) +SET(VERSION_MINOR "${PLUGIN_VERSION_MINOR}${PLUGIN_VERSION_PATCH}") +SET(VERSION_DATE ${PLUGIN_VERSION_DATE}) -FIND_PACKAGE(Gettext REQUIRED) - -# For convenience we define the sources as a variable. You can add -# header files and cpp/c files and CMake will sort them out +#SET(CMAKE_BUILD_TYPE Debug) +INCLUDE("cmake/PluginConfigure.cmake") SET(SRC_POLAR src/polar_pi.h @@ -84,14 +38,22 @@ SET(SRC_POLAR src/Polar.h src/Polar.cpp src/icons.h - src/icons.cpp + src/icons.cpp + src/jsonreader.h + src/jsonreader.cpp + src/jsonwriter.h + src/jsonwriter.cpp + src/jsonval.h + src/jsonval.cpp + src/json_defs.h + ) -SET(SRC_NMEA0183 +SET(SRC_LNMEA0183 src/nmea0183/LatLong.hpp src/nmea0183/latlong.cpp src/nmea0183/long.cpp src/nmea0183/nmea0183.cpp - src/nmea0183/nmea0183.h + src/nmea0183/nmea0183.hpp src/nmea0183/Response.hpp src/nmea0183/response.cpp src/nmea0183/RMB.hpp @@ -134,121 +96,18 @@ SET(SRC_NMEA0183 src/nmea0183/vhw.cpp src/nmea0183/vwr.cpp src/nmea0183/vwr.hpp + src/nmea0183/vwt.cpp + src/nmea0183/vwt.hpp src/nmea0183/zda.cpp src/nmea0183/zda.hpp src/nmea0183/rsa.hpp src/nmea0183/rsa.cpp src/nmea0183/SatInfo.h - ) -INCLUDE_DIRECTORIES(src/nmea0183) - -SET(SRC_WXJSON - src/wxJSON/jsonreader.h - src/wxJSON/jsonreader.cpp - src/wxJSON/jsonwriter.h - src/wxJSON/jsonwriter.cpp - src/wxJSON/jsonval.h - src/wxJSON/jsonval.cpp - src/wxJSON/json_defs.h - ) -INCLUDE_DIRECTORIES(src/wxJSON) - -ADD_LIBRARY(${PACKAGE_NAME} SHARED ${SRC_POLAR} ${SRC_NMEA0183} ${SRC_WXJSON} ) - -IF(WIN32) - SET(OPENCPN_IMPORT_LIB "../../${CMAKE_CFG_INTDIR}/${PARENT}") - TARGET_LINK_LIBRARIES( ${PACKAGE_NAME} LIB_BZIP ${OPENCPN_IMPORT_LIB} ) - ADD_DEPENDENCIES(${PACKAGE_NAME} ${PARENT}) -ENDIF(WIN32) - -TARGET_LINK_LIBRARIES( ${PACKAGE_NAME} ${wxWidgets_LIBRARIES} ) - -IF(APPLE) - INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME LIBRARY DESTINATION ${CMAKE_BINARY_DIR}/OpenCPN.app/Contents/PlugIns) -ENDIF(APPLE) - -IF(UNIX AND NOT APPLE) - IF(NOT DEFINED PREFIX_PLUGINS) - SET(PREFIX_PLUGINS /usr/local/lib/opencpn) - ENDIF(NOT DEFINED PREFIX_PLUGINS) - - INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME LIBRARY DESTINATION ${PREFIX_PLUGINS}) -ENDIF(UNIX AND NOT APPLE) - -IF(WIN32) -INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME DESTINATION "plugins") -ENDIF(WIN32) - -# find src/ -name \*.cpp -or -name \*.c -or -name \*.h -or -name \*.hpp >po/POTFILES.in -FIND_PROGRAM(GETTEXT_XGETTEXT_EXECUTABLE xgettext) -IF (GETTEXT_XGETTEXT_EXECUTABLE) -ADD_CUSTOM_COMMAND( - OUTPUT po/${PACKAGE_NAME}.pot.dummy - COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --force-po --package-name=${PACKAGE_NAME} --package-version="${PACKAGE_VERSION}" --output=po/${PACKAGE_NAME}.pot --keyword=_ --width=80 --files-from=${CMAKE_CURRENT_SOURCE_DIR}/po/POTFILES.in - DEPENDS po/POTFILES.in po/${PACKAGE_NAME}.pot - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "polar-pot-update [${PACKAGE_NAME}]: Generated pot file." -) -ADD_CUSTOM_TARGET(polar-pot-update COMMENT "polar-pot-update: Done." DEPENDS po/${PACKAGE_NAME}.pot.dummy) - -ENDIF(GETTEXT_XGETTEXT_EXECUTABLE ) - -MACRO(GETTEXT_UPDATE_PO _potFile) - SET(_poFiles ${_potFile}) - GET_FILENAME_COMPONENT(_absPotFile ${_potFile} ABSOLUTE) - - FOREACH (_currentPoFile ${ARGN}) - GET_FILENAME_COMPONENT(_absFile ${_currentPoFile} ABSOLUTE) - GET_FILENAME_COMPONENT(_poBasename ${_absFile} NAME_WE) - - ADD_CUSTOM_COMMAND( - OUTPUT ${_absFile}.dummy - COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --width=80 --strict --quiet --update --backup=none --no-location -s ${_absFile} ${_absPotFile} - DEPENDS ${_absPotFile} ${_absFile} - COMMENT "polar-po-update [${_poBasename}]: Updated po file." - ) - - SET(_poFiles ${_poFiles} ${_absFile}.dummy) - - ENDFOREACH (_currentPoFile ) - - ADD_CUSTOM_TARGET(polar-po-update COMMENT "polar-po-update: Done." DEPENDS ${_poFiles}) -ENDMACRO(GETTEXT_UPDATE_PO) - -IF (GETTEXT_MSGMERGE_EXECUTABLE) -FILE(GLOB PACKAGE_PO_FILES po/*.po) -GETTEXT_UPDATE_PO(po/${PACKAGE_NAME}.pot ${PACKAGE_PO_FILES}) -ENDIF(GETTEXT_MSGMERGE_EXECUTABLE) - -SET(_gmoFiles) -MACRO(GETTEXT_BUILD_MO) - FOREACH (_poFile ${ARGN}) - GET_FILENAME_COMPONENT(_absFile ${_poFile} ABSOLUTE) - GET_FILENAME_COMPONENT(_poBasename ${_absFile} NAME_WE) - SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_poBasename}.mo) - - ADD_CUSTOM_COMMAND( - OUTPUT ${_gmoFile} - COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check -o ${_gmoFile} ${_absFile} - DEPENDS ${_absFile} - COMMENT "polar-i18n [${_poBasename}]: Created mo file." - ) - -IF(APPLE) - INSTALL(FILES ${_gmoFile} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/OpenCPN.app/Contents/Resources/${_poBasename}.lproj RENAME opencpn-${PACKAGE_NAME}.mo ) -ELSE(APPLE) - INSTALL(FILES ${_gmoFile} DESTINATION ${PREFIX_DATA}/locale/${_poBasename}/LC_MESSAGES RENAME opencpn-${PACKAGE_NAME}.mo ) -ENDIF(APPLE) - - SET(_gmoFiles ${_gmoFiles} ${_gmoFile}) - ENDFOREACH (_poFile ) -ENDMACRO(GETTEXT_BUILD_MO) -if(GETTEXT_MSGFMT_EXECUTABLE) - FILE(GLOB PACKAGE_PO_FILES po/*.po) - GETTEXT_BUILD_MO(${PACKAGE_PO_FILES}) - ADD_CUSTOM_TARGET(polar-i18n COMMENT "polar-i18n: Done." DEPENDS ${_gmoFiles}) - #ADD_DEPENDENCIES(polar-i18n ${PACKAGE_PO_FILES}) - ADD_DEPENDENCIES(${PACKAGE_NAME} polar-i18n) -ENDIF(GETTEXT_MSGFMT_EXECUTABLE) + ) +ADD_DEFINITIONS(-DTIXML_USE_STL) +ADD_LIBRARY(${PACKAGE_NAME} SHARED ${SRC_POLAR} ${SRC_LNMEA0183}) +INCLUDE("cmake/PluginInstall.cmake") +INCLUDE("cmake/PluginLocalization.cmake") +INCLUDE("cmake/PluginPackage.cmake") diff --git a/README.md b/README.md index 5b6fc49..8ce73e1 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,134 @@ -polar_pi -======== +Polar Diagram Plugin for OpenCPN +================================ -Polar-Diagram-Plugin for OpenCPN +This plugin is originally developed by Konnibe. I have forked this from his +git repository and I am continuing development. Konnibe has been unable to continue +development on this logbook due to ill health. -Building from source --------------------- -Please use Git for download and don't hit the downloads-link above to create a .zip or tar.zip !! +Downloading the Plugin +====================== -Clone the git repository to /plugins/polar_pi (the _pi at the end matters!) as follows: +The latest binary release can be found here: -cd OPENCPN_SOURCE_TLD/plugins +https://github.com/ptulp/polar_pi/releases -OPENCPN_SOURCE_TLD = where you stored the opencpn-source files e.g. ~/home/username/path_to_opencpn-source +You should be able to find binaries (RPM and DEB) for Linux as well as some for +Windows and OSX there. -open a terminal here and copy/paste this command: -git clone git://github.com/konnibe/polar_pi.git polar_pi +If the binaries for your platform are not there, then just stand by, we have several +people contributing binaries and it takes a few days to get them in from everyone. -Run this commands: -cd ../build +Compiling +========= +This plugin now builds out of the OpenCPN source tree. You do not need to build +the entire of OpenCPN or even clone it from git just to build this plugin. It +should, however, also successfully build from inside the OpenCPN source tree along +with the rest of OpenCPN if you clone it into the OpenCPN/plugins directory. + +If you need instructions as to how to build OpenCPN then see the developers +manual at http://opencpn.org/ocpn/developers_manual + +You need to have all of the dependencies required to compile OpenCPN installed in +order to be able to build this plugin. Those might vary depending on your system. + +###Clone this repository from github + +You might choose to fork this repository on github so you might +use your own git: URL instead of the one below. + +``` +git clone https://github.com/ptulp/polar_pi +``` + +or, from your own fork, a command similar to this (replace pulp with +your own git user name): + +``` +git clone git@github.com:ptulp/polar-pi.git polar_pi +``` + +###Build on Linux + +Note that you will need to have all of the development tools installed that +are required to build OpenCPN. If you have any doubts then run the cmake .. +command and it will complain about missing dependencies. At the very least +you will need the g++ compiler and development libraries, cmake, gettext, so +install those first and see how far you get. + +``` +mkdir polar_pi/build +cd polar_pi/build cmake .. +cmake --build . +``` + +###Build on Mac OS X + +Tools: Can be installed either manually or from Homebrew (http://brew.sh) -cmake --build . --target polar_pi +``` +#brew install git #If I remember well, it is already available on the system +brew install cmake +brew install gettext +ln -s /usr/local/Cellar/gettext/0.19.2/bin/msgmerge /usr/local/bin/msgmerge +ln -s /usr/local/Cellar/gettext/0.19.2/bin/msgfmt /usr/local/bin/msgfmt +``` +To target older OS X versions than the one you are running, you need the respective SDKs installed. The easiest way to achieve that is using https://github.com/devernay/xcodelegacy + +####Building wxWidgets +(do not use wxmac from Homebrew, it is not compatible with OpenCPN) +Get wxWidgets 3.0.x source from http://wxwidgets.org +Configure, build and install +``` +cd wxWidgets-3.0.2 +./configure --enable-unicode --with-osx-cocoa --with-macosx-sdk=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/ --with-macosx-version-min=10.7 --enable-aui --disable-debug --enable-opengl +make sudo make install +``` + +####Building the plugin +Before running cmake, you must set the deployment target to OS X 10.7 to be compatible with the libraries used by core OpenCPN +``` +export MACOSX_DEPLOYMENT_TARGET=10.7 + +cd polar_pi +mkdir build +cd build +cmake .. +cmake --build . +``` + +Packaging +========= + +From inside the build directory, the following command will make packages for your +current platform against the as-built code: + +``` +make package +``` + +Note that you will need to have the packaging tools installed for your platform and +any other platforms that you build packages for. e.g. on Ubuntu you will need the +development tools required to build deb file as well as the rpm package required to +build RPM files. + +To check the contents of the Debian/Ubuntu package, use this command: + +``` +dpkg -c polar_pi_1.0001-1_amd64.deb +``` + +###Packaging on OS X +Get and install the Packages application from http://s.sudre.free.fr/Software/Packages/about.html +After installing Packages create the Plugin package. +``` +make create-pkg +``` +This will create the Polar-Plugin_1.0xx.pkg file in the build directory. +Executing this file will install the plugin. -that's it. diff --git a/VERSION.cmake b/VERSION.cmake new file mode 100644 index 0000000..db32373 --- /dev/null +++ b/VERSION.cmake @@ -0,0 +1,4 @@ +SET(PLUGIN_VERSION_MAJOR "1") +SET(PLUGIN_VERSION_MINOR "0") +SET(PLUGIN_VERSION_PATCH "01") +SET(PLUGIN_VERSION_DATE "2015-02-13") diff --git a/buildosx/InstallOSX/pkg_background.jpg b/buildosx/InstallOSX/pkg_background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cd03966e60eb112a5a8641fcfaf95ca275d4b7c5 GIT binary patch literal 63481 zcmeFZXINBAv?jcpCW|0Q&Y_VYqD09wNJb=QRC3NilF)#Fg5)Sc8p#>SAV|(RtK=L7 zBunUK+T&5rojLc;%=g?M-;cp(H|^e4t7@(FR@JJv*5>N-)dFxsK}KE%0D(Y&9O@r% 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 z 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≶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 literal 0 HcmV?d00001 diff --git a/buildosx/InstallOSX/polar_pi.pkgproj.in b/buildosx/InstallOSX/polar_pi.pkgproj.in new file mode 100755 index 0000000..76d6732 --- /dev/null +++ b/buildosx/InstallOSX/polar_pi.pkgproj.in @@ -0,0 +1,1350 @@ + + + + + PACKAGES + + + PACKAGE_FILES + + DEFAULT_INSTALL_LOCATION + /Applications/OpenCPN.app/Contents + HIERARCHY + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + lib${PACKAGE_NAME}.dylib + PATH_TYPE + 3 + PERMISSIONS + 493 + TYPE + 3 + UID + 0 + + + GID + 80 + PATH + ${PACKAGE_NAME} + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + Plugins + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 2 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + Resources/de.lproj/opencpn-${PACKAGE_NAME}.mo + PATH_TYPE + 3 + PERMISSIONS + 420 + TYPE + 3 + UID + 0 + + + GID + 80 + PATH + de.lproj + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + Resources + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + Contents + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 2 + UID + 0 + + + GID + 80 + PATH + OpenCPN.app + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 2 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + Utilities + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 80 + PATH + Applications + PATH_TYPE + 0 + PERMISSIONS + 509 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 80 + PATH + Application Support + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Documentation + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Filesystems + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Frameworks + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Input Methods + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Internet Plug-Ins + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + LaunchAgents + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + LaunchDaemons + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PreferencePanes + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Preferences + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 80 + PATH + Printers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + PrivilegedHelperTools + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickLook + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + QuickTime + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Screen Savers + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Scripts + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Services + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + GID + 0 + PATH + Widgets + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Extensions + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + Library + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + System + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + CHILDREN + + + CHILDREN + + GID + 0 + PATH + Shared + PATH_TYPE + 0 + PERMISSIONS + 1023 + TYPE + 1 + UID + 0 + + + GID + 80 + PATH + Users + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + + GID + 0 + PATH + / + PATH_TYPE + 0 + PERMISSIONS + 493 + TYPE + 1 + UID + 0 + + PAYLOAD_TYPE + 0 + SPLIT_FORKS + + VERSION + 2 + + PACKAGE_SCRIPTS + + POSTINSTALL_PATH + + PREINSTALL_PATH + + RESOURCES + + + PACKAGE_SETTINGS + + AUTHENTICATION + 1 + CONCLUSION_ACTION + 0 + IDENTIFIER + org.opencpn.pkg.${PACKAGE_NAME} + LOCATION + 0 + NAME + ${VERBOSE_NAME}-Plugin + OVERWRITE_PERMISSIONS + + USE_HFS+_COMPRESSION + + VERSION + 1.0 + + UUID + 5773AC4B-F49D-49E7-9C62-3A5795603C67 + + + PROJECT + + PROJECT_COMMENTS + + NOTES + + PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M + IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv + c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l + cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7 + IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250 + ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp + dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u + dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD + b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjExMzguNTEiPgo8c3R5bGUg + dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5 + Pgo8L2JvZHk+CjwvaHRtbD4K + + + PROJECT_PRESENTATION + + BACKGROUND + + ALIGNMENT + 4 + BACKGROUND_PATH + + PATH + pkg_background.jpg + PATH_TYPE + 1 + + CUSTOM + 1 + SCALING + 1 + + INSTALLATION TYPE + + HIERARCHIES + + INSTALLER + + LIST + + + DESCRIPTION + + OPTIONS + + HIDDEN + + STATE + 1 + + PACKAGE_UUID + 5773AC4B-F49D-49E7-9C62-3A5795603C67 + REQUIREMENTS + + + BEHAVIOR + 1 + DICTIONARY + + IC_REQUIREMENT_FILES_CONDITION + 0 + IC_REQUIREMENT_FILES_DISK_TYPE + 0 + IC_REQUIREMENT_FILES_LIST + + /Applications/OpenCPN.app + + IC_REQUIREMENT_FILES_SELECTOR + 0 + + IDENTIFIER + fr.whitebox.Packages.requirement.files + MESSAGE + + + LANGUAGE + Czech + VALUE + OpenCPN not found + + + LANGUAGE + Dutch + VALUE + OpenCPN not found + + + LANGUAGE + English + VALUE + OpenCPN not found + + + LANGUAGE + French + VALUE + OpenCPN ne pas trouver + + + LANGUAGE + German + VALUE + OpenCPN nicht gefunden + + + LANGUAGE + Italian + VALUE + OpenCPN not found + + + LANGUAGE + Spanish + VALUE + OpenCPN not found + + + NAME + Files + STATE + + + + TITLE + + + LANGUAGE + Czech + VALUE + ${TITLE_NAME} Plugin for OpenCPN + + + LANGUAGE + Dutch + VALUE + ${TITLE_NAME} Plugin for OpenCPN + + + LANGUAGE + English + VALUE + ${TITLE_NAME} Plugin for OpenCPN + + + LANGUAGE + French + VALUE + ${TITLE_NAME} Complément (plugin) pour OpenCPN + + + LANGUAGE + German + VALUE + ${TITLE_NAME} Plugin für OpenCPN + + + LANGUAGE + Italian + VALUE + ${TITLE_NAME} Plugin for OpenCPN + + + LANGUAGE + Spanish + VALUE + Plugin ${TITLE_NAME} para OpenCPN + + + TOOLTIP + + TYPE + 0 + UUID + D0A63AF2-D83E-4B8C-8E87-D4A7FF5C140E + + + REMOVED + + + + INSTALLATION TYPE + 0 + MODE + 1 + + INSTALLATION_STEPS + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewIntroductionController + INSTALLER_PLUGIN + Introduction + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewReadMeController + INSTALLER_PLUGIN + ReadMe + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewLicenseController + INSTALLER_PLUGIN + License + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewDestinationSelectController + INSTALLER_PLUGIN + TargetSelect + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewInstallationTypeController + INSTALLER_PLUGIN + PackageSelection + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewInstallationController + INSTALLER_PLUGIN + Install + LIST_TITLE_KEY + InstallerSectionTitle + + + ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS + ICPresentationViewSummaryController + INSTALLER_PLUGIN + Summary + LIST_TITLE_KEY + InstallerSectionTitle + + + INTRODUCTION + + LOCALIZATIONS + + + LICENSE + + KEYWORDS + + LOCALIZATIONS + + + LANGUAGE + Czech + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + Dutch + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + English + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + French + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + German + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + Italian + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + Polish + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + LANGUAGE + Spanish + VALUE + + PATH + license.txt + PATH_TYPE + 3 + + + + MODE + 0 + + SUMMARY + + LOCALIZATIONS + + + TITLE + + LOCALIZATIONS + + + LANGUAGE + English + VALUE + ${TITLE_NAME} Plugin + + + + + PROJECT_REQUIREMENTS + + LIST + + + BEHAVIOR + 3 + DICTIONARY + + IC_REQUIREMENT_JAVASCRIPT_FUNCTION + checkForOCPN + IC_REQUIREMENT_JAVASCRIPT_PARAMETERS + + + IC_REQUIREMENT_CHECK_TYPE + 0 + IDENTIFIER + fr.whitebox.Packages.requirement.javascript + MESSAGE + + + LANGUAGE + Czech + SECONDARY_VALUE + Please install OpenCPN version 3.3.1606 (or later) in Applications folder. + VALUE + OpenCPN not found. + + + LANGUAGE + Dutch + SECONDARY_VALUE + Please install OpenCPN version 3.3.1606 (or later) in Applications folder. + VALUE + OpenCPN not found. + + + LANGUAGE + English + SECONDARY_VALUE + Please install OpenCPN version 3.3.1606 (or later) in Applications folder. + VALUE + OpenCPN not found. + + + LANGUAGE + French + SECONDARY_VALUE + S'il vous plait, installez la version 3.3.1606 (or later) dans le dossier des applications. + VALUE + OpenCPN n'existe pas + + + LANGUAGE + German + SECONDARY_VALUE + Bitte erst OpenCPN Version3.3.1606 (or later) im Programme Ordner installieren. + VALUE + OpenCPN nicht gefunden. + + + + LANGUAGE + Italian + SECONDARY_VALUE + Please install first OpenCPN version 3.3.1606 (or later) in Applications folder. + VALUE + OpenCPN not found. + + + LANGUAGE + Spanish + SECONDARY_VALUE + Instale por favor primero OpenCPN versión 3.3.1606 (or later) en la carpeta de Aplicaciones + VALUE + OpenCPN no encontrado + + + NAME + JavaScript + STATE + + + + BEHAVIOR + 2 + DICTIONARY + + IC_REQUIREMENT_JAVASCRIPT_FUNCTION + checkOCPNVersion + IC_REQUIREMENT_JAVASCRIPT_PARAMETERS + + IC_REQUIREMENT_JAVASCRIPT_RETURN_VALUE + 1 + + IC_REQUIREMENT_CHECK_TYPE + 0 + IDENTIFIER + fr.whitebox.Packages.requirement.javascript + MESSAGE + + + LANGUAGE + English + SECONDARY_VALUE + + VALUE + OpenCPN Version undetermined. Assuming 3.3.1606 or later. + + + NAME + JavaScript 1 + STATE + + + + POSTINSTALL_PATH + + PREINSTALL_PATH + + RESOURCES + + ROOT_VOLUME_ONLY + + + PROJECT_SETTINGS + + ADVANCED_OPTIONS + + installer-script.options:allow-external-scripts + + + BUILD_FORMAT + 0 + BUILD_PATH + + PATH + . + PATH_TYPE + 3 + + EXCLUDED_FILES + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + .DS_Store + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Remove .DS_Store files + PROXY_TOOLTIP + Remove ".DS_Store" files created by the Finder. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + .pbdevelopment + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Remove .pbdevelopment files + PROXY_TOOLTIP + Remove ".pbdevelopment" files created by ProjectBuilder or Xcode. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + CVS + TYPE + 1 + + + REGULAR_EXPRESSION + + STRING + .cvsignore + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + .cvspass + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + .svn + TYPE + 1 + + + REGULAR_EXPRESSION + + STRING + .git + TYPE + 1 + + + REGULAR_EXPRESSION + + STRING + .gitignore + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Remove SCM metadata + PROXY_TOOLTIP + Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + classes.nib + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + designable.db + TYPE + 0 + + + REGULAR_EXPRESSION + + STRING + info.nib + TYPE + 0 + + + PROTECTED + + PROXY_NAME + Optimize nib files + PROXY_TOOLTIP + Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles. + STATE + + + + PATTERNS_ARRAY + + + REGULAR_EXPRESSION + + STRING + Resources Disabled + TYPE + 1 + + + PROTECTED + + PROXY_NAME + Remove Resources Disabled folders + PROXY_TOOLTIP + Remove "Resources Disabled" folders. + STATE + + + + SEPARATOR + + + + NAME + ${VERBOSE_NAME}-Plugin_${VERSION_MAJOR}.${VERSION_MINOR} + REFERENCE_FOLDER_PATH + . + + + SHARED_GLOBAL_DATA + + IC_REQUIREMENT_JAVASCRIPT_SHARED_SOURCE_CODE + function checkForOCPN() { +var chk_flag = false; +try { +// is OpenCPN installed? + chk_flag = system.files.fileExistsAtPath('/Applications/OpenCPN.app'); +} catch (e) { +// an exception just occurred + return (false) +} +// return the check results + return chk_flag; +} + +function checkOCPNVersion() { +var chk_flag = false; +var ocpn_vers; +try { +// is OpenCPN installed? + chk_flag = system.files.fileExistsAtPath('/Applications/OpenCPN.app'); +if (chk_flag) { +// is it the right version of OpenCPN? + ocpn_data = system.files.bundleAtPath('/Applications/OpenCPN.app'); +ocpn_vers = ocpn_data.CFBundleShortVersionString; +chk_flag = (ocpn_vers >= '3.3.1606'); } +} catch (e) { +// an exception just occurred + return (false) +} +// return the check results + return chk_flag; + } + + + TYPE + 0 + VERSION + 2 + + diff --git a/buildwin/NSIS.template.in b/buildwin/NSIS.template.in new file mode 100644 index 0000000..bd68ef7 --- /dev/null +++ b/buildwin/NSIS.template.in @@ -0,0 +1,977 @@ +; CPack install script designed for a nmake build + +;-------------------------------- +; You must define these values + + !define VERSION "@CPACK_PACKAGE_VERSION@" + !define PATCH "@CPACK_PACKAGE_VERSION_PATCH@" + !define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@" + +;-------------------------------- +;Variables + + Var MUI_TEMP + Var STARTMENU_FOLDER + Var SV_ALLUSERS + Var START_MENU + Var DO_NOT_ADD_TO_PATH + Var ADD_TO_PATH_ALL_USERS + Var ADD_TO_PATH_CURRENT_USER + Var INSTALL_DESKTOP + Var IS_DEFAULT_INSTALLDIR +;-------------------------------- +;Include Modern UI + + !include "MUI.nsh" + + ;Default installation folder + InstallDir "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + +;-------------------------------- +;General + + ;Name and file + Name "@CPACK_NSIS_PACKAGE_NAME@" + OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@" + + ;Set compression + SetCompressor @CPACK_NSIS_COMPRESSOR@ + + ;Require administrator access + RequestExecutionLevel admin + +@CPACK_NSIS_DEFINES@ + + !include Sections.nsh + +;--- Component support macros: --- +; The code for the add/remove functionality is from: +; http://nsis.sourceforge.net/Add/Remove_Functionality +; It has been modified slightly and extended to provide +; inter-component dependencies. +Var AR_SecFlags +Var AR_RegFlags +@CPACK_NSIS_SECTION_SELECTED_VARS@ + +; Loads the "selected" flag for the section named SecName into the +; variable VarName. +!macro LoadSectionSelectedIntoVar SecName VarName + SectionGetFlags ${${SecName}} $${VarName} + IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits +!macroend + +; Loads the value of a variable... can we get around this? +!macro LoadVar VarName + IntOp $R0 0 + $${VarName} +!macroend + +; Sets the value of a variable +!macro StoreVar VarName IntValue + IntOp $${VarName} 0 + ${IntValue} +!macroend + +!macro InitSection SecName + ; This macro reads component installed flag from the registry and + ;changes checked state of the section on the components page. + ;Input: section index constant name specified in Section command. + + ClearErrors + ;Reading component status from registry + ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" "Installed" + IfErrors "default_${SecName}" + ;Status will stay default if registry value not found + ;(component was never installed) + IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags + IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off + IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit + + ; Note whether this component was installed before + !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags + IntOp $R0 $AR_RegFlags & $AR_RegFlags + + ;Writing modified flags + SectionSetFlags ${${SecName}} $AR_SecFlags + + "default_${SecName}:" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected +!macroend + +!macro FinishSection SecName + ; This macro reads section flag set by user and removes the section + ;if it is not selected. + ;Then it writes component installed flag to registry + ;Input: section index constant name specified in Section command. + + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags + ;Checking lowest bit: + IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED} + IntCmp $AR_SecFlags 1 "leave_${SecName}" + ;Section is not selected: + ;Calling Section uninstall macro and writing zero installed flag + !insertmacro "Remove_${${SecName}}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 0 + Goto "exit_${SecName}" + + "leave_${SecName}:" + ;Section is selected: + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 1 + + "exit_${SecName}:" +!macroend + +!macro RemoveSection_CPack SecName + ; This macro is used to call section's Remove_... macro + ;from the uninstaller. + ;Input: section index constant name specified in Section command. + + !insertmacro "Remove_${${SecName}}" +!macroend + +; Determine whether the selection of SecName changed +!macro MaybeSelectionChanged SecName + !insertmacro LoadVar ${SecName}_selected + SectionGetFlags ${${SecName}} $R1 + IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits + + ; See if the status has changed: + IntCmp $R0 $R1 "${SecName}_unchanged" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected + + IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected" + !insertmacro "Deselect_required_by_${SecName}" + goto "${SecName}_unchanged" + + "${SecName}_was_selected:" + !insertmacro "Select_${SecName}_depends" + + "${SecName}_unchanged:" +!macroend +;--- End of Add/Remove macros --- + +;-------------------------------- +;Interface Settings + + !define MUI_HEADERIMAGE + !define MUI_ABORTWARNING + +;-------------------------------- +; path functions + +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 + +;---------------------------------------- +; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02" +;---------------------------------------- +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 +;==================================================== +; get_NT_environment +; Returns: the selected environment +; Output : head of the stack +;==================================================== +!macro select_NT_profile UN +Function ${UN}select_NT_profile + StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single + DetailPrint "Selected environment for all users" + Push "all" + Return + environment_single: + DetailPrint "Selected environment for current user only." + Push "current" + Return +FunctionEnd +!macroend +!insertmacro select_NT_profile "" +!insertmacro select_NT_profile "un." +;---------------------------------------------------- +!define NT_current_env 'HKCU "Environment"' +!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + +!ifndef WriteEnvStr_RegKey + !ifdef ALL_USERS + !define WriteEnvStr_RegKey \ + 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + !else + !define WriteEnvStr_RegKey 'HKCU "Environment"' + !endif +!endif + +; AddToPath - Adds the given dir to the search path. +; Input - head of the stack +; Note - Win9x systems requires reboot + +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + + # don't add if the path doesn't exist + IfFileExists "$0\*.*" "" AddToPath_done + + ReadEnvStr $1 PATH + ; if the path is too long for a NSIS variable NSIS will return a 0 + ; length string. If we find that, then warn and skip any path + ; modification as it will trash the existing path. + StrLen $2 $1 + IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done + CheckPathLength_ShowPathWarning: + Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!" + Goto AddToPath_done + CheckPathLength_Done: + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + GetFullPathName /SHORT $3 $0 + Push "$1;" + Push "$3;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$3\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + + Call IsNT + Pop $1 + StrCmp $1 1 AddToPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 -1 END + FileReadByte $1 $2 + IntCmp $2 26 0 +2 +2 # DOS EOF + FileSeek $1 -1 END # write over EOF + FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" + FileClose $1 + SetRebootFlag true + Goto AddToPath_done + + AddToPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto DoTrim + ReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + DoTrim: + StrCmp $1 "" AddToPath_NTdoIt + Push $1 + Call Trim + Pop $1 + StrCpy $0 "$1;$0" + AddToPath_NTdoIt: + StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $0 + Goto DoSend + WriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $0 + DoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + AddToPath_done: + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + +; RemoveFromPath - Remove a given dir from the path +; Input: head of the stack + +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + IntFmt $6 "%c" 26 # DOS EOF + + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCpy $5 $3 1 -1 # read last char + StrCmp $5 $6 0 +2 # if DOS EOF + StrCpy $3 $3 -1 # remove DOS EOF so we can compare + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + unRemoveFromPath_dosLoopRemoveLine: + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto unDoTrim + unReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + unDoTrim: + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 ";" +2 # if last char != ; + StrCpy $1 "$1;" # append ; + Push $1 + Push "$0;" + Call un.StrStr ; Find `$0;` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 ";" 0 +2 # if last char == ; + StrCpy $3 $3 -1 # remove last char + + StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $3 + Goto unDoSend + unWriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $3 + unDoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Uninstall sutff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +########################################### +# Utility Functions # +########################################### + +;==================================================== +; IsNT - Returns 1 if the current system is NT, 0 +; otherwise. +; Output: head of the stack +;==================================================== +; IsNT +; no input +; output, top of the stack = 1 if NT or 0 if not +; +; Usage: +; Call IsNT +; Pop $R0 +; ($R0 at this point is 1 or 0) + +!macro IsNT un +Function ${un}IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd +!macroend +!insertmacro IsNT "" +!insertmacro IsNT "un." + +; StrStr +; input, top of stack = string to search for +; top of stack-1 = string to search in +; output, top of stack (replaces with the portion of the string remaining) +; modifies no other variables. +; +; Usage: +; Push "this is a long ass string" +; Push "ass" +; Call StrStr +; Pop $R0 +; ($R0 at this point is "ass string") + +!macro StrStr un +Function ${un}StrStr +Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop +done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd +!macroend +!insertmacro StrStr "" +!insertmacro StrStr "un." + +Function Trim ; Added by Pelaca + Exch $R1 + Push $R2 +Loop: + StrCpy $R2 "$R1" 1 -1 + StrCmp "$R2" " " RTrim + StrCmp "$R2" "$\n" RTrim + StrCmp "$R2" "$\r" RTrim + StrCmp "$R2" ";" RTrim + GoTo Done +RTrim: + StrCpy $R1 "$R1" -1 + Goto Loop +Done: + Pop $R2 + Exch $R1 +FunctionEnd + +Function ConditionalAddToRegisty + Pop $0 + Pop $1 + StrCmp "$0" "" ConditionalAddToRegisty_EmptyString + WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ + "$1" "$0" + ;MessageBox MB_OK "Set Registry: '$1' to '$0'" + DetailPrint "Set install registry entry: '$1' to '$0'" + ConditionalAddToRegisty_EmptyString: +FunctionEnd + +;-------------------------------- + +!ifdef CPACK_USES_DOWNLOAD +Function DownloadFile + IfFileExists $INSTDIR\* +2 + CreateDirectory $INSTDIR + Pop $0 + + ; Skip if already downloaded + IfFileExists $INSTDIR\$0 0 +2 + Return + + StrCpy $1 "@CPACK_DOWNLOAD_SITE@" + + try_again: + NSISdl::download "$1/$0" "$INSTDIR\$0" + + Pop $1 + StrCmp $1 "success" success + StrCmp $1 "Cancelled" cancel + MessageBox MB_OK "Download failed: $1" + cancel: + Return + success: +FunctionEnd +!endif + +;-------------------------------- +; Installation types +@CPACK_NSIS_INSTALLATION_TYPES@ + +;-------------------------------- +; Component sections +@CPACK_NSIS_COMPONENT_SECTIONS@ + +;-------------------------------- +; Define some macro setting for the gui +@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ +@CPACK_NSIS_INSTALLER_ICON_CODE@ +@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ +@CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@ + +;-------------------------------- +;Pages + !insertmacro MUI_PAGE_WELCOME + + !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" + Page custom InstallOptionsPage + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page Configuration +; !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" +; !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" +; !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" +; !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + + @CPACK_NSIS_PAGE_COMPONENTS@ + + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" ;first language is the default language + !insertmacro MUI_LANGUAGE "Albanian" + !insertmacro MUI_LANGUAGE "Arabic" + !insertmacro MUI_LANGUAGE "Basque" + !insertmacro MUI_LANGUAGE "Belarusian" + !insertmacro MUI_LANGUAGE "Bosnian" + !insertmacro MUI_LANGUAGE "Breton" + !insertmacro MUI_LANGUAGE "Bulgarian" + !insertmacro MUI_LANGUAGE "Croatian" + !insertmacro MUI_LANGUAGE "Czech" + !insertmacro MUI_LANGUAGE "Danish" + !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "Estonian" + !insertmacro MUI_LANGUAGE "Farsi" + !insertmacro MUI_LANGUAGE "Finnish" + !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "German" + !insertmacro MUI_LANGUAGE "Greek" + !insertmacro MUI_LANGUAGE "Hebrew" + !insertmacro MUI_LANGUAGE "Hungarian" + !insertmacro MUI_LANGUAGE "Icelandic" + !insertmacro MUI_LANGUAGE "Indonesian" + !insertmacro MUI_LANGUAGE "Irish" + !insertmacro MUI_LANGUAGE "Italian" + !insertmacro MUI_LANGUAGE "Japanese" + !insertmacro MUI_LANGUAGE "Korean" + !insertmacro MUI_LANGUAGE "Kurdish" + !insertmacro MUI_LANGUAGE "Latvian" + !insertmacro MUI_LANGUAGE "Lithuanian" + !insertmacro MUI_LANGUAGE "Luxembourgish" + !insertmacro MUI_LANGUAGE "Macedonian" + !insertmacro MUI_LANGUAGE "Malay" + !insertmacro MUI_LANGUAGE "Mongolian" + !insertmacro MUI_LANGUAGE "Norwegian" + !insertmacro MUI_LANGUAGE "Polish" + !insertmacro MUI_LANGUAGE "Portuguese" + !insertmacro MUI_LANGUAGE "PortugueseBR" + !insertmacro MUI_LANGUAGE "Romanian" + !insertmacro MUI_LANGUAGE "Russian" + !insertmacro MUI_LANGUAGE "Serbian" + !insertmacro MUI_LANGUAGE "SerbianLatin" + !insertmacro MUI_LANGUAGE "SimpChinese" + !insertmacro MUI_LANGUAGE "Slovak" + !insertmacro MUI_LANGUAGE "Slovenian" + !insertmacro MUI_LANGUAGE "Spanish" + !insertmacro MUI_LANGUAGE "Swedish" + !insertmacro MUI_LANGUAGE "Thai" + !insertmacro MUI_LANGUAGE "TradChinese" + !insertmacro MUI_LANGUAGE "Turkish" + !insertmacro MUI_LANGUAGE "Ukrainian" + !insertmacro MUI_LANGUAGE "Welsh" + + +;-------------------------------- +;Reserve Files + + ;These files should be inserted before other files in the data block + ;Keep these lines before any File command + ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA) + + ReserveFile "NSIS.InstallOptions.ini" + !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +;-------------------------------- +;Installer Sections + +Section "-Core installation" + ;Use the entire tree produced by the INSTALL target. Keep the + ;list of directories here in sync with the RMDir commands below. + SetOutPath "$INSTDIR" + @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@ + @CPACK_NSIS_FULL_INSTALL@ + + ;Store installation folder + WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + + ;Create uninstaller + WriteUninstaller "$INSTDIR\Uninstall @CPACK_NSIS_PACKAGE_NAME@.exe" + Push "DisplayName" + Push "@CPACK_NSIS_DISPLAY_NAME@" + Call ConditionalAddToRegisty + Push "DisplayVersion" + Push "@CPACK_PACKAGE_VERSION@" + Call ConditionalAddToRegisty + Push "Publisher" + Push "@CPACK_PACKAGE_VENDOR@" + Call ConditionalAddToRegisty + Push "UninstallString" + Push "$INSTDIR\Uninstall @CPACK_NSIS_PACKAGE_NAME@.exe" + Call ConditionalAddToRegisty + Push "NoRepair" + Push "1" + Call ConditionalAddToRegisty + + !ifdef CPACK_NSIS_ADD_REMOVE + ;Create add/remove functionality + Push "ModifyPath" + Push "$INSTDIR\AddRemove.exe" + Call ConditionalAddToRegisty + !else + Push "NoModify" + Push "1" + Call ConditionalAddToRegisty + !endif + + ; Optional registration + Push "DisplayIcon" + Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@" + Call ConditionalAddToRegisty + Push "HelpLink" + Push "@CPACK_NSIS_HELP_LINK@" + Call ConditionalAddToRegisty + Push "URLInfoAbout" + Push "@CPACK_NSIS_URL_INFO_ABOUT@" + Call ConditionalAddToRegisty + Push "Contact" + Push "@CPACK_NSIS_CONTACT@" + Call ConditionalAddToRegisty + !insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State" +; !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + + ;Create shortcuts +; CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" +; @CPACK_NSIS_CREATE_ICONS@ +; @CPACK_NSIS_CREATE_ICONS_EXTRA@ +; CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall @CPACK_NSIS_PACKAGE_NAME@.exe" + + ;Read a value from an InstallOptions INI file + !insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State" + + ; Write special uninstall registry entries + Push "StartMenu" + Push "$STARTMENU_FOLDER" + Call ConditionalAddToRegisty + Push "DoNotAddToPath" + Push "$DO_NOT_ADD_TO_PATH" + Call ConditionalAddToRegisty + Push "AddToPathAllUsers" + Push "$ADD_TO_PATH_ALL_USERS" + Call ConditionalAddToRegisty + Push "AddToPathCurrentUser" + Push "$ADD_TO_PATH_CURRENT_USER" + Call ConditionalAddToRegisty + Push "InstallToDesktop" + Push "$INSTALL_DESKTOP" + Call ConditionalAddToRegisty + +; !insertmacro MUI_STARTMENU_WRITE_END + +@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@ + +SectionEnd + +Section "-Add to path" + Push $INSTDIR\bin + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath + StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0 + Call AddToPath + doNotAddToPath: +SectionEnd + +;-------------------------------- +; Create custom pages +Function InstallOptionsPage + !insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" + +FunctionEnd + +;-------------------------------- +; determine admin versus local install +Function un.onInit + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + Goto done + StrCmp $1 "Power" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + Goto done + + noLM: + ;Get installation folder from registry if available + + done: + +FunctionEnd + +;--- Add/Remove callback functions: --- +!macro SectionList MacroName + ;This macro used to perform operation on multiple sections. + ;List all of your components in following manner here. +@CPACK_NSIS_COMPONENT_SECTION_LIST@ +!macroend + +Section -FinishComponents + ;Removes unselected components and writes component status to registry + !insertmacro SectionList "FinishSection" + +!ifdef CPACK_NSIS_ADD_REMOVE + ; Get the name of the installer executable + System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1' + StrCpy $R3 $R0 + + ; Strip off the last 13 characters, to see if we have AddRemove.exe + StrLen $R1 $R0 + IntOp $R1 $R0 - 13 + StrCpy $R2 $R0 13 $R1 + StrCmp $R2 "AddRemove.exe" addremove_installed + + ; We're not running AddRemove.exe, so install it + CopyFiles $R3 $INSTDIR\AddRemove.exe + + addremove_installed: +!endif +SectionEnd +;--- End of Add/Remove callback functions --- + +;-------------------------------- +; Component dependencies +Function .onSelChange + !insertmacro SectionList MaybeSelectionChanged +FunctionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" +; ReadRegStr $START_MENU SHCTX \ +; "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" + ;MessageBox MB_OK "Start menu is in: $START_MENU" + ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "DoNotAddToPath" + ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathAllUsers" + ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathCurrentUser" + ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS" + ReadRegStr $INSTALL_DESKTOP SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "InstallToDesktop" + ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " + +@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + + ;Remove files we installed. + ;Keep the list of directories here in sync with the File commands above. +@CPACK_NSIS_DELETE_FILES@ +@CPACK_NSIS_DELETE_DIRECTORIES@ + +!ifdef CPACK_NSIS_ADD_REMOVE + ;Remove the add/remove program + Delete "$INSTDIR\AddRemove.exe" +!endif + + ;Remove the uninstaller itself. + Delete "$INSTDIR\Uninstall @CPACK_NSIS_PACKAGE_NAME@.exe" + DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ;Remove the installation directory if it is empty. + RMDir "$INSTDIR" + + ; Remove the registry entries. + DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ; Removes all optional components + !insertmacro SectionList "RemoveSection_CPack" + +; !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + +; Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + startMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors startMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + ; If the user changed the shortcut, then untinstall may not work. This should + ; try to fix it. +; StrCpy $MUI_TEMP "$START_MENU" +; Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + secondStartMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors secondStartMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop + secondStartMenuDeleteLoopDone: + + DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + Push $INSTDIR\bin + StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 + Call un.RemoveFromPath + doNotRemoveFromPath: +SectionEnd + +;-------------------------------- +; determine admin versus local install +; Is install for "AllUsers" or "JustMe"? +; Default to "JustMe" - set to "AllUsers" if admin or on Win9x +; This function is used for the very first "custom page" of the installer. +; This custom page does not show up visibly, but it executes prior to the +; first visible page and sets up $INSTDIR properly... +; Choose different default installation folder based on SV_ALLUSERS... +; "Program Files" for AllUsers, "My Documents" for JustMe... + +Function .onInit + StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst + + ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" + StrCmp $0 "" inst + + MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ + "@CPACK_NSIS_PACKAGE_NAME@ is already installed. $\n$\nDo you want to uninstall the old version before installing the new one?" \ + IDYES uninst IDNO inst + Abort + +;Run the uninstaller +uninst: + ClearErrors + StrLen $2 "\Uninstall @CPACK_NSIS_PACKAGE_NAME@.exe" + StrCpy $3 $0 -$2 # remove "\Uninstall @CPACK_NSIS_PACKAGE_NAME@.exe" from UninstallString to get path + ExecWait '$0 _?=$3' ;Do not copy the uninstaller to a temp file + + IfErrors uninst_failed inst +uninst_failed: + MessageBox MB_OK|MB_ICONSTOP "Uninstall failed." + Abort + + +inst: + ; Reads components status for registry + !insertmacro SectionList "InitSection" + + ; check to see if /D has been used to change + ; the install directory by comparing it to the + ; install directory that is expected to be the + ; default + StrCpy $IS_DEFAULT_INSTALLDIR 0 + StrCmp "$INSTDIR" "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2 + StrCpy $IS_DEFAULT_INSTALLDIR 1 + + StrCpy $SV_ALLUSERS "JustMe" + ; if default install dir then change the default + ; if it is installed for JustMe + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + StrCmp $1 "Power" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + + noLM: + StrCpy $SV_ALLUSERS "AllUsers" + ;Get installation folder from registry if available + + done: + StrCmp $SV_ALLUSERS "AllUsers" 0 +3 + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage + !insertmacro MUI_INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini" + + noOptionsPage: +FunctionEnd diff --git a/cmake/PluginConfigure.cmake b/cmake/PluginConfigure.cmake new file mode 100644 index 0000000..cd32867 --- /dev/null +++ b/cmake/PluginConfigure.cmake @@ -0,0 +1,80 @@ +##--------------------------------------------------------------------------- +## Author: Sean D'Epagnier +## Copyright: +## License: GPLv3+ +##--------------------------------------------------------------------------- + +SET(PLUGIN_SOURCE_DIR .) + +# This should be 2.8.0 to have FindGTK2 module +IF (COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 OLD) + CMAKE_POLICY(SET CMP0005 OLD) + CMAKE_POLICY(SET CMP0011 OLD) +ENDIF (COMMAND cmake_policy) + +MESSAGE (STATUS "*** Staging to build ${PACKAGE_NAME} ***") + +configure_file(cmake/version.h.in ${PROJECT_SOURCE_DIR}/src/version.h) +SET(PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}" ) + +#SET(CMAKE_BUILD_TYPE Debug) +#SET(CMAKE_VERBOSE_MAKEFILE ON) + +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src) + +# SET(PROFILING 1) + +# IF NOT DEBUGGING CFLAGS="-O2 -march=native" +IF(NOT MSVC) + IF(PROFILING) + ADD_DEFINITIONS( "-Wall -g -fprofile-arcs -ftest-coverage -fexceptions" ) + ELSE(PROFILING) +# ADD_DEFINITIONS( "-Wall -g -fexceptions" ) + ADD_DEFINITIONS( "-Wall -Wno-unused-result -g -O2 -fexceptions" ) + ENDIF(PROFILING) + + IF(NOT APPLE) + SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic") + ELSE(NOT APPLE) + SET(CMAKE_SHARED_LINKER_FLAGS "-Wl -undefined dynamic_lookup") + ENDIF(NOT APPLE) + +ENDIF(NOT MSVC) + +# Add some definitions to satisfy MS +IF(MSVC) + ADD_DEFINITIONS(-D__MSVC__) + ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_DEPRECATE) +ENDIF(MSVC) + +SET(wxWidgets_USE_LIBS base core net xml html adv) +SET(BUILD_SHARED_LIBS TRUE) + +FIND_PACKAGE(wxWidgets REQUIRED) + +IF(MSYS) +# this is just a hack. I think the bug is in FindwxWidgets.cmake +STRING( REGEX REPLACE "/usr/local" "\\\\;C:/MinGW/msys/1.0/usr/local" wxWidgets_INCLUDE_DIRS ${wxWidgets_INCLUDE_DIRS} ) +ENDIF(MSYS) + +INCLUDE(${wxWidgets_USE_FILE}) + +FIND_PACKAGE(OpenGL) +IF(OPENGL_GLU_FOUND) + + SET(wxWidgets_USE_LIBS ${wxWidgets_USE_LIBS} gl) + INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}) + + MESSAGE (STATUS "Found OpenGL..." ) + MESSAGE (STATUS " Lib: " ${OPENGL_LIBRARIES}) + MESSAGE (STATUS " Include: " ${OPENGL_INCLUDE_DIR}) + ADD_DEFINITIONS(-DocpnUSE_GL) +ELSE(OPENGL_GLU_FOUND) + MESSAGE (STATUS "OpenGL not found..." ) +ENDIF(OPENGL_GLU_FOUND) + +SET(BUILD_SHARED_LIBS TRUE) + +FIND_PACKAGE(Gettext REQUIRED) + diff --git a/cmake/PluginInstall.cmake b/cmake/PluginInstall.cmake new file mode 100644 index 0000000..d97a2f9 --- /dev/null +++ b/cmake/PluginInstall.cmake @@ -0,0 +1,91 @@ +##--------------------------------------------------------------------------- +## Author: Sean D'Epagnier +## Copyright: +## License: GPLv3+ +##--------------------------------------------------------------------------- + +IF(NOT APPLE) + TARGET_LINK_LIBRARIES( ${PACKAGE_NAME} ${wxWidgets_LIBRARIES} ${EXTRA_LIBS} ) +ENDIF(NOT APPLE) + +IF(WIN32) + SET(PARENT "opencpn") + + IF(MSVC) +# TARGET_LINK_LIBRARIES(${PACKAGE_NAME} +# gdiplus.lib +# glu32.lib) + TARGET_LINK_LIBRARIES(${PACKAGE_NAME} ${OPENGL_LIBRARIES}) + + SET(OPENCPN_IMPORT_LIB "${PARENT}.lib") + ENDIF(MSVC) + + IF(MINGW) +# assuming wxwidgets is compiled with unicode, this is needed for mingw headers + ADD_DEFINITIONS( " -DUNICODE" ) + TARGET_LINK_LIBRARIES(${PACKAGE_NAME} ${OPENGL_LIBRARIES}) + SET(OPENCPN_IMPORT_LIB "${PARENT}.dll") + SET( CMAKE_SHARED_LINKER_FLAGS "-L../buildwin" ) + ENDIF(MINGW) + + TARGET_LINK_LIBRARIES( ${PACKAGE_NAME} ${OPENCPN_IMPORT_LIB} ) +ENDIF(WIN32) + +IF(UNIX) + IF(PROFILING) + find_library(GCOV_LIBRARY + NAMES + gcov + PATHS + /usr/lib/gcc/i686-pc-linux-gnu/4.7 + ) + + SET(EXTRA_LIBS ${EXTRA_LIBS} ${GCOV_LIBRARY}) + ENDIF(PROFILING) +ENDIF(UNIX) + +IF(APPLE) + INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME LIBRARY DESTINATION ${CMAKE_BINARY_DIR}/OpenCPN.app/Contents/SharedSupport/plugins) + FIND_PACKAGE(ZLIB REQUIRED) + TARGET_LINK_LIBRARIES( ${PACKAGE_NAME} ${ZLIB_LIBRARIES} ) + INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME LIBRARY DESTINATION ${CMAKE_BINARY_DIR}/OpenCPN.app/Contents/PlugIns) +ENDIF(APPLE) + +IF(UNIX AND NOT APPLE) + FIND_PACKAGE(BZip2 REQUIRED) + INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR}) + FIND_PACKAGE(ZLIB REQUIRED) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES( ${PACKAGE_NAME} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARY} ) +ENDIF(UNIX AND NOT APPLE) + +SET(PARENT opencpn) + +SET(PREFIX_DATA share) +SET(PREFIX_LIB lib) + +IF(WIN32) + MESSAGE (STATUS "Install Prefix: ${CMAKE_INSTALL_PREFIX}") + SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/../OpenCPN) + IF(CMAKE_CROSSCOMPILING) + INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME DESTINATION "plugins") + SET(INSTALL_DIRECTORY "plugins/${PACKAGE_NAME}") + ELSE(CMAKE_CROSSCOMPILING) + INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME DESTINATION "plugins") + SET(INSTALL_DIRECTORY "plugins\\\\${PACKAGE_NAME}") + ENDIF(CMAKE_CROSSCOMPILING) + + IF(${BUNDLE_DATA} AND EXISTS ${PROJECT_SOURCE_DIR}/data) + INSTALL(DIRECTORY data DESTINATION "${INSTALL_DIRECTORY}") + ENDIF(${BUNDLE_DATA} AND EXISTS ${PROJECT_SOURCE_DIR}/data) +ENDIF(WIN32) + +IF(UNIX AND NOT APPLE) + SET(PREFIX_PARENTDATA ${PREFIX_DATA}/${PARENT}) + SET(PREFIX_PARENTLIB ${PREFIX_LIB}/${PARENT}) + INSTALL(TARGETS ${PACKAGE_NAME} RUNTIME LIBRARY DESTINATION ${PREFIX_PARENTLIB}) + + IF(${BUNDLE_DATA} AND EXISTS ${PROJECT_SOURCE_DIR}/data) + INSTALL(DIRECTORY data DESTINATION ${PREFIX_PARENTDATA}/plugins/${PACKAGE_NAME}) + ENDIF(${BUNDLE_DATA} AND EXISTS ${PROJECT_SOURCE_DIR}/data) +ENDIF(UNIX AND NOT APPLE) diff --git a/cmake/PluginLocalization.cmake b/cmake/PluginLocalization.cmake new file mode 100644 index 0000000..9f036e5 --- /dev/null +++ b/cmake/PluginLocalization.cmake @@ -0,0 +1,123 @@ +##--------------------------------------------------------------------------- +## Author: Pavel Kalian / Sean D'Epagnier +## Copyright: +## License: GPLv3+ +##--------------------------------------------------------------------------- + +FIND_PROGRAM(GETTEXT_XGETTEXT_EXECUTABLE xgettext) +string(REPLACE "_pi" "" I18N_NAME ${PACKAGE_NAME}) +IF (GETTEXT_XGETTEXT_EXECUTABLE) + ADD_CUSTOM_COMMAND( + OUTPUT po/${PACKAGE_NAME}.pot.dummy + COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --force-po --package-name=${PACKAGE_NAME} --package-version="${PACKAGE_VERSION}" --output=po/${PACKAGE_NAME}.pot --keyword=_ --width=80 --files-from=${CMAKE_CURRENT_SOURCE_DIR}/po/POTFILES.in + DEPENDS po/POTFILES.in po/${PACKAGE_NAME}.pot + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "${I18N_NAME}-pot-update [${PACKAGE_NAME}]: Generated pot file." + ) + ADD_CUSTOM_TARGET(${I18N_NAME}-pot-update COMMENT "[${PACKAGE_NAME}]-pot-update: Done." DEPENDS po/${PACKAGE_NAME}.pot.dummy) + +ENDIF(GETTEXT_XGETTEXT_EXECUTABLE ) + +MACRO(GETTEXT_UPDATE_PO _potFile) + SET(_poFiles ${_potFile}) + GET_FILENAME_COMPONENT(_absPotFile ${_potFile} ABSOLUTE) + + FOREACH (_currentPoFile ${ARGN}) + GET_FILENAME_COMPONENT(_absFile ${_currentPoFile} ABSOLUTE) + GET_FILENAME_COMPONENT(_poBasename ${_absFile} NAME_WE) + + ADD_CUSTOM_COMMAND( + OUTPUT ${_absFile}.dummy + COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --width=80 --strict --quiet --update --backup=none --no-location -s ${_absFile} ${_absPotFile} + DEPENDS ${_absPotFile} ${_absFile} + COMMENT "${I18N_NAME}-po-update [${_poBasename}]: Updated po file." + ) + + SET(_poFiles ${_poFiles} ${_absFile}.dummy) + + ENDFOREACH (_currentPoFile ) + + ADD_CUSTOM_TARGET(${I18N_NAME}-po-update COMMENT "[${PACKAGE_NAME}]-po-update: Done." DEPENDS ${_poFiles}) +ENDMACRO(GETTEXT_UPDATE_PO) + +IF (GETTEXT_MSGMERGE_EXECUTABLE) + FILE(GLOB PACKAGE_PO_FILES po/*.po) + GETTEXT_UPDATE_PO(po/${PACKAGE_NAME}.pot ${PACKAGE_PO_FILES}) +ENDIF(GETTEXT_MSGMERGE_EXECUTABLE) + +SET(_gmoFiles) +MACRO(GETTEXT_BUILD_MO) + FOREACH (_poFile ${ARGN}) + GET_FILENAME_COMPONENT(_absFile ${_poFile} ABSOLUTE) + GET_FILENAME_COMPONENT(_poBasename ${_absFile} NAME_WE) + SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_poBasename}.mo) + +IF(APPLE) + ADD_CUSTOM_COMMAND( + OUTPUT ${_gmoFile} + COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check -o ${_gmoFile} ${_absFile} + COMMAND ${CMAKE_COMMAND} -E copy ${_gmoFile} "Resources/${_poBasename}.lproj/opencpn-${PACKAGE_NAME}.mo" + DEPENDS ${_absFile} + COMMENT "${I18N_NAME}-i18n [${_poBasename}]: Created mo file." + ) +ELSE(APPLE) + ADD_CUSTOM_COMMAND( + OUTPUT ${_gmoFile} + COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check -o ${_gmoFile} ${_absFile} + COMMAND ${CMAKE_COMMAND} -E copy ${_gmoFile} "Resources/${_poBasename}/LC_MESSAGES/opencpn-${PACKAGE_NAME}.mo" + DEPENDS ${_absFile} + COMMENT "${I18N_NAME}-i18n [${_poBasename}]: Created mo file." + ) +ENDIF(APPLE) + +## Why are we copying files to “/use/local/bin/OpenCPN.app” under OSX? Shouldn’t we copy to “/Applications/OpenCPN.app”? +## Now the languages files will never be used when we do make install. + + IF(APPLE) + INSTALL(FILES ${_gmoFile} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/OpenCPN.app/Contents/Resources/${_poBasename}.lproj RENAME opencpn-${PACKAGE_NAME}.mo ) + ELSE(APPLE) + INSTALL(FILES ${_gmoFile} DESTINATION ${PREFIX_DATA}/locale/${_poBasename}/LC_MESSAGES RENAME opencpn-${PACKAGE_NAME}.mo ) + ENDIF(APPLE) + + SET(_gmoFiles ${_gmoFiles} ${_gmoFile}) + ENDFOREACH (_poFile ) +ENDMACRO(GETTEXT_BUILD_MO) + +if(GETTEXT_MSGFMT_EXECUTABLE) + FILE(GLOB PACKAGE_PO_FILES po/*.po) + GETTEXT_BUILD_MO(${PACKAGE_PO_FILES}) + ADD_CUSTOM_TARGET(${I18N_NAME}-i18n COMMENT "${PACKAGE_NAME}-i18n: Done." DEPENDS ${_gmoFiles}) + ADD_DEPENDENCIES(${PACKAGE_NAME} ${I18N_NAME}-i18n) +ENDIF(GETTEXT_MSGFMT_EXECUTABLE) + +IF(WIN32) + FIND_PROGRAM(ZIP_EXECUTABLE wzzip PATHS "$ENV{ProgramFiles}/WinZip") + IF(ZIP_EXECUTABLE) + SET(ZIP_COMMAND "${ZIP_EXECUTABLE} -P") + ENDIF(ZIP_EXECUTABLE) +ENDIF(WIN32) + +IF(UNIX) + FIND_PROGRAM(ZIP_EXECUTABLE zip) + IF(ZIP_EXECUTABLE) + SET(ZIP_COMMAND "${ZIP_EXECUTABLE} -r") + ENDIF(ZIP_EXECUTABLE) +ENDIF(UNIX) + +## +## This doesn't seem to work -- does everything, sets the variables, but doesn't +## actually build the zip file. Does anyone have any idea how to do this? +## +MACRO(BUILD_LANGUAGES_ZIP zipFile) + ADD_CUSTOM_COMMAND( + OUTPUT "${zipFile}" + COMMAND ${ZIP_COMMAND} "${zipFile}" "Resources/*" + COMMENT "Created zip file ${zipFile} using ${ZIP_COMMAND}" + ) +ENDMACRO(BUILD_LANGUAGES_ZIP) + +IF(ZIP_COMMAND) + BUILD_LANGUAGES_ZIP(${PACKAGE_NAME}_Languages.zip) + ADD_CUSTOM_TARGET(${PACKAGE_NAME}_Languages.zip COMMENT "${PACKAGE_NAME}_Languages.zip: Done." DEPENDS ${_gmoFiles}) + ADD_DEPENDENCIES(${PACKAGE_NAME} ${PACKAGE_NAME}_Languages.zip) +ENDIF(ZIP_COMMAND) diff --git a/cmake/PluginPackage.cmake b/cmake/PluginPackage.cmake new file mode 100644 index 0000000..5b14f48 --- /dev/null +++ b/cmake/PluginPackage.cmake @@ -0,0 +1,183 @@ +##--------------------------------------------------------------------------- +## Author: Sean D'Epagnier +## Copyright: +## License: GPLv3+ +##--------------------------------------------------------------------------- + +# build a CPack driven installer package +#include (InstallRequiredSystemLibraries) + +SET(CPACK_PACKAGE_NAME "${PACKAGE_NAME}") +SET(CPACK_PACKAGE_VENDOR "opencpn.org") +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CPACK_PACKAGE_NAME} ${PACKAGE_VERSION}) +SET(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION}) +SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) +SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR}) +SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH}) +SET(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_CURRENT_BINARY_DIR};${PACKAGE_NAME};ALL;/") +SET(CPACK_PACKAGE_EXECUTABLES OpenCPN ${PACKAGE_NAME}) + +IF(WIN32) +# to protect against confusable windows users, let us _not_ generate zip packages +# SET(CPACK_GENERATOR "NSIS;ZIP") + + # override install directory to put package files in the opencpn directory + SET(CPACK_PACKAGE_INSTALL_DIRECTORY "OpenCPN") + +# CPACK_NSIS_DIR ?? +# CPACK_BUILDWIN_DIR ?? +# CPACK_PACKAGE_ICON ?? + + SET(CPACK_NSIS_PACKAGE_NAME "${PACKAGE_NAME}") + + # Let cmake find NSIS.template.in + SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/buildwin") + +# These lines set the name of the Windows Start Menu shortcut and the icon that goes with it +# SET(CPACK_NSIS_INSTALLED_ICON_NAME "${PACKAGE_NAME}") +# SET(CPACK_NSIS_DISPLAY_NAME "OpenCPN ${PACKAGE_NAME}") + +# SET(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME}_${VERSION_MAJOR}.${VERSION_MINOR}_setup" ) + + SET(CPACK_NSIS_DIR "${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode") #Gunther + SET(CPACK_BUILDWIN_DIR "${PROJECT_SOURCE_DIR}/buildwin") #Gunther + +ELSE(WIN32) + SET(CPACK_PACKAGE_INSTALL_DIRECTORY ${PACKAGE_NAME}) +ENDIF(WIN32) + +SET(CPACK_STRIP_FILES "${PACKAGE_NAME}") + +SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpl.txt") + +IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/README") +# MESSAGE(STATUS "Using generic cpack package description file.") + SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") + SET(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README") +ENDIF () + +#SET(CPACK_SOURCE_GENERATOR "TGZ") + +# The following components are regex's to match anywhere (unless anchored) +# in absolute path + filename to find files or directories to be excluded +# from source tarball. +set(CPACK_SOURCE_IGNORE_FILES +"^${CMAKE_CURRENT_SOURCE_DIR}/.git/*" +"^${CMAKE_CURRENT_SOURCE_DIR}/build*" +"^${CPACK_PACKAGE_INSTALL_DIRECTORY}/*" +) + +IF(UNIX AND NOT APPLE) +# INCLUDE(UseRPMTools) +# IF(RPMTools_FOUND) +# RPMTools_ADD_RPM_TARGETS(packagename ${PROJECT_SOURCE_DIR}/package.spec) +# ENDIF(RPMTools_FOUND) + +# need apt-get install rpm, for rpmbuild + SET(PACKAGE_DEPS "opencpn, bzip2, gzip") + SET(PACKAGE_RELEASE 1) + + + IF (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*") + SET (ARCH "armhf") + # don't bother with rpm on armhf + SET(CPACK_GENERATOR "DEB;RPM;TBZ2") + ELSE () + SET(CPACK_GENERATOR "DEB;RPM;TBZ2") + + IF (CMAKE_SIZEOF_VOID_P MATCHES "8") + SET (ARCH "amd64") + SET(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") + ELSE (CMAKE_SIZEOF_VOID_P MATCHES "8") + SET (ARCH "i386") + # note: in a chroot must use "setarch i686 make package" + SET(CPACK_RPM_PACKAGE_ARCHITECTURE "i686") + ENDIF (CMAKE_SIZEOF_VOID_P MATCHES "8") + ENDIF () + + SET(CPACK_DEBIAN_PACKAGE_DEPENDS ${PACKAGE_DEPS}) + SET(CPACK_DEBIAN_PACKAGE_RECOMMENDS ${PACKAGE_RECS}) + SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${ARCH}) + SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}") + SET(CPACK_DEBIAN_PACKAGE_SECTION "misc") + SET(CPACK_DEBIAN_COMPRESSION_TYPE "xz") # requires my patches to cmake + + SET(CPACK_RPM_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}") + SET(CPACK_RPM_PACKAGE_REQUIRES ${PACKAGE_DEPS}) +# SET(CPACK_RPM_PACKAGE_GROUP "Applications/Engineering") + SET(CPACK_RPM_PACKAGE_LICENSE "gplv3+") + + SET(CPACK_RPM_COMPRESSION_TYPE "xz") +# SET(CPACK_RPM_USER_BINARY_SPECFILE "${PROJECT_SOURCE_DIR}/opencpn.spec.in") + + SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE_NAME} PlugIn for OpenCPN") + SET(CPACK_PACKAGE_DESCRIPTION "${PACKAGE_NAME} PlugIn for OpenCPN") +# SET(CPACK_SET_DESTDIR ON) + SET(CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + + + SET(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME}_${PACKAGE_VERSION}-${PACKAGE_RELEASE}_${ARCH}" ) +ENDIF(UNIX AND NOT APPLE) + +IF(TWIN32 AND NOT UNIX) +# configure_file(${PROJECT_SOURCE_DIR}/src/opencpn.rc.in ${PROJECT_SOURCE_DIR}/src/opencpn.rc) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_GERMAN.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_GERMAN.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_FRENCH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_FRENCH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_CZECH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_CZECH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_DANISH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_DANISH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_SPANISH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_SPANISH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_ITALIAN.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_ITALIAN.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_DUTCH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_DUTCH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_POLISH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_POLISH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_PORTUGUESEBR.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_PORTUGUESEBR.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_PORTUGUESE.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_PORTUGUESE.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_RUSSIAN.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_RUSSIAN.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_SWEDISH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_SWEDISH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_FINNISH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_FINNISH.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_NORWEGIAN.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_NORWEGIAN.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_CHINESETW.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_CHINESETW.nsh" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/buildwin/NSIS_Unicode/Language files/Langstrings_TURKISH.nsh.in" "${PROJECT_SOURCE_DIR}//buildwin/NSIS_Unicode/Include/Langstrings_TURKISH.nsh" @ONLY) +ENDIF(TWIN32 AND NOT UNIX) + + +# this dummy target is necessary to make sure the ADDITIONAL_MAKE_CLEAN_FILES directive is executed. +# apparently, the base CMakeLists.txt file must have "some" target to activate all the clean steps. +#ADD_CUSTOM_TARGET(dummy COMMENT "dummy: Done." DEPENDS ${PACKAGE_NAME}) + + +INCLUDE(CPack) + + +IF(APPLE) + + # Copy a bunch of files so the Packages installer builder can find them + # relative to ${CMAKE_CURRENT_BINARY_DIR} + # This avoids absolute paths in the wmm.pkgproj file + +configure_file(${PROJECT_SOURCE_DIR}/cmake/gpl.txt + ${CMAKE_CURRENT_BINARY_DIR}/license.txt COPYONLY) + +configure_file(${PROJECT_SOURCE_DIR}/buildosx/InstallOSX/pkg_background.jpg + ${CMAKE_CURRENT_BINARY_DIR}/pkg_background.jpg COPYONLY) + + # Patch the pkgproj.in file to make the output package name conform to Xxx-Plugin_x.x.pkg format + # Key is: + # NAME + # ${VERBOSE_NAME}-Plugin_${VERSION_MAJOR}.${VERSION_MINOR} + + configure_file(${PROJECT_SOURCE_DIR}/buildosx/InstallOSX/${PACKAGE_NAME}.pkgproj.in + ${CMAKE_CURRENT_BINARY_DIR}/${VERBOSE_NAME}.pkgproj) + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${VERBOSE_NAME}-Plugin.pkg + COMMAND /usr/local/bin/packagesbuild -F ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${VERBOSE_NAME}.pkgproj + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${PACKAGE_NAME} + COMMENT "create-pkg [${PACKAGE_NAME}]: Generating pkg file." +) + + ADD_CUSTOM_TARGET(create-pkg COMMENT "create-pkg: Done." + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${VERBOSE_NAME}-Plugin.pkg ) + + +ENDIF(APPLE) diff --git a/cmake/gpl.txt b/cmake/gpl.txt new file mode 100644 index 0000000..cd5c7e9 --- /dev/null +++ b/cmake/gpl.txt @@ -0,0 +1,413 @@ + + +This program is distributed under the terms of the GPL v2. + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +--------------------------------------------------------------------------- +Additional Licenses +--------------------------------------------------------------------------- +Portions of this program are distributed under the terms of the New BSD +License. Those portions, herinafter called "BSD Modules", include: + +FindPortaudio.cmake +Copyright (c) 2006 Andreas Schneider + +CrashRpt Package +Copyright (c) 2003, The CrashRpt Project Authors. + +Redistribution and use is allowed according to the terms of the New BSD license. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +* Neither the name of the BSD Modules nor the names of its +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- +Portions of this program are distributed under the terms of the MIT License. +Those portions, herinafter called "MIT Modules", include: + +pugixml library (http://pugixml.org). +pugixml is Copyright (C) 2006-2012 Arseny Kapoulkine. + + +The MIT License (MIT) + +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 +AUTHORS OR COPYRIGHT HOLDERS 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. + diff --git a/cmake/version.h.in b/cmake/version.h.in new file mode 100644 index 0000000..87488ec --- /dev/null +++ b/cmake/version.h.in @@ -0,0 +1,3 @@ +#define PLUGIN_VERSION_MAJOR ${VERSION_MAJOR} +#define PLUGIN_VERSION_MINOR ${VERSION_MINOR} +#define PLUGIN_VERSION_DATE "${VERSION_DATE}" diff --git a/de.mo b/de.mo deleted file mode 100644 index 1e72946c2215786bfd5d656f1004e4b3c8a86b4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 529 zcmZvW%}N6?6osQz!GastF0wBfXZiyr{vg&Wr7f0r6n8atuG8o=cSusT&mq2^&*Ghq z(v25B4oObVJ>Q2rUyPvgT{lQz*SDoJbd`$JX6}7@Y!5h2mb6X zz839`uUPyHR&>n_6Kzt-+fUk8AH)q9uw|nWLZUs7f>zL?m+~n3uzE+ExPf+F^65zm rzS#GtQ-hdq+?UEhuKZl`U~@UarJX^iY$kbGjdiW_kY!-l08{n@tYndZ diff --git a/default.mo b/default.mo deleted file mode 100644 index b0ff129ef6ff360ec58a151d755099707f23f3b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 472 zcmZ9H!A=4(5QZ^&+M{O=J$S=eyNkrNs4*fM0z`tV@kYw-xKyFtv_<7Xy!vQ9i?i7v ziGT8EI-M`mzd!qXUk%a@`G9;#-X$NAD<$M_8lF+Dm_LoJdBw~_KZhr@P8luO*es+C zCRiHlVdM&x!}Y3gkQ%{)@qG$ii_#McH`1eEF^^in+Yp^F-V$-rszg1<1S99Z+QZ2$9FNxK~N)`wy$|Z%_^mH8c zN4@PAqL2q&qdjWcy)G%F$4`G;E~L^Omd&Mg=r11ATS&HCmEi>~^mJx&r3=B5nexFi z+@VHWhZ`Hrm1j}d4%;-TTNvQ_!`R#nmGgp4I|cgcy-l5JW6CXkEghE9&jky&mk(xT NGwjyM1goPpegTtNiU0rr diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..999f98a --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,12 @@ +src/polar_pi.h +src/polar_pi.cpp +src/Options.h +src/Options.cpp +src/Polar.h +src/Polar.cpp +src/PolarDialog.h +src/PolarDialog.cpp +src/PolarGui.h +src/PolarGui.cpp +src/icons.h +src/icons.cpp diff --git a/po/de.mo b/po/de.mo deleted file mode 100644 index 625f460ca6e811943c3e75bc57c99dce44d240a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3487 zcmai$O^h5z6~_xOU!9O(118}s6~H!$-Q(SL)!D*xorVv?2tET(!fWt;*oW_f4t@}B z!4vS?@B#QT{1E&R`~dtJlzzW}r{LRg4gRIAzw}YyO;`cFbJgWPkjC&kD2v5R~z|&Cdb>YY1 zO8Y&9V$VZ<>P2pk!|%e^;ZNZsaGgdHj}l5qUxMQ2_gcOVKf(Ji;k)5G@MYHEkMK0_ zjv&Z9e+b3SZ76a5Ipn9_=0;QXJNPm94wUbIh0^ceu$do=C-XTD#qKG%4p*Se_cbW( z-hk5oO~@3~uOL75o3{Syq6#@ zs_#Sb{}m{4{&D-h2PH560LA}*K(QaOh!W2e@Qd&y{0Y1cKMVf_KMEfq2r|wSP{VG^ zZ@|y+{vs4RuR_A!!~*PJ5-YiwX477tWu0Wd$h@YPfW{5>xSC_M}`N4ru27NuD)D^7jly zt`0@^i^TXGMXpm6!nJ=9VniUx2X&r!qpOKAY22^#-1tflU8#3;YDT3ol~xP6NlLw# z_(Ux@S`2(#M!XhhCps zTvv->;I8VWnb$>PYm?`yXGfXEQ=gRHr24#GHv?Cu;!0Lg?IshGs@_ggOmfqWR+F80 zLuREf>A7?B`j)Sv4I|D|H9MnEQ9pBTE__%|?8pQc=cLZNX&-ep%e^V-)8Fl?6_=z6 z%N^}(zN=PUYPxE5cO~hYT&)qN%INJR^BuM3a*0`%jLM{F-`4Vav}~K`-k2D>uy*}_ zeu$=DN;711J1~`MoDBEiYLV<@MO}o&6Q7IB*0gKlqNm)DfT?xjRCU!xlI0cmEz{g| zaFaRm-ULS{p)NjJ$FfXoyiUWc3K?=o-?GkQa_qKSYuUhAwc+Y=KyaERa4mFQkxv7c z*M-#^o6ko}Ya2)FZY-(IvC$JEm06vKbh+iM%~)i6#_P!F`m7s=Pq=gm_Iu+H#0-Sc-?GeV)EYYE}os4rQJ$W`FOKTY=w}xva7E( ztMzoVXnpg{*!hCEcT)2u+S*Y~%;HUxARE!@@@ntE@7c~wwBW2~lJVy51kb$L@#iOb zlG&&9V4Red@t2<6yc$1w&`t(shr~TQaH0iW{bWD$(O2UoV_BcZqcvwlNM<|poq4{5 z*Z7**-9|sEm8|kzeeTcqU!0>kZ>y zAO`IzQ;-Tnvg;axjN@N78R`@Sei=zd&(v4sB*hudVJX_y7-;h};hfV~(;&(rbwkzO zoh6+WO^($BVlk<-oMf^PL7&5pXB%nDUa5-%$xo5b+t-ff~fGDAis$cG!u->X4k O#-TgveUJX6kNOXnVS-cu diff --git a/po/de.po b/po/de.po index 9226dce..84d7f62 100644 --- a/po/de.po +++ b/po/de.po @@ -2,10 +2,11 @@ msgid "" msgstr "" "Project-Id-Version: Polar\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-06-16 23:45+0200\n" +"POT-Creation-Date: 2015-02-12 17:27+0100\n" "PO-Revision-Date: 2013-06-16 23:46+0100\n" "Last-Translator: Konni \n" "Language-Team: \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -13,174 +14,245 @@ msgstr "" "X-Poedit-KeywordsList: _;gettext;gettext_noop\n" "X-Poedit-Basepath: .\n" "X-Poedit-SourceCharset: UTF-8\n" - # -#: src/PolarGui.h:98 -msgid "Polar Diagram" -msgstr "Polar Diagramm" - +msgid "\"" +msgstr "" # -#: src/PolarGui.cpp:25 -msgid "Mode:" -msgstr "Modus:" - +msgid "'" +msgstr "" +# +msgid "?" +msgstr "" +# +msgid "Calculate speed-bullets for x degrees " +msgstr "Berechne die Speed-Bullets für x Grad" +# +msgid "Clear Data" +msgstr "Lösche Daten" +# +msgid "Collecting Data from: " +msgstr "Sammle Daten von: " +# +msgid "Collecting: " +msgstr "Sammle Daten: " +# +msgid "Create" +msgstr "Erstellen" +# +msgid "Current <" +msgstr "Strom <" # -#: src/PolarGui.cpp:29 msgid "Data from Logbooks" msgstr "Daten aus Logbüchern" - # -#: src/PolarGui.cpp:29 msgid "Data from NMEA" msgstr "Daten von NMEA" - # -#: src/PolarGui.cpp:29 msgid "Data from VDR" msgstr "Daten von VDR" - # -#: src/PolarGui.cpp:29 -msgid "Edit manuell" +msgid "Degrees:" +msgstr "Grad:" +# +msgid "E" +msgstr "" +# +#, fuzzy +msgid "Edit manual" msgstr "Manuelles Editieren" - # -#: src/PolarGui.cpp:35 -msgid "Rings:" -msgstr "Ringe:" - +msgid "Engine started / Recording is stopped" +msgstr "Maschine gestartet / Aufnahme gestoppt" # -#: src/PolarGui.cpp:43 -msgid "Set diagramm to x knots" -msgstr "Setzte Diagramm auf x Knoten" - +msgid "" +"Example:\n" +"Max-Speed = 2,5 kts\n" +"Selected 10 % = 0,25 kts\n" +"Range from 2,25 to 2,5 kts" +msgstr "" +"Beispiel:\n" +"Max-Speed = 2,5 kts\n" +"Selected 10% = 0,25 kts\n" +"Bereich von 2,25 bis 2,5 kts" # -#: src/PolarGui.cpp:47 -msgid "Degrees:" -msgstr "Grad:" - +msgid "F" +msgstr "" # -#: src/PolarGui.cpp:55 -msgid "Calculate speed-bullets for x degrees " -msgstr "Berechne die Speed-Bullets für x Grad" - +msgid "Filter" +msgstr "" # -#: src/PolarGui.cpp:59 src/Polar.cpp:1364 -msgid "Wind:" +msgid "Filtered by:" +msgstr "Gefiltert nach:" +# +msgid "Fo1" msgstr "" - # -#: src/PolarGui.cpp:63 src/PolarGui.cpp:90 src/Polar.cpp:1384 -#: src/Polar.cpp:1397 -msgid "any" -msgstr "alles" - +msgid "Fo2" +msgstr "" # -#: src/PolarGui.cpp:72 -msgid "Source:" -msgstr "Quelle:" - +msgid "Fo3" +msgstr "" # -#: src/PolarGui.cpp:76 -msgid "Speedo" -msgstr "Log" - +msgid "Fock 1" +msgstr "" +# +msgid "Fock 2" +msgstr "" +# +msgid "Fock 3" +msgstr "" # -#: src/PolarGui.cpp:76 msgid "GPS" msgstr "" - # -#: src/PolarGui.cpp:80 -msgid "" -"Speedo uses column STW\n" -"GPS uses column SOG" +msgid "Ge1" msgstr "" -"Log nutzt die Spalte FdW\n" -"GPS die Spalte FüG im Logbuch" - # -#: src/PolarGui.cpp:84 -msgid "Current <" -msgstr "Strom <" - +msgid "Ge2" +msgstr "" # -#: src/PolarGui.cpp:98 -msgid "Filter" +msgid "Ge3" msgstr "" - # -#: src/PolarGui.cpp:104 -msgid "Create" -msgstr "Erstellen" - +msgid "Genoa 1" +msgstr "" # -#: src/PolarGui.cpp:110 -msgid "Save" -msgstr "Speichern" - +msgid "Genoa 2" +msgstr "" +# +msgid "Genoa 3" +msgstr "" +# +msgid "Ji" +msgstr "" +# +msgid "Jib" +msgstr "" # -#: src/PolarGui.cpp:113 msgid "Load" msgstr "Laden" - # -#: src/PolarGui.cpp:212 -msgid "Clear Data" -msgstr "Lösche Daten" - +msgid "Ma" +msgstr "" # -#: src/PolarGui.cpp:215 -msgid "Record Start" -msgstr "Aufnahme Start" - +msgid "Main" +msgstr "" +# +msgid "Max. only" +msgstr "Max. von allen" +# +msgid "Mi" +msgstr "" +# +msgid "Mizzen" +msgstr "" +# +msgid "Mizzen Storm" +msgstr "" +# +msgid "Mode:" +msgstr "Modus:" +# +msgid "Mt" +msgstr "" +# +msgid "MyLabel" +msgstr "Mein Label" +# +msgid "NM" +msgstr "" +# +msgid "Please wait." +msgstr "Bitte warte..." # -#: src/polar_pi.cpp:121 src/polar_pi.cpp:183 src/polar_pi.cpp:209 -#: src/polar_pi.cpp:231 src/polar_pi.cpp:260 msgid "Polar" msgstr "" - # -#: src/polar_pi.cpp:189 +msgid "Polar Diagram" +msgstr "Polar Diagramm" +# +msgid "Polar Filter" +msgstr "" +# msgid "Polar PlugIn for OpenCPN" msgstr "Polar Plugin für OpenCPN" - # -#: src/polar_pi.cpp:195 msgid "Polar PlugIn for OpenCPN\n" msgstr "Polar Plugin für OpenCPN\n" - # -#: src/polar_pi.cpp:222 msgid "Polar Preferences" msgstr "Polar Einstellungen" - # -#: src/polar_pi.cpp:235 +msgid "Range" +msgstr "Bereich" +# +msgid "Range from maximum speed to minus" +msgstr "Bereich vom Max.-Speed bis minus" +# +msgid "Record " +msgstr "Aufnahme" +# +msgid "Record Start" +msgstr "Aufnahme Start" +# +msgid "Rings:" +msgstr "Ringe:" +# +msgid "Sails" +msgstr "Segel" +# +msgid "Save" +msgstr "Speichern" +# +msgid "Save Polar File" +msgstr "Speichere Polar Datei" +# +msgid "Select a Polar-File" +msgstr "Wähle eine Polar-Datei" +# +msgid "Select a VDR-File" +msgstr "Wähle eine VDR-Datei" +# +msgid "Set diagramm to x knots" +msgstr "Setzte Diagramm auf x Knoten" +# msgid "Show Polar icon" msgstr "Zeige Polar Icon an" - # -#: src/polar_pi.cpp:238 msgid "Show metres/sec for Wind Speed" msgstr "" - # -#: src/PolarDialog.cpp:38 +msgid "Source:" +msgstr "Quelle:" +# +msgid "Sp" +msgstr "" +# +msgid "Speedo" +msgstr "Log" +# +msgid "" +"Speedo uses column STW\n" +"GPS uses column SOG" +msgstr "" +"Log nutzt die Spalte FdW\n" +"GPS die Spalte FüG im Logbuch" +# +msgid "Spinnacker" +msgstr "" +# +msgid "St" +msgstr "" +# msgid "Start" msgstr "" - # -#: src/PolarDialog.cpp:38 +msgid "Staysail" +msgstr "" +# msgid "Stop" msgstr "" - # -#: src/PolarDialog.cpp:40 -msgid "Record " -msgstr "Aufnahme" - -#: src/PolarDialog.cpp:167 msgid "" "The plugin logbookkonni isn't installed\n" "\n" @@ -193,129 +265,80 @@ msgstr "" "Es wird benötigt um Daten aus allen Logbüchern zu sammeln\n" "\n" "Der Create-Button ist nicht sichtbar und der Modus nicht wählbar" - # -#: src/Polar.h:190 -msgid "Polar Filter" +msgid "Tr" msgstr "" - -#: src/Polar.cpp:63 -msgid "Max. only" -msgstr "Max. von allen" - # -#: src/Polar.cpp:184 -msgid "Engine started / Recording is stopped" -msgstr "Maschine gestartet / Aufnahme gestoppt" - +msgid "Try" +msgstr "" # -#: src/Polar.cpp:201 -msgid "Select a VDR-File" -msgstr "Wähle eine VDR-Datei" - +msgid "Use Average from all speed-data" +msgstr "Durchschnitt von allen Speed-Daten" # -#: src/Polar.cpp:214 src/Polar.cpp:394 -msgid "Please wait." -msgstr "Bitte warte..." - +msgid "Use Max-Speed only" +msgstr "Nutze nur Max.-Speed" # -#: src/Polar.cpp:316 -msgid "less than 3 entries found" -msgstr "weniger als 3 Einträge gefunden" - +msgid "Wavehight" +msgstr "" # -#: src/Polar.cpp:319 -msgid "less than 5 entries found" -msgstr "weniger als 5 Einträge gefunden" - +msgid "Wavehight from" +msgstr "" # -#: src/Polar.cpp:322 -msgid "more than 10 entries found" -msgstr "mehr als 10 Einträge gefunden" - +msgid "Wind:" +msgstr "" # -#: src/Polar.cpp:365 -msgid "Filtered by:" -msgstr "Gefiltert nach:" - +msgid "" +"You can change the abbreviations and the names of the sails\n" +"in Options/Miscellaneous/Sails(Logbook)" +msgstr "" # -#: src/Polar.cpp:401 -msgid "Collecting: " -msgstr "Sammle Daten: " - +msgid "any" +msgstr "alles" # -#: src/Polar.cpp:818 -msgid "Save Polar File" -msgstr "Speichere Polar Datei" - +msgid "day(s)" +msgstr "" # -#: src/Polar.cpp:992 -msgid "Select a Polar-File" -msgstr "Wähle eine Polar-Datei" - -#: src/Polar.cpp:1217 -msgid "Use Max-Speed only" -msgstr "Nutze nur Max.-Speed" - +msgid "ft" +msgstr "" # -#: src/Polar.cpp:1224 -msgid "Use Average from all speed-data" -msgstr "Durchschnitt von allen Speed-Daten" - +msgid "fth" +msgstr "" # -#: src/Polar.cpp:1230 -msgid "Range from maximum speed to minus" -msgstr "Bereich vom Max.-Speed bis minus" - +msgid "gal" +msgstr "" # -#: src/Polar.cpp:1231 -msgid "" -"Example:\n" -"Max-Speed = 2,5 kts\n" -"Selected 10 % = 0,25 kts\n" -"Range from 2,25 to 2,5 kts" +msgid "h" msgstr "" -"Beispiel:\n" -"Max-Speed = 2,5 kts\n" -"Selected 10% = 0,25 kts\n" -"Bereich von 2,25 bis 2,5 kts" - # -#: src/Polar.cpp:1248 -msgid "Range" -msgstr "Bereich" - +msgid "km/h" +msgstr "" # -#: src/Polar.cpp:1270 -msgid "Sails" -msgstr "Segel" - +msgid "kts" +msgstr "" # -#: src/Polar.cpp:1281 -msgid "MyLabel" -msgstr "Mein Label" - +msgid "less than 3 entries found" +msgstr "weniger als 3 Einträge gefunden" # -#: src/Polar.cpp:1295 -msgid "Wavehight" +msgid "less than 5 entries found" +msgstr "weniger als 5 Einträge gefunden" +# +msgid "m" msgstr "" - # -#: src/Polar.cpp:1372 -msgid "kts" +msgid "m/s" msgstr "" - # -#: src/Polar.cpp:1379 -msgid "Wavehight from" +msgid "mb" msgstr "" - # -#: src/Polar.cpp:1392 +msgid "month" +msgstr "" +# +msgid "more than 10 entries found" +msgstr "mehr als 10 Einträge gefunden" +# msgid "to" msgstr "bis" - # -#: src/Polar.cpp:1452 -msgid "Collecting Data from: " -msgstr "Sammle Daten von: " +msgid "week(s)" +msgstr "" diff --git a/po/default.mo b/po/default.mo deleted file mode 100644 index a116241f837d840a0c8fd84bdfcab20371e62178..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 438 zcmZvW!A`?442Fl`)FWpOIdFrNW~eYSK!`EWv`th{5Vy%|O&92rD)E3xyaunwvyiHS zUihV7R_xF5|GmBS)$!W!-tpe`-t^x0uGRDY^urThYvxahH7}SEALaZJty4xzmY5Q3 zkldzxU=hgo_!SUJ){Vp=k76#mOdQEL-it&Od63`Xo2qyJ;f|$<8g2rPcxpkr63AG| z#zt$!PG9RX$BTubC8#pY@jRG-E>=(=PZ5@q1=G=V*aj3~6by_e)c(VD<&zP9&_Pv# z(tVaKz&fO}hxD5FTCP6)jFt~|W^$zq$$E1|!4tnhjkZaY7|azh5yoNcC(V\n" "Language-Team: \n" @@ -15,6 +15,15 @@ msgstr "" "X-Poedit-Basepath: .\n" "X-Poedit-SourceCharset: UTF-8\n" # +msgid "\"" +msgstr "" +# +msgid "'" +msgstr "" +# +msgid "?" +msgstr "" +# msgid "Calculate speed-bullets for x degrees " msgstr "" # @@ -45,7 +54,10 @@ msgstr "" msgid "Degrees:" msgstr "" # -msgid "Edit manuell" +msgid "E" +msgstr "" +# +msgid "Edit manual" msgstr "" # msgid "Engine started / Recording is stopped" @@ -58,24 +70,93 @@ msgid "" "Range from 2,25 to 2,5 kts" msgstr "" # +msgid "F" +msgstr "" +# msgid "Filter" msgstr "" # msgid "Filtered by:" msgstr "" # +msgid "Fo1" +msgstr "" +# +msgid "Fo2" +msgstr "" +# +msgid "Fo3" +msgstr "" +# +msgid "Fock 1" +msgstr "" +# +msgid "Fock 2" +msgstr "" +# +msgid "Fock 3" +msgstr "" +# msgid "GPS" msgstr "" # +msgid "Ge1" +msgstr "" +# +msgid "Ge2" +msgstr "" +# +msgid "Ge3" +msgstr "" +# +msgid "Genoa 1" +msgstr "" +# +msgid "Genoa 2" +msgstr "" +# +msgid "Genoa 3" +msgstr "" +# +msgid "Ji" +msgstr "" +# +msgid "Jib" +msgstr "" +# msgid "Load" msgstr "" # +msgid "Ma" +msgstr "" +# +msgid "Main" +msgstr "" +# +msgid "Max. only" +msgstr "" +# +msgid "Mi" +msgstr "" +# +msgid "Mizzen" +msgstr "" +# +msgid "Mizzen Storm" +msgstr "" +# msgid "Mode:" msgstr "" # +msgid "Mt" +msgstr "" +# msgid "MyLabel" msgstr "" # +msgid "NM" +msgstr "" +# msgid "Please wait." msgstr "" # @@ -139,6 +220,9 @@ msgstr "" msgid "Source:" msgstr "" # +msgid "Sp" +msgstr "" +# msgid "Speedo" msgstr "" # @@ -147,13 +231,19 @@ msgid "" "GPS uses column SOG" msgstr "" # +msgid "Spinnacker" +msgstr "" +# +msgid "St" +msgstr "" +# msgid "Start" msgstr "" # -msgid "Stop" +msgid "Staysail" msgstr "" # -msgid "Testing, work in progress..." +msgid "Stop" msgstr "" # msgid "" @@ -161,12 +251,21 @@ msgid "" "\n" "It's needed to collect wind/speed-data from all available logbooks\n" "\n" -"The create-button is hidden" +"The create-button is hidden and the mode isn't useable" +msgstr "" +# +msgid "Tr" +msgstr "" +# +msgid "Try" msgstr "" # msgid "Use Average from all speed-data" msgstr "" # +msgid "Use Max-Speed only" +msgstr "" +# msgid "Wavehight" msgstr "" # @@ -176,13 +275,30 @@ msgstr "" msgid "Wind:" msgstr "" # -msgid "Work in progess" +msgid "" +"You can change the abbreviations and the names of the sails\n" +"in Options/Miscellaneous/Sails(Logbook)" msgstr "" # -msgid "Work in progress" +msgid "any" msgstr "" # -msgid "any" +msgid "day(s)" +msgstr "" +# +msgid "ft" +msgstr "" +# +msgid "fth" +msgstr "" +# +msgid "gal" +msgstr "" +# +msgid "h" +msgstr "" +# +msgid "km/h" msgstr "" # msgid "kts" @@ -194,8 +310,23 @@ msgstr "" msgid "less than 5 entries found" msgstr "" # +msgid "m" +msgstr "" +# +msgid "m/s" +msgstr "" +# +msgid "mb" +msgstr "" +# +msgid "month" +msgstr "" +# msgid "more than 10 entries found" msgstr "" # msgid "to" msgstr "" +# +msgid "week(s)" +msgstr "" diff --git a/po/default.pot b/po/default.pot deleted file mode 100644 index 8bba8d8..0000000 --- a/po/default.pot +++ /dev/null @@ -1,14 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Polar\n" -"POT-Creation-Date: 2013-05-12 16:55+0100\n" -"PO-Revision-Date: 2013-05-12 16:56+0100\n" -"Last-Translator: Konni \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.5\n" -"X-Poedit-KeywordsList: _;gettext;gettext_noop\n" -"X-Poedit-Basepath: .\n" -"X-Poedit-SourceCharset: UTF-8\n" diff --git a/po/polar_pi.pot b/po/polar_pi.pot index 8cade39..56d310e 100644 --- a/po/polar_pi.pot +++ b/po/polar_pi.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: polar_pi 3.3.604\n" +"Project-Id-Version: polar_pi 1.001\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-06-16 23:45+0200\n" +"POT-Creation-Date: 2015-02-12 17:27+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,208 +17,274 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: src/PolarGui.h:98 -msgid "Polar Diagram" +#: src/polar_pi.cpp:120 src/polar_pi.cpp:182 src/polar_pi.cpp:208 +#: src/polar_pi.cpp:230 src/polar_pi.cpp:259 +msgid "Polar" msgstr "" -#: src/PolarGui.cpp:25 -msgid "Mode:" +#: src/polar_pi.cpp:188 +msgid "Polar PlugIn for OpenCPN" msgstr "" -#: src/PolarGui.cpp:29 -msgid "Data from Logbooks" +#: src/polar_pi.cpp:194 +msgid "Polar PlugIn for OpenCPN\n" msgstr "" -#: src/PolarGui.cpp:29 -msgid "Data from NMEA" +#: src/polar_pi.cpp:221 +msgid "Polar Preferences" msgstr "" -#: src/PolarGui.cpp:29 -msgid "Data from VDR" +#: src/polar_pi.cpp:234 +msgid "Show Polar icon" msgstr "" -#: src/PolarGui.cpp:29 -msgid "Edit manuell" +#: src/polar_pi.cpp:237 +msgid "Show metres/sec for Wind Speed" msgstr "" -#: src/PolarGui.cpp:35 -msgid "Rings:" +#: src/Options.cpp:51 +msgid "Ma" msgstr "" -#: src/PolarGui.cpp:43 -msgid "Set diagramm to x knots" +#: src/Options.cpp:52 +msgid "Tr" msgstr "" -#: src/PolarGui.cpp:47 -msgid "Degrees:" +#: src/Options.cpp:53 +msgid "Ge1" msgstr "" -#: src/PolarGui.cpp:55 -msgid "Calculate speed-bullets for x degrees " +#: src/Options.cpp:54 +msgid "Ge2" msgstr "" -#: src/PolarGui.cpp:59 src/Polar.cpp:1364 -msgid "Wind:" +#: src/Options.cpp:55 +msgid "Ge3" msgstr "" -#: src/PolarGui.cpp:63 src/PolarGui.cpp:90 src/Polar.cpp:1384 -#: src/Polar.cpp:1397 -msgid "any" +#: src/Options.cpp:56 +msgid "Fo1" msgstr "" -#: src/PolarGui.cpp:72 -msgid "Source:" +#: src/Options.cpp:57 +msgid "Fo2" msgstr "" -#: src/PolarGui.cpp:76 -msgid "Speedo" +#: src/Options.cpp:58 +msgid "Fo3" msgstr "" -#: src/PolarGui.cpp:76 -msgid "GPS" +#: src/Options.cpp:59 +msgid "Ji" msgstr "" -#: src/PolarGui.cpp:80 -msgid "" -"Speedo uses column STW\n" -"GPS uses column SOG" +#: src/Options.cpp:60 +msgid "Mi" msgstr "" -#: src/PolarGui.cpp:84 -msgid "Current <" +#: src/Options.cpp:61 +msgid "Mt" msgstr "" -#: src/PolarGui.cpp:98 -msgid "Filter" +#: src/Options.cpp:62 +msgid "St" msgstr "" -#: src/PolarGui.cpp:104 -msgid "Create" +#: src/Options.cpp:63 +msgid "Sp" msgstr "" -#: src/PolarGui.cpp:110 -msgid "Save" +#: src/Options.cpp:64 +msgid "?" msgstr "" -#: src/PolarGui.cpp:113 -msgid "Load" +#: src/Options.cpp:66 +msgid "Main" msgstr "" -#: src/PolarGui.cpp:212 -msgid "Clear Data" +#: src/Options.cpp:67 +msgid "Try" msgstr "" -#: src/PolarGui.cpp:215 -msgid "Record Start" +#: src/Options.cpp:68 +msgid "Genoa 1" msgstr "" -#: src/polar_pi.cpp:121 src/polar_pi.cpp:183 src/polar_pi.cpp:209 -#: src/polar_pi.cpp:231 src/polar_pi.cpp:260 -msgid "Polar" +#: src/Options.cpp:69 +msgid "Genoa 2" msgstr "" -#: src/polar_pi.cpp:189 -msgid "Polar PlugIn for OpenCPN" +#: src/Options.cpp:70 +msgid "Genoa 3" msgstr "" -#: src/polar_pi.cpp:195 -msgid "Polar PlugIn for OpenCPN\n" +#: src/Options.cpp:71 +msgid "Fock 1" msgstr "" -#: src/polar_pi.cpp:222 -msgid "Polar Preferences" +#: src/Options.cpp:72 +msgid "Fock 2" msgstr "" -#: src/polar_pi.cpp:235 -msgid "Show Polar icon" +#: src/Options.cpp:73 +msgid "Fock 3" msgstr "" -#: src/polar_pi.cpp:238 -msgid "Show metres/sec for Wind Speed" +#: src/Options.cpp:74 +msgid "Jib" msgstr "" -#: src/PolarDialog.cpp:38 -msgid "Start" +#: src/Options.cpp:75 +msgid "Mizzen" msgstr "" -#: src/PolarDialog.cpp:38 -msgid "Stop" +#: src/Options.cpp:76 +msgid "Mizzen Storm" msgstr "" -#: src/PolarDialog.cpp:40 -msgid "Record " +#: src/Options.cpp:77 +msgid "Staysail" msgstr "" -#: src/PolarDialog.cpp:167 +#: src/Options.cpp:78 +msgid "Spinnacker" +msgstr "" + +#: src/Options.cpp:79 msgid "" -"The plugin logbookkonni isn't installed\n" -"\n" -"It's needed to collect wind/speed-data from all available logbooks\n" -"\n" -"The create-button is hidden and the mode isn't useable" +"You can change the abbreviations and the names of the sails\n" +"in Options/Miscellaneous/Sails(Logbook)" +msgstr "" + +#: src/Options.cpp:143 +msgid "'" msgstr "" -#: src/Polar.h:190 +#: src/Options.cpp:144 +msgid "\"" +msgstr "" + +#: src/Options.cpp:146 +msgid "NM" +msgstr "" + +#: src/Options.cpp:147 src/Options.cpp:156 src/Polar.cpp:1475 +msgid "kts" +msgstr "" + +#: src/Options.cpp:149 +msgid "m" +msgstr "" + +#: src/Options.cpp:150 +msgid "ft" +msgstr "" + +#: src/Options.cpp:151 +msgid "fth" +msgstr "" + +#: src/Options.cpp:154 +msgid "mb" +msgstr "" + +#: src/Options.cpp:155 +msgid "F" +msgstr "" + +#: src/Options.cpp:157 +msgid "m/s" +msgstr "" + +#: src/Options.cpp:158 +msgid "km/h" +msgstr "" + +#: src/Options.cpp:161 +msgid "gal" +msgstr "" + +#: src/Options.cpp:162 +msgid "h" +msgstr "" + +#: src/Options.cpp:163 +msgid "E" +msgstr "" + +#: src/Options.cpp:168 +msgid "day(s)" +msgstr "" + +#: src/Options.cpp:169 +msgid "week(s)" +msgstr "" + +#: src/Options.cpp:170 +msgid "month" +msgstr "" + +#: src/Polar.h:188 msgid "Polar Filter" msgstr "" -#: src/Polar.cpp:63 +#: src/Polar.cpp:64 msgid "Max. only" msgstr "" -#: src/Polar.cpp:184 +#: src/Polar.cpp:185 msgid "Engine started / Recording is stopped" msgstr "" -#: src/Polar.cpp:201 +#: src/Polar.cpp:202 msgid "Select a VDR-File" msgstr "" -#: src/Polar.cpp:214 src/Polar.cpp:394 +#: src/Polar.cpp:215 src/Polar.cpp:392 msgid "Please wait." msgstr "" -#: src/Polar.cpp:316 +#: src/Polar.cpp:314 msgid "less than 3 entries found" msgstr "" -#: src/Polar.cpp:319 +#: src/Polar.cpp:317 msgid "less than 5 entries found" msgstr "" -#: src/Polar.cpp:322 +#: src/Polar.cpp:320 msgid "more than 10 entries found" msgstr "" -#: src/Polar.cpp:365 +#: src/Polar.cpp:363 msgid "Filtered by:" msgstr "" -#: src/Polar.cpp:401 +#: src/Polar.cpp:399 msgid "Collecting: " msgstr "" -#: src/Polar.cpp:818 +#: src/Polar.cpp:831 msgid "Save Polar File" msgstr "" -#: src/Polar.cpp:992 +#: src/Polar.cpp:1046 msgid "Select a Polar-File" msgstr "" -#: src/Polar.cpp:1217 +#: src/Polar.cpp:1320 msgid "Use Max-Speed only" msgstr "" -#: src/Polar.cpp:1224 +#: src/Polar.cpp:1327 msgid "Use Average from all speed-data" msgstr "" -#: src/Polar.cpp:1230 +#: src/Polar.cpp:1333 msgid "Range from maximum speed to minus" msgstr "" -#: src/Polar.cpp:1231 +#: src/Polar.cpp:1334 msgid "" "Example:\n" "Max-Speed = 2,5 kts\n" @@ -226,34 +292,146 @@ msgid "" "Range from 2,25 to 2,5 kts" msgstr "" -#: src/Polar.cpp:1248 +#: src/Polar.cpp:1351 msgid "Range" msgstr "" -#: src/Polar.cpp:1270 +#: src/Polar.cpp:1373 msgid "Sails" msgstr "" -#: src/Polar.cpp:1281 +#: src/Polar.cpp:1384 msgid "MyLabel" msgstr "" -#: src/Polar.cpp:1295 +#: src/Polar.cpp:1398 msgid "Wavehight" msgstr "" -#: src/Polar.cpp:1372 -msgid "kts" +#: src/Polar.cpp:1467 src/PolarGui.cpp:87 +msgid "Wind:" msgstr "" -#: src/Polar.cpp:1379 +#: src/Polar.cpp:1482 msgid "Wavehight from" msgstr "" -#: src/Polar.cpp:1392 +#: src/Polar.cpp:1487 src/Polar.cpp:1500 src/PolarGui.cpp:91 +#: src/PolarGui.cpp:118 +msgid "any" +msgstr "" + +#: src/Polar.cpp:1495 msgid "to" msgstr "" -#: src/Polar.cpp:1452 +#: src/Polar.cpp:1560 msgid "Collecting Data from: " msgstr "" + +#: src/PolarDialog.cpp:38 +msgid "Start" +msgstr "" + +#: src/PolarDialog.cpp:38 +msgid "Stop" +msgstr "" + +#: src/PolarDialog.cpp:40 +msgid "Record " +msgstr "" + +#: src/PolarDialog.cpp:167 +msgid "" +"The plugin logbookkonni isn't installed\n" +"\n" +"It's needed to collect wind/speed-data from all available logbooks\n" +"\n" +"The create-button is hidden and the mode isn't useable" +msgstr "" + +#: src/PolarGui.h:99 +msgid "Polar Diagram" +msgstr "" + +#: src/PolarGui.cpp:28 +msgid "Mode:" +msgstr "" + +#: src/PolarGui.cpp:32 +msgid "Data from Logbooks" +msgstr "" + +#: src/PolarGui.cpp:32 +msgid "Data from NMEA" +msgstr "" + +#: src/PolarGui.cpp:32 +msgid "Data from VDR" +msgstr "" + +#: src/PolarGui.cpp:32 +msgid "Edit manual" +msgstr "" + +#: src/PolarGui.cpp:38 +msgid "Filter" +msgstr "" + +#: src/PolarGui.cpp:44 +msgid "Create" +msgstr "" + +#: src/PolarGui.cpp:55 +msgid "Save" +msgstr "" + +#: src/PolarGui.cpp:58 +msgid "Load" +msgstr "" + +#: src/PolarGui.cpp:63 +msgid "Rings:" +msgstr "" + +#: src/PolarGui.cpp:71 +msgid "Set diagramm to x knots" +msgstr "" + +#: src/PolarGui.cpp:75 +msgid "Degrees:" +msgstr "" + +#: src/PolarGui.cpp:83 +msgid "Calculate speed-bullets for x degrees " +msgstr "" + +#: src/PolarGui.cpp:100 +msgid "Source:" +msgstr "" + +#: src/PolarGui.cpp:104 +msgid "Speedo" +msgstr "" + +#: src/PolarGui.cpp:104 +msgid "GPS" +msgstr "" + +#: src/PolarGui.cpp:108 +msgid "" +"Speedo uses column STW\n" +"GPS uses column SOG" +msgstr "" + +#: src/PolarGui.cpp:112 +msgid "Current <" +msgstr "" + +#: src/PolarGui.cpp:230 +msgid "Clear Data" +msgstr "" + +#: src/PolarGui.cpp:233 +msgid "Record Start" +msgstr "" diff --git a/src/Options.cpp b/src/Options.cpp index 167b705..12f577e 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -76,7 +76,7 @@ Options::Options(void) sailsName.Add(_("Mizzen Storm")); sailsName.Add(_("Staysail")); sailsName.Add(_("Spinnacker")); - sailsName.Add(_("You can change the abreviations and the names of the sails\nin Options/Miscellaneous/Sails")); + sailsName.Add(_("You can change the abbreviations and the names of the sails\nin Options/Miscellaneous/Sails(Logbook)")); rowGap = 0; colGap = 0; @@ -109,18 +109,18 @@ Options::Options(void) noGPS = true; colouredMaintenance = true; waypointArrived = false; - waypointText = _("automatic line Waypoint arrived"); - guardChange = false; - guardChangeText = _("automatic line\nchange of guards"); - courseChange = false; - courseChangeDegrees = _T("90"); - courseChangeText = _("automatic line\nchange of course >"); - courseTextAfterMinutes = _T("5"); - everySM = false; - everySMAmount = _T("10"); - everySMText = _("automatic line\nDistance > "); - dCourseChangeDegrees = -1; - dEverySM = -1; +// waypointText = _("automatic line Waypoint arrived"); +// guardChange = false; +// guardChangeText = _("automatic line\nchange of guards"); +// courseChange = false; +// courseChangeDegrees = _T("90"); +// courseChangeText = _("automatic line\nchange of course >"); +// courseTextAfterMinutes = _T("5"); +// everySM = false; +// everySMAmount = _T("10"); +// everySMText = _("automatic line\nDistance > "); +// dCourseChangeDegrees = -1; +// dEverySM = -1; // Timer timer = false; @@ -133,9 +133,9 @@ Options::Options(void) thour = _T("0"); tmin = _T("1");; tsec = _T("0");; - ttext = _("Automatic line by timer\n\n\ +/* ttext = _("Automatic line by timer\n\n\ You can set/unset a timer-interval\n\ -or change this text in Toolbox/Plugins/Logbook\n\nShift+Enter appends a new line"); +or change this text in Toolbox/Plugins/Logbook\n\nShift+Enter appends a new line"); */ timerSec = 5; // Grid Navigation diff --git a/src/Polar.cpp b/src/Polar.cpp index 8701b3c..4fe8c76 100644 --- a/src/Polar.cpp +++ b/src/Polar.cpp @@ -1,3 +1,4 @@ + #ifndef WX_PRECOMP #include #endif @@ -109,8 +110,7 @@ void Polar::setValue(wxString s, int dir, int spd) windsp[spd].count[dir] = 0; } - //if(mode != 2) - dlg->m_panelPolar->Refresh(); + dlg->m_panelPolar->Refresh(); } void Polar::setMode(int sel) @@ -129,7 +129,7 @@ void Polar::setMode(int sel) nmea = false; dlg->m_buttonFilterPolar->Enable(); dlg->m_choiceSourcePolar->Enable(); - source(sel); + source(dlg->m_choiceSourcePolar->GetSelection()); break; case 1: case 2: @@ -142,7 +142,7 @@ void Polar::setMode(int sel) dlg->m_button61->Disable(); dlg->m_buttonFilterPolar->Disable(); dlg->m_choiceSourcePolar->Enable(); - source(sel); + source(dlg->m_choiceSourcePolar->GetSelection()); if(sel == 2) loadVDR(); @@ -167,11 +167,12 @@ void Polar::setMode(int sel) dlg->m_buttonFilterPolar->Disable(); dlg->m_choiceSourcePolar->Disable(); dlg->m_toggleBtnRecord->Hide(); - source(sel); + source(dlg->m_choiceSourcePolar->GetSelection()); nmea = false; break; } - + + dlg->m_panel6->Layout(); dlg->m_panelPolar->Refresh(); } @@ -211,7 +212,7 @@ void Polar::loadVDR() wxFileInputStream input(fdlg.GetPath()); wxTextInputStream in(input); - wxProgressDialog progressRead( _("Please wait."), _T(""), + wxProgressDialog progressRead( _("Please wait."), _("Loading NMEA messages from file "), 100, dlg, wxFRAME_NO_TASKBAR | wxPD_AUTO_HIDE | wxPD_CAN_ABORT ); progressRead.Fit(); @@ -232,7 +233,6 @@ void Polar::loadVDR() }while(true); dlg->m_panelPolar->Refresh(); - dlg->m_toggleBtnRecord->Show(); } bool Polar::insert() @@ -256,12 +256,12 @@ bool Polar::insert() else if(windAngle > 0 && tdir > 180) windAngle += 180; - int row = wxRound((windAngle-24)/8); + int row = wxRound((windAngle-5)/5); int col = windSpeed/4; - if(row > 19) - row = 39 - row; + if(row > 35) + row = 71 - row; - if((row >= 0 && row < 20) && (col >= 0 && col < 10)) + if((row >= 0 && row < 36) && (col >= 0 && col < 10)) { if(!dlg->m_gridEdit->GetCellValue(row,col).IsEmpty()) { @@ -401,18 +401,18 @@ void Polar::createPolar() ::wxSafeYield(); - wxFileInputStream stream( files[i] ); // get trough the files + wxFileInputStream stream( files[i] ); // get trough the files wxTextInputStream in(stream); wxString wdirstr,wsp; double speed = -1; while(!stream.Eof()) { - wxString str = in.ReadLine(); // read line by line + wxString str = in.ReadLine(); // read line by line if(stream.Eof()) break; wxStringTokenizer tkz(str,_T("\t"),wxTOKEN_RET_EMPTY); // split into fields int o = 0; - int winddir = -1; int wsp = -1; + int wind_dir = -1; int wsp = -1; bool rel = false; nextline = false; @@ -424,13 +424,13 @@ void Polar::createPolar() case 7: // Sign "S" if(s.Trim() != _T("S")) { nextline = true; break; } // only at sea , no harbour,mooring etc., else read next line break; - case 14: // SOG // get speed over ground from GPS, if speed=0 get next line + case 14: // SOG // get speed over ground from GPS, if speed=0 get next line if(dlg->m_choiceSourcePolar->GetSelection() == 0) break; s.Replace(_T(","),_T(".")); speed = wxAtof(s); if(speed == 0.0) { nextline = true; break; } break; - case 15: // STW // get speed trough water from Speedo, if speed=0 get next line + case 15: // STW // get speed trough water from Speedo, if speed=0 get next line if(dlg->m_choiceSourcePolar->GetSelection() == 1) break; s.Replace(_T(","),_T(".")); speed = wxAtof(s); @@ -438,14 +438,14 @@ void Polar::createPolar() break; case 19: // WindDirection if(s.Trim().IsEmpty()) - { winddir = -1; nextline = true; break; } // if winddirection is empty, get next line + { wind_dir = -1; nextline = true; break; } // if winddirection is empty, get next line s.Replace(_T(","),_T(".")); - winddir = wxAtoi(s); + wind_dir = wxAtoi(s); if(s.Contains(_T("R"))) rel = true; break; - case 20: // WindSpeed // add Windspeed in struct p[winddirection] + case 20: // WindSpeed // add Windspeed in struct p[winddirection] { s.Replace(_T(","),_T(".")); double wspd = wxAtof(s); @@ -461,7 +461,7 @@ void Polar::createPolar() } //filter here break; - case 28: // Engine#1 Hours // Don't use when Engine is on + case 28: // Engine#1 Hours // Don't use when Engine is on if(!s.Trim().Contains(_T("00:00"))) { speed = 0; nextline = true; } break; @@ -505,32 +505,34 @@ void Polar::createPolar() if(nextline) { break; } // true = read next line o++; } - if(wsp >= 0 && !nextline) + + if(wsp >= 0 && !nextline) { if(rel) { - int tdir = winddir; - winddir = wxRound(atan(wsp*sin(winddir*PI/180)/(wsp*cos(winddir*PI/180)-speed))*180/PI); - if(winddir < 0 && tdir <= 180) - winddir += 180; - else if(winddir < 0 && tdir > 180) - winddir += 360; - else if(winddir > 0 && tdir > 180) - winddir += 180; + int tdir = wind_dir; + wind_dir = wxRound(atan(wsp*sin(wind_dir*PI/180)/(wsp*cos(wind_dir*PI/180)-speed))*180/PI); + if(wind_dir < 0 && tdir <= 180) + wind_dir += 180; + else if(wind_dir < 0 && tdir > 180) + wind_dir += 360; + else if(wind_dir > 0 && tdir > 180) + wind_dir += 180; rel = false; } wsp /= 4; - if(winddir < 180) - winddir = wxRound((winddir-24)/8); + if(wind_dir < 180) + wind_dir = wxRound((wind_dir-5)/5); else - winddir = 39-wxRound((winddir-24)/8); - // wxMessageBox(wxString::Format(_T("windspd:%i winddir:%i speed:%.2f size:%i"),wsp,winddir,speed,windsp[wsp].winddir.size())); - if(winddir >= 0) + wind_dir = 71-wxRound((wind_dir-5)/5); + // wxMessageBox(wxString::Format(_T("windspd:%i winddir:%i speed:%.2f size:%i"), wsp, wind_dir, speed, windsp[wsp].winddir.size())); + + if(wind_dir >= 0) { - windsp[wsp].winddir.insert(std::pair(winddir,speed)); - if(speed > windsp[wsp].wdirMax[winddir]) - windsp[wsp].wdirMax[winddir] = speed; + windsp[wsp].winddir.insert(std::pair(wind_dir,speed)); + if(speed > windsp[wsp].wdirMax[wind_dir]) + windsp[wsp].wdirMax[wind_dir] = speed; } } } @@ -547,17 +549,13 @@ void Polar::createPolar() int wdir = (*it).first; double spd = (*it).second; - if((wdir == n) ) + if(wdir == n) { double percent = ((spd-windsp[i].wdirMax[n])/windsp[i].wdirMax[n])*100; - // wxMessageBox(wxString::Format(_T("%.2f %.2f %.2f proz = %.2f"),spd,windsp[i].wdirMax[n],spd-windsp[i].wdirMax[n],percent)); if(percent >= -wxAtof(filterDlg->m_choice6->GetString(filterDlg->m_choice6->GetSelection()))) { windsp[i].count[n]++; windsp[i].wdirTotal[n] += spd; - /*wxMessageBox(wxString::Format(_T("%.2f %.2f %.2f proz = %.2f\n%i %.2f"),spd,windsp[i].wdirMax[n],windsp[i].wdirMax[n]-spd,((windsp[i].wdirMax[n]-spd)/spd)*100, - windsp[i].count[n],windsp[i].wdirTotal[n]));*/ - } } } @@ -576,19 +574,30 @@ void Polar::createPolar() int wdir = (*it).first; double spd = (*it).second; - if((wdir == n) ) + if(wdir == n) { windsp[i].count[n]++; windsp[i].wdirTotal[n] += spd; - /*wxMessageBox(wxString::Format(_T("%.2f %.2f %.2f proz = %.2f\n%i %.2f"),spd,windsp[i].wdirMax[n],windsp[i].wdirMax[n]-spd,((windsp[i].wdirMax[n]-spd)/spd)*100, - windsp[i].count[n],windsp[i].wdirTotal[n]));*/ - } } } } } + if(filterDlg->m_checkBoxMax->GetValue()) + { + for(int i = 0; i < 10; i++) + { + for(int n = 0; n < WINDDIR; n++) + { + if(windsp[i].wdirMax[n] > 0) + { + windsp[i].count[n]++; + windsp[i].wdirTotal[n] = windsp[i].wdirMax[n]; + } + } + } + } for(int i = 0; i < 10; i++) { @@ -597,8 +606,8 @@ void Polar::createPolar() if(windsp[i].count[n] > 0) { windsp[i].wdirTotal[n] /= windsp[i].count[n]; - dlg->m_gridEdit->SetCellValue(n,i,wxString::Format(_T("%.2f"),windsp[i].wdirTotal[n])); - } + dlg->m_gridEdit->SetCellValue(n,i,wxString::Format(_T("%.2f"),windsp[i].wdirTotal[n])); + } } } @@ -626,19 +635,19 @@ void Polar::createSpeedBullets() int linelength; wxColour colour,brush; - wxPen p = dc->GetPen(); // get actual Pen for restoring later - for(int wsp = sel; wsp < end; wsp++) // go thru all winddirection-structures depending on choiocebox degrees + wxPen p = dc->GetPen(); // get actual Pen for restoring later + for(int wsp = sel; wsp < end; wsp++) // go thru all winddirection-structures depending on choiocebox degrees { pc = 0; colour = windColor[wsp]; brush = windColor[wsp]; for(int dir = 0; dir < WINDDIR; dir++) { - if(windsp[wsp].count[dir] <= 0) continue; // no data ? continue + if(windsp[wsp].count[dir] <= 0) continue; // no data ? continue if(mode == 0) { if(windsp[wsp].count[dir] < 3) - //dc->SetBrush( wxBrush(wxColour(255,0,0)) ); // set bulletcolor for logbook-mode + //dc->SetBrush( wxBrush(wxColour(255,0,0)) ); // set bulletcolor for logbook-mode brush = wxColour(255,0,0); else if( windsp[wsp].count[dir] >= 3 && windsp[wsp].count[dir] < 5) //dc->SetBrush( wxBrush(wxColour(255,255,0)) ); @@ -656,7 +665,7 @@ void Polar::createSpeedBullets() if(filterDlg->m_checkBoxMax->GetValue()) linelength = windsp[wsp].wdirMax[dir]*length; else - linelength = windsp[wsp].wdirTotal[dir]*length; // calculate distance from centerpoint for speed + linelength = windsp[wsp].wdirTotal[dir]*length; // calculate distance from centerpoint for speed break; case 1: case 2: @@ -664,14 +673,14 @@ void Polar::createSpeedBullets() linelength = (windsp[wsp].wdirMax[dir])*length; break; } - xt = wxRound(cos(toRad(dir*8+24))*linelength+center.x); // calculate the point for the bullet - yt = wxRound(sin(toRad(dir*8+24))*linelength+center.y); + xt = wxRound(cos(toRad(dir*5+5))*linelength+center.x); // calculate the point for the bullet + yt = wxRound(sin(toRad(dir*5+5))*linelength+center.y); wxPoint pt(xt,yt); if(pt != wxPoint(center.x,center.y)) ptArr[pc++] = pt; } - if(pc > 2) //Draw splines, needs min. 3 points + if(pc > 2) //Draw splines, needs min. 3 points { dc->SetPen(wxPen(colour,3)); dc->DrawSpline(pc,ptArr); @@ -683,7 +692,7 @@ void Polar::createSpeedBullets() if(ptArr[i].x != 0 && ptArr[i].y != 0) { dc->SetPen(wxPen(wxColour(0,0,0),2)); - dc->DrawCircle(ptArr[i],radius); // draw the bullet + dc->DrawCircle(ptArr[i],radius); // draw the bullet ptArr[i].x = ptArr[i].y = 0; } else @@ -716,12 +725,12 @@ void Polar::createSpeedBulletsMax() int linelength; wxColour colour,brush; - wxPen p = dc->GetPen(); // get actual Pen for restoring later - for(int wsp = 0; wsp < end; wsp++) // go thru all winddirection-structures depending on choiocebox max. all + wxPen p = dc->GetPen(); // get actual Pen for restoring later + for(int wsp = 0; wsp < end; wsp++) // go thru all winddirection-structures depending on choiocebox max. all { for(int dir = 0; dir < WINDDIR; dir++) { - if(windsp[wsp].count[dir] <= 0) continue; // no data ? continue + if(windsp[wsp].count[dir] <= 0) continue; // no data ? continue if(wsp == 0) { temp[0].wdirMax[dir] = windsp[wsp].wdirMax[dir]; @@ -738,7 +747,7 @@ void Polar::createSpeedBulletsMax() - for(int wsp = 0; wsp < end; wsp++) // go thru all winddirection-structures depending on choiocebox degrees + for(int wsp = 0; wsp < end; wsp++) // go thru all winddirection-structures depending on choiocebox degrees { pc = 0; colour = windColor[wsp]; brush = windColor[wsp]; @@ -747,7 +756,7 @@ void Polar::createSpeedBulletsMax() switch(mode) { case 0: - linelength = temp[0].wdirTotal[dir]*length; // calculate distance from centerpoint for speed + linelength = temp[0].wdirTotal[dir]*length; // calculate distance from centerpoint for speed break; case 1: case 2: @@ -755,8 +764,8 @@ void Polar::createSpeedBulletsMax() linelength = (temp[0].wdirMax[dir])*length; break; } - xt = wxRound(cos(toRad(dir*8+24))*linelength+center.x); // calculate the point for the bullet - yt = wxRound(sin(toRad(dir*8+24))*linelength+center.y); + xt = wxRound(cos(toRad(dir*5+5))*linelength+center.x); // calculate the point for the bullet + yt = wxRound(sin(toRad(dir*5+5))*linelength+center.y); wxPoint pt(xt,yt); if(pt != wxPoint(center.x,center.y)) ptArr[pc++] = pt; @@ -764,7 +773,7 @@ void Polar::createSpeedBulletsMax() } colour = windColor[GREEN]; brush = windColor[GREEN]; - if(pc > 2) //Draw splines, needs min. 3 points + if(pc > 2) //Draw splines, needs min. 3 points { dc->SetPen(wxPen(colour,3)); dc->DrawSpline(pc,ptArr); @@ -777,7 +786,7 @@ void Polar::createSpeedBulletsMax() if(ptArr[i].x != 0 && ptArr[i].y != 0) { dc->SetPen(wxPen(wxColour(0,0,0),2)); - dc->DrawCircle(ptArr[i],radius); // draw the bullet + dc->DrawCircle(ptArr[i],radius); // draw the bullet ptArr[i].x = ptArr[i].y = 0; } else @@ -834,18 +843,18 @@ void Polar::save() { for(int dir = 0; dir < end; dir++) { - save[sp].wdirTotal[dir] += save[sp].wdirTotal[39-dir]; - save[sp].count[dir] += save[sp].count [39-dir]; - save[sp].wdirMax[dir] += save[sp].wdirMax [39-dir]; + save[sp].wdirTotal[dir] += save[sp].wdirTotal[71-dir]; + save[sp].count[dir] += save[sp].count [71-dir]; + save[sp].wdirMax[dir] += save[sp].wdirMax [71-dir]; - if(save[sp].count[dir] >= 2 && save[sp].count[39-dir] > 0) + if(save[sp].count[dir] >= 2 && save[sp].count[71-dir] > 0) save[sp].wdirTotal[dir] /= 2; - if(save[sp].wdirMax[dir] > 0 && save[sp].wdirMax[39-dir] > 0) + if(save[sp].wdirMax[dir] > 0 && save[sp].wdirMax[71-dir] > 0) save[sp].wdirMax[dir] /= 2; - save[sp].wdirTotal [39-dir] = 0; - save[sp].count[39-dir] = 0; + save[sp].wdirTotal [71-dir] = 0; + save[sp].count[71-dir] = 0; //if(save[sp].count[dir] > 0) //save[sp].count[dir] = 1; @@ -855,6 +864,7 @@ void Polar::save() wxFileOutputStream output( saveFile); wxTextOutputStream polarFile(output); +/* Original OCPN file format if(sel == 0) { for(int sp = 0; sp < 10; sp++) @@ -874,7 +884,7 @@ void Polar::save() data = save[sp].wdirMax[dir]; break; } - polarFile << (dir+3)*8 << _T(" "); + polarFile << (dir+1)*5 << _T(" "); if(save[sp].count[dir] > 0 && data >= 0.0) polarFile << wxString::Format(_T("%.2f "),data); else @@ -884,23 +894,26 @@ void Polar::save() polarFile << _T("\n"); } } - else if(sel == 1) + else if(sel == 1) */ // End of original OCPN file format + + if(sel == 0 || sel == 1) // Both OCPN and QTVlm are the same format { - polarFile << _T("TWA/TWS\t"); + polarFile << _T("TWA\\TWS;"); for(int i = 0 ; i < 11; i++) - polarFile << wxString::Format(_T("%i\t"),i*4); + polarFile << wxString::Format(_T("%i;"),i*4); polarFile << _T("60\n"); for(int dir = -1; dir < end; dir++) { if(dir == -1) - { - for(int z = 0; z < 13; z++) - polarFile << _T("0\t"); - polarFile << _T("\n"); + { + polarFile << _T("0;"); + for(int z = 0; z < 11; z++) + polarFile << _T("0.00;"); + polarFile << _T("0\n"); continue; } - polarFile << 24+(dir*8) << _T("\t"); + polarFile << 5+(dir*5) << _T(";"); for(int sp = 0; sp < 10; sp++) { data = -1; @@ -916,11 +929,11 @@ void Polar::save() break; } if(sp == 0) - polarFile << _T("0\t"); + polarFile << _T("0.00;"); if(save[sp].count[dir] > 0 && data >= 0.0) - polarFile << wxString::Format(_T("%.2f\t"),data); + polarFile << wxString::Format(_T("%.2f;"),data); else - polarFile << _T("\t"); + polarFile << _T("0.00;"); } polarFile << _T("0\n"); @@ -928,14 +941,22 @@ void Polar::save() } else if(sel == 2) { - polarFile << _T("TWA\t"); + polarFile << _T("TWA\\TWS,"); for(int i = 0 ; i < 11; i++) - polarFile << wxString::Format(_T("%i\t"),i*4); + polarFile << wxString::Format(_T("%i,"),i*4); polarFile << _T("\n"); - for(int dir = 0; dir < end; dir++) + for(int dir = -1; dir < end; dir++) { - polarFile << 24+(dir*8) << _T("\t"); + if(dir == -1) + { + polarFile << _T("0,"); + for(int z = 0; z < 11; z++) + polarFile << _T("0.0,"); + polarFile << _T("0\n"); + continue; + } + polarFile << 5+(dir*5) << _T(","); for(int sp = 0; sp < 10; sp++) { data = -1; @@ -951,11 +972,11 @@ void Polar::save() break; } if(sp == 0) - polarFile << _T("0\t"); + polarFile << _T("0,"); if(save[sp].count[dir] > 0 && data >= 0.0) - polarFile << wxString::Format(_T("%.2f\t"),data); + polarFile << wxString::Format(_T("%.1f,"),data); else - polarFile << _T("\t"); + polarFile << _T(","); } polarFile << _T("\n"); @@ -963,7 +984,7 @@ void Polar::save() } else { - wxString s = _T(","); + wxString s = _T("TWA\\TWS,"); for(int col = 0; col < dlg->m_gridEdit->GetCols(); col++) s << dlg->m_gridEdit->GetColLabelValue(col)+_T(","); s.RemoveLast(); @@ -995,9 +1016,12 @@ void Polar::showDlg() void Polar::source(int sel) { if(mode == 0 && sel == 1) - { - dlg->m_staticText141->Show(); - dlg->m_choiceCurrentPolar->Show(); + { +// At this moment the current info is not used so do not show current button. +// dlg->m_staticText141->Show(); +// dlg->m_choiceCurrentPolar->Show(); + dlg->m_staticText141->Hide(); + dlg->m_choiceCurrentPolar->Hide(); } else { @@ -1025,25 +1049,60 @@ void Polar::loadPolar() wxString wdirstr,wsp; bool first = true; - int mode = -1, row = -1; + int mode = -1, row = -1, sep = -1; int ocpnCol = 0; while(!stream.Eof()) { - wxString str = in.ReadLine(); // read line by line + wxString str = in.ReadLine(); // read line by line if(stream.Eof()) break; if(first) { - if(str.Contains(_T("TWA/TWS"))) - mode = 1; + if(str.Contains(_T("TWA\\TWS"))) + { + mode = 1; + if(str.GetChar(7) == ';') + sep = 1; + else if(str.GetChar(7) == ',') + sep = 2; + else if(str.GetChar(7) == '\t') + sep = 3; + else if(str.GetChar(7) == ' ') + sep = 0; + } else if (str.Contains(_T("TWA"))) + { mode = 2; - else if(str.GetChar(0) == '4') + if(str.GetChar(3) == ';') + sep = 1; + else if(str.GetChar(3) == ',') + sep = 2; + else if(str.GetChar(3) == '\t') + sep = 3; + else if(str.GetChar(3) == ' ') + sep = 0; + } + else if(str.GetChar(0) == '4') + { mode = 0; + if(str.GetChar(1) == ';') + sep = 1; + else if(str.GetChar(1) == ',') + sep = 2; + else if(str.GetChar(1) == '\t') + sep = 3; + else if(str.GetChar(1) == ' ') + sep = 0; + } else { wxMessageBox(_T("Cannot load this file")); return; } + if( sep == -1) + { + wxMessageBox(_T("Format in this file not recognised")); + return; + } first = false; if( mode != 0) @@ -1051,7 +1110,7 @@ void Polar::loadPolar() } wxStringTokenizer tkz; - switch(mode) + switch(sep) { case 0: { @@ -1060,7 +1119,18 @@ void Polar::loadPolar() } break; case 1: + { + wxStringTokenizer tk(str,_T(";"),wxTOKEN_RET_EMPTY); + tkz = tk; + } + break; case 2: + { + wxStringTokenizer tk(str,_T(","),wxTOKEN_RET_EMPTY); + tkz = tk; + } + break; + case 3: { wxStringTokenizer tk(str,_T("\t"),wxTOKEN_RET_EMPTY); tkz = tk; @@ -1069,7 +1139,7 @@ void Polar::loadPolar() } wxString u = tkz.GetNextToken(); - if(u == _T("0") && mode == 1) + if(u == _T("0") && (mode == 1 || mode == 2)) { row++; continue; } else if(row == -1) row++; @@ -1077,16 +1147,19 @@ void Polar::loadPolar() if(mode == 1 || mode == 2) { - int col = 0, i = 0; + int col = 0, i = 0, x = 0; wxString s; + x = wxAtoi(u); + row = (x + 2) / 5 - 1; + while(tkz.HasMoreTokens()) { i++; if(i > 11) break; - s = tkz.GetNextToken(); - if(s == _T("0") && (mode == 1 || mode == 2)) continue; + s = tkz.GetNextToken(); + if(s == _T("0") || s == _T("0.00") || s == _T("0.0")) continue; dlg->m_gridEdit->SetCellValue(row,col,s); - setValue(s,row,col++); + setValue(s,row,col++); } } else @@ -1138,11 +1211,11 @@ void Polar::setSentence(wxString sentence) windAngle = m_NMEA0183.Mwv.WindAngle; windReference = m_NMEA0183.Mwv.Reference; - if(m_NMEA0183.Mwv.WindSpeedUnits == 'N') + if(m_NMEA0183.Mwv.WindSpeedUnits == 'K') windSpeed = wxRound(m_NMEA0183.Mwv.WindSpeed/1.852); else if(m_NMEA0183.Mwv.WindSpeedUnits == 'M') windSpeed = wxRound((m_NMEA0183.Mwv.WindSpeed*3600)/1852); - else if(m_NMEA0183.Mwv.WindSpeedUnits == 'K') + else if(m_NMEA0183.Mwv.WindSpeedUnits == 'N') windSpeed = m_NMEA0183.Mwv.WindSpeed; } @@ -1153,13 +1226,17 @@ void Polar::setSentence(wxString sentence) { windAngle = m_NMEA0183.Vwr.WindDirectionMagnitude; windReference = _T("R"); + windSpeed = m_NMEA0183.Vwr.WindSpeedKnots; + } - //if(m_NMEA0183.Vwr..WindSpeedUnits == 'N') - windSpeed = m_NMEA0183.Vwr.WindSpeedKnots; - //else if(m_NMEA0183.Mwv.WindSpeedUnits == 'M') - windSpeed = m_NMEA0183.Vwr.WindSpeedms; - //else if(m_NMEA0183.Mwv.WindSpeedUnits == 'K') - windSpeed = m_NMEA0183.Vwr.WindSpeedKnots; + } + else if(m_NMEA0183.LastSentenceIDReceived == _T("VWT")) + { + if(m_NMEA0183.Parse()) + { + windAngle = m_NMEA0183.Vwt.WindDirectionMagnitude; + windReference = _T("T"); + windSpeed = m_NMEA0183.Vwt.WindSpeedKnots; } } @@ -1451,7 +1528,12 @@ void FilterDlg::OnOKButtonClick( wxCommandEvent& event ) polar->filterSails = true; } - this->Hide(); + this->Hide(); + EndModal(wxID_OK); +#ifdef __WXOSX__ + if( GetParent() ) + GetParent()->Raise(); +#endif } ///////////////////////////// Collect Dialog /////////////////////////////////// diff --git a/src/Polar.h b/src/Polar.h index d44cd9b..d861aa3 100644 --- a/src/Polar.h +++ b/src/Polar.h @@ -8,17 +8,17 @@ #include #include -#include "nmea0183.h" +#include "nmea0183/nmea0183.h" WX_DEFINE_ARRAY_DOUBLE(int, ArrayOfDouble); -#define WINDDIR 40 +#define WINDDIR 72 class PolarDialog; class polar_pi; class FilterDlg; class Options; -//class NMEA0183; +//class NMEA0183P; class Polar { @@ -95,11 +95,10 @@ class Polar PolarDialog* dlg; FilterDlg* filterDlg; - NMEA0183 m_NMEA0183; + NMEA0183P m_NMEA0183; wxString logbookDataPath; wxSize center; - int radius; int rSpeed[24]; double dist; @@ -148,7 +147,6 @@ class FilterDlg : public wxDialog wxStaticText* m_staticTextUnitHeight; wxFlexGridSizer* fgSizer50; wxPanel* m_panel33; - wxButton* m_buttonSailsReset; wxStaticText* m_staticTextKnot; PolarDialog* dlg; @@ -187,7 +185,7 @@ class FilterDlg : public wxDialog void init(); - FilterDlg( PolarDialog* parent, Polar* polar,wxWindowID id = wxID_ANY, const wxString& title = _("Polar Filter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 451,470 ), long style = wxDEFAULT_DIALOG_STYLE ); + FilterDlg( PolarDialog* parent, Polar* polar,wxWindowID id = wxID_ANY, const wxString& title = _("Polar Filter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 451,600 ), long style = wxDEFAULT_DIALOG_STYLE ); ~FilterDlg(); }; diff --git a/src/PolarGui.cpp b/src/PolarGui.cpp index 048cc25..37bcb2c 100644 --- a/src/PolarGui.cpp +++ b/src/PolarGui.cpp @@ -11,8 +11,8 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); +// this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetSizeHints( wxSize(-1,-1), wxDefaultSize ); wxBoxSizer* bSizer1; bSizer1 = new wxBoxSizer( wxVERTICAL ); @@ -22,19 +22,47 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons bSizerPolar = new wxBoxSizer( wxHORIZONTAL ); + wxBoxSizer* bSizer14; + bSizer14 = new wxBoxSizer( wxHORIZONTAL ); + m_staticText11 = new wxStaticText( this, wxID_ANY, _("Mode:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText11->Wrap( -1 ); bSizerPolar->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - wxString m_choiceModeChoices[] = { _("Data from Logbooks"), _("Data from NMEA"), _("Data from VDR"), _("Edit manuell") }; + wxString m_choiceModeChoices[] = { _("Data from Logbooks"), _("Data from NMEA"), _("Data from VDR"), _("Edit manual") }; int m_choiceModeNChoices = sizeof( m_choiceModeChoices ) / sizeof( wxString ); m_choiceMode = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceModeNChoices, m_choiceModeChoices, 0 ); m_choiceMode->SetSelection( 0 ); bSizerPolar->Add( m_choiceMode, 0, wxALL, 5 ); + m_buttonFilterPolar = new wxButton( this, wxID_ANY, _("Filter"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPolar->Add( m_buttonFilterPolar, 0, wxALL, 5 ); + + m_staticline421 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerPolar->Add( m_staticline421, 0, wxEXPAND | wxALL, 5 ); + + m_button61 = new wxButton( this, wxID_ANY, _("Create"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPolar->Add( m_button61, 0, wxALL, 5 ); + + m_staticline431 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerPolar->Add( m_staticline431, 0, wxEXPAND | wxALL, 5 ); + + bSizerPolar->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticline432 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizerPolar->Add( m_staticline432, 0, wxEXPAND | wxALL, 5 ); + + m_buttonSavePolar = new wxButton( this, wxID_ANY, _("Save"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPolar->Add( m_buttonSavePolar, 0, wxALIGN_RIGHT|wxALL, 5 ); + + m_buttonLoad = new wxButton( this, wxID_ANY, _("Load"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerPolar->Add( m_buttonLoad, 0, wxALIGN_RIGHT|wxALL, 5 ); + + bSizer48->Add( bSizerPolar, 0, 0, 5 ); + m_staticText144 = new wxStaticText( this, wxID_ANY, _("Rings:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText144->Wrap( -1 ); - bSizerPolar->Add( m_staticText144, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer14->Add( m_staticText144, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); wxString m_choiceRingsPolarChoices[] = { _T("6"), _T("9"), _T("12"), _T("18"), _T("24") }; int m_choiceRingsPolarNChoices = sizeof( m_choiceRingsPolarChoices ) / sizeof( wxString ); @@ -42,36 +70,36 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons m_choiceRingsPolar->SetSelection( 0 ); m_choiceRingsPolar->SetToolTip( _("Set diagramm to x knots") ); - bSizerPolar->Add( m_choiceRingsPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer14->Add( m_choiceRingsPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); m_staticText145 = new wxStaticText( this, wxID_ANY, _("Degrees:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText145->Wrap( -1 ); - bSizerPolar->Add( m_staticText145, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer14->Add( m_staticText145, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); wxString m_choiceDegreesPolarChoices[] = { _T("8"), _T("10"), _T("15") }; int m_choiceDegreesPolarNChoices = sizeof( m_choiceDegreesPolarChoices ) / sizeof( wxString ); m_choiceDegreesPolar = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceDegreesPolarNChoices, m_choiceDegreesPolarChoices, 0 ); - m_choiceDegreesPolar->SetSelection( 0 ); + m_choiceDegreesPolar->SetSelection( 1 ); m_choiceDegreesPolar->SetToolTip( _("Calculate speed-bullets for x degrees ") ); - bSizerPolar->Add( m_choiceDegreesPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer14->Add( m_choiceDegreesPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); m_staticText148 = new wxStaticText( this, wxID_ANY, _("Wind:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText148->Wrap( -1 ); - bSizerPolar->Add( m_staticText148, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer14->Add( m_staticText148, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); wxString m_choiceWindPolarChoices[] = { _("any") }; int m_choiceWindPolarNChoices = sizeof( m_choiceWindPolarChoices ) / sizeof( wxString ); m_choiceWindPolar = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceWindPolarNChoices, m_choiceWindPolarChoices, 0 ); m_choiceWindPolar->SetSelection( 0 ); - bSizerPolar->Add( m_choiceWindPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer14->Add( m_choiceWindPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); m_staticline441 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerPolar->Add( m_staticline441, 0, wxEXPAND | wxALL, 5 ); + bSizer14->Add( m_staticline441, 0, wxEXPAND | wxALL, 5 ); m_staticText146 = new wxStaticText( this, wxID_ANY, _("Source:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText146->Wrap( -1 ); - bSizerPolar->Add( m_staticText146, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer14->Add( m_staticText146, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); wxString m_choiceSourcePolarChoices[] = { _("Speedo"), _("GPS") }; int m_choiceSourcePolarNChoices = sizeof( m_choiceSourcePolarChoices ) / sizeof( wxString ); @@ -79,13 +107,13 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons m_choiceSourcePolar->SetSelection( 0 ); m_choiceSourcePolar->SetToolTip( _("Speedo uses column STW\nGPS uses column SOG") ); - bSizerPolar->Add( m_choiceSourcePolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); + bSizer14->Add( m_choiceSourcePolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); m_staticText141 = new wxStaticText( this, wxID_ANY, _("Current <"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText141->Wrap( -1 ); m_staticText141->Hide(); - bSizerPolar->Add( m_staticText141, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizer14->Add( m_staticText141, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); wxString m_choiceCurrentPolarChoices[] = { _("any"), _T("0.5"), _T("1.0") }; int m_choiceCurrentPolarNChoices = sizeof( m_choiceCurrentPolarChoices ) / sizeof( wxString ); @@ -93,28 +121,9 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons m_choiceCurrentPolar->SetSelection( 0 ); m_choiceCurrentPolar->Hide(); - bSizerPolar->Add( m_choiceCurrentPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - m_buttonFilterPolar = new wxButton( this, wxID_ANY, _("Filter"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerPolar->Add( m_buttonFilterPolar, 0, wxALL, 5 ); - - m_staticline421 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerPolar->Add( m_staticline421, 0, wxEXPAND | wxALL, 5 ); - - m_button61 = new wxButton( this, wxID_ANY, _("Create"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerPolar->Add( m_button61, 0, wxALL, 5 ); - - m_staticline431 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerPolar->Add( m_staticline431, 0, wxEXPAND | wxALL, 5 ); - - m_buttonSavePolar = new wxButton( this, wxID_ANY, _("Save"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerPolar->Add( m_buttonSavePolar, 0, wxALL, 5 ); - - m_buttonLoad = new wxButton( this, wxID_ANY, _("Load"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerPolar->Add( m_buttonLoad, 0, wxALL, 5 ); - + bSizer14->Add( m_choiceCurrentPolar, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); - bSizer48->Add( bSizerPolar, 0, 0, 5 ); + bSizer48->Add( bSizer14, 0, 0, 5 ); m_staticline45 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); bSizer48->Add( m_staticline45, 0, wxEXPAND | wxALL, 0 ); @@ -136,7 +145,7 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons m_gridEdit = new wxGrid( m_panel6, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); // Grid - m_gridEdit->CreateGrid( 20, 10 ); + m_gridEdit->CreateGrid( 36, 10 ); m_gridEdit->EnableEditing( true ); m_gridEdit->EnableGridLines( true ); m_gridEdit->EnableDragGridSize( false ); @@ -171,41 +180,50 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons // Rows m_gridEdit->EnableDragRowSize( true ); m_gridEdit->SetRowLabelSize( 50 ); - m_gridEdit->SetRowLabelValue( 0, _T("24\xB0") ); - m_gridEdit->SetRowLabelValue( 1, _T("32\xB0") ); - m_gridEdit->SetRowLabelValue( 2, _T("40\xB0") ); - m_gridEdit->SetRowLabelValue( 3, _T("48\xB0") ); - m_gridEdit->SetRowLabelValue( 4, _T("56\xB0") ); - m_gridEdit->SetRowLabelValue( 5, _T("64\xB0") ); - m_gridEdit->SetRowLabelValue( 6, _T("72\xB0") ); - m_gridEdit->SetRowLabelValue( 7, _T("80\xB0") ); - m_gridEdit->SetRowLabelValue( 8, _T("88\xB0") ); - m_gridEdit->SetRowLabelValue( 9, _T("96\xB0") ); - m_gridEdit->SetRowLabelValue( 10, _T("104\xB0") ); - m_gridEdit->SetRowLabelValue( 11, _T("112\xB0") ); - m_gridEdit->SetRowLabelValue( 12, _T("120\xB0") ); - m_gridEdit->SetRowLabelValue( 13, _T("128\xB0") ); - m_gridEdit->SetRowLabelValue( 14, _T("136\xB0") ); - m_gridEdit->SetRowLabelValue( 15, _T("144\xB0") ); - m_gridEdit->SetRowLabelValue( 16, _T("152\xB0") ); - m_gridEdit->SetRowLabelValue( 17, _T("160\xB0") ); - m_gridEdit->SetRowLabelValue( 18, _T("168\xB0") ); - m_gridEdit->SetRowLabelValue( 19, _T("176\xB0") ); + m_gridEdit->SetRowLabelValue( 0, _T("5\xB0") ); + m_gridEdit->SetRowLabelValue( 1, _T("10\xB0") ); + m_gridEdit->SetRowLabelValue( 2, _T("15\xB0") ); + m_gridEdit->SetRowLabelValue( 3, _T("20\xB0") ); + m_gridEdit->SetRowLabelValue( 4, _T("25\xB0") ); + m_gridEdit->SetRowLabelValue( 5, _T("30\xB0") ); + m_gridEdit->SetRowLabelValue( 6, _T("35\xB0") ); + m_gridEdit->SetRowLabelValue( 7, _T("40\xB0") ); + m_gridEdit->SetRowLabelValue( 8, _T("45\xB0") ); + m_gridEdit->SetRowLabelValue( 9, _T("50\xB0") ); + m_gridEdit->SetRowLabelValue( 10, _T("55\xB0") ); + m_gridEdit->SetRowLabelValue( 11, _T("60\xB0") ); + m_gridEdit->SetRowLabelValue( 12, _T("65\xB0") ); + m_gridEdit->SetRowLabelValue( 13, _T("70\xB0") ); + m_gridEdit->SetRowLabelValue( 14, _T("75\xB0") ); + m_gridEdit->SetRowLabelValue( 15, _T("80\xB0") ); + m_gridEdit->SetRowLabelValue( 16, _T("85\xB0") ); + m_gridEdit->SetRowLabelValue( 17, _T("90\xB0") ); + m_gridEdit->SetRowLabelValue( 18, _T("95\xB0") ); + m_gridEdit->SetRowLabelValue( 19, _T("100\xB0") ); + m_gridEdit->SetRowLabelValue( 20, _T("105\xB0") ); + m_gridEdit->SetRowLabelValue( 21, _T("110\xB0") ); + m_gridEdit->SetRowLabelValue( 22, _T("115\xB0") ); + m_gridEdit->SetRowLabelValue( 23, _T("120\xB0") ); + m_gridEdit->SetRowLabelValue( 24, _T("125\xB0") ); + m_gridEdit->SetRowLabelValue( 25, _T("130\xB0") ); + m_gridEdit->SetRowLabelValue( 26, _T("135\xB0") ); + m_gridEdit->SetRowLabelValue( 27, _T("140\xB0") ); + m_gridEdit->SetRowLabelValue( 28, _T("145\xB0") ); + m_gridEdit->SetRowLabelValue( 29, _T("150\xB0") ); + m_gridEdit->SetRowLabelValue( 30, _T("155\xB0") ); + m_gridEdit->SetRowLabelValue( 31, _T("160\xB0") ); + m_gridEdit->SetRowLabelValue( 32, _T("165\xB0") ); + m_gridEdit->SetRowLabelValue( 33, _T("170\xB0") ); + m_gridEdit->SetRowLabelValue( 34, _T("175\xB0") ); + m_gridEdit->SetRowLabelValue( 35, _T("180\xB0") ); m_gridEdit->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); // Label Appearance // Cell Defaults m_gridEdit->SetDefaultCellAlignment( wxALIGN_RIGHT, wxALIGN_CENTRE ); - bSizer13->Add( m_gridEdit, 0, wxALL|wxEXPAND, 0 ); - - m_staticTextEngine = new wxStaticText( m_panel6, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextEngine->Wrap( -1 ); - bSizer13->Add( m_staticTextEngine, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer13->Add( 0, 0, 1, wxEXPAND, 5 ); - + bSizer13->Add( m_gridEdit, 1, wxALL|wxEXPAND, 5 ); + wxBoxSizer* bSizer12; bSizer12 = new wxBoxSizer( wxHORIZONTAL ); @@ -232,12 +250,11 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons this->SetSizer( bSizer1 ); this->Layout(); - this->Centre( wxBOTH ); this->Centre( wxBOTH ); // Connect Events - this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( PolarDlg::PolarDlgOnInitDialog ) );this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( PolarDlg::PolarDlgOnInitDialog ) ); - this->Connect( wxEVT_SIZE, wxSizeEventHandler( PolarDlg::OnSizePolarDlg ) );this->Connect( wxEVT_SIZE, wxSizeEventHandler( PolarDlg::OnSizePolarDlg ) ); + this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( PolarDlg::PolarDlgOnInitDialog ) ); + this->Connect( wxEVT_SIZE, wxSizeEventHandler( PolarDlg::OnSizePolarDlg ) ); m_choiceMode->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PolarDlg::OnChoiceMode ), NULL, this ); m_choiceRingsPolar->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PolarDlg::OnChoicePolarKnots ), NULL, this ); m_choiceDegreesPolar->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PolarDlg::OnChoiceDegreesPolar ), NULL, this ); @@ -258,8 +275,8 @@ PolarDlg::PolarDlg( wxWindow* parent, wxWindowID id, const wxString& title, cons PolarDlg::~PolarDlg() { // Disconnect Events - this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( PolarDlg::PolarDlgOnInitDialog ) );this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( PolarDlg::PolarDlgOnInitDialog ) ); - this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PolarDlg::OnSizePolarDlg ) );this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PolarDlg::OnSizePolarDlg ) ); + this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( PolarDlg::PolarDlgOnInitDialog ) ); + this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PolarDlg::OnSizePolarDlg ) ); m_choiceMode->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PolarDlg::OnChoiceMode ), NULL, this ); m_choiceRingsPolar->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PolarDlg::OnChoicePolarKnots ), NULL, this ); m_choiceDegreesPolar->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( PolarDlg::OnChoiceDegreesPolar ), NULL, this ); @@ -372,7 +389,7 @@ FilterDlg::FilterDlg( wxWindow* parent, wxWindowID id, const wxString& title, co m_panel33 = new wxPanel( m_notebook6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); bSizer54 = new wxBoxSizer( wxVERTICAL ); - m_staticText152 = new wxStaticText( m_panel33, wxID_ANY, _("Work in irogress"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText152 = new wxStaticText( m_panel33, wxID_ANY, _("Work in progress"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText152->Wrap( -1 ); bSizer54->Add( m_staticText152, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); @@ -447,4 +464,4 @@ FilterDlg::~FilterDlg() m_sdbSizer11OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlg::OnOKButtonClick ), NULL, this ); } -*/ \ No newline at end of file +*/ diff --git a/src/PolarGui.h b/src/PolarGui.h index a664f7c..ec7936f 100644 --- a/src/PolarGui.h +++ b/src/PolarGui.h @@ -89,13 +89,14 @@ class PolarDlg : public wxDialog wxBoxSizer* bSizerPolar; wxChoice* m_choiceMode; wxStaticLine* m_staticline431; + wxStaticLine* m_staticline432; wxSplitterWindow* m_splitter1; wxPanel* m_panelPolar; wxPanel* m_panel6; wxGrid* m_gridEdit; wxStaticText* m_staticTextEngine; - PolarDlg( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Polar Diagram"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 968,602 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER ); + PolarDlg( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Polar Diagram"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 1024,602 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER ); ~PolarDlg(); void m_splitter1OnIdle( wxIdleEvent& ) diff --git a/src/wxJSON/json_defs.h b/src/json_defs.h similarity index 92% rename from src/wxJSON/json_defs.h rename to src/json_defs.h index 0fc9848..136fb6e 100644 --- a/src/wxJSON/json_defs.h +++ b/src/json_defs.h @@ -43,26 +43,16 @@ // variable: // WXDLLIMPEXP_DATA_MYCOMP(int) myGlobalIntVar; // -#ifdef WXMAKINGDLL_JSON - #define WXDLLIMPEXP_JSON WXEXPORT - #define WXDLLIMPEXP_DATA_JSON(type) WXEXPORT type -#elif defined(WXUSINGDLL) - #define WXDLLIMPEXP_JSON WXIMPORT - #define WXDLLIMPEXP_DATA_JSON(type) WXIMPORT type -#else // not making nor using DLL +//#ifdef WXMAKINGDLL_JSON +// #define WXDLLIMPEXP_JSON WXEXPORT +// #define WXDLLIMPEXP_DATA_JSON(type) WXEXPORT type +//#elif defined(WXUSINGDLL) +// #define WXDLLIMPEXP_JSON WXIMPORT +// #define WXDLLIMPEXP_DATA_JSON(type) WXIMPORT type +//#else // not making nor using DLL #define WXDLLIMPEXP_JSON #define WXDLLIMPEXP_DATA_JSON(type) type -#endif - -//dsr -#undef WXDLLIMPEXP_JSON -#undef WXDLLIMPEXP_DATA_JSON - - #define WXDLLIMPEXP_JSON - #define WXDLLIMPEXP_DATA_JSON(type) type - -//dsr - +//#endif // the __PRETTY_FUNCTION__ macro expands to the full class's // member name in the GNU GCC. diff --git a/src/wxJSON/jsonreader.cpp b/src/jsonreader.cpp similarity index 99% rename from src/wxJSON/jsonreader.cpp rename to src/jsonreader.cpp index 25704f6..4da408c 100644 --- a/src/wxJSON/jsonreader.cpp +++ b/src/jsonreader.cpp @@ -7,12 +7,12 @@ // Copyright: (c) 2007 Luciano Cattani // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// - +#ifndef __WXOSX__ #ifdef __GNUG__ #pragma implementation "jsonreader.cpp" #endif - -#include +#endif +#include "jsonreader.h" #include #include @@ -1849,11 +1849,11 @@ wxJSONReader::ConvertCharByChar( wxString& s, const wxMemoryBuffer& utf8Buffer ) @return the last char read or -1 in case of EOF */ -union byte_union -{ - unsigned char cu[2]; - short int bu; -}; +//union byte +//{ +// unsigned char c[2]; +// short int b; +//}; int wxJSONReader::ReadMemoryBuff( wxInputStream& is, wxJSONValue& val ) @@ -1880,29 +1880,29 @@ wxJSONReader::ReadMemoryBuff( wxInputStream& is, wxJSONValue& val ) break; } unsigned char c2 = (unsigned char) ch; - c1 -= '0'; - c2 -= '0'; - if ( c1 > 9 ) { - c1 -= 7; - } - if ( c2 > 9 ) { - c2 -= 7; + c1 -= '0'; + c2 -= '0'; + if ( c1 > 9 ) { + c1 -= 7; + } + if ( c2 > 9 ) { + c2 -= 7; } - if ( c1 > 15 ) { - ++errors; + if ( c1 > 15 ) { + ++errors; } - else if ( c2 > 15 ) { - ++errors; + else if ( c2 > 15 ) { + ++errors; } else { byte = (c1 * 16) + c2; buff.AppendByte( byte ); } } // end while - + if ( errors > 0 ) { wxString err; - err.Printf( membuffError, errors ); + err.Printf( membuffError, errors ); AddError( err ); } diff --git a/src/wxJSON/jsonreader.h b/src/jsonreader.h similarity index 99% rename from src/wxJSON/jsonreader.h rename to src/jsonreader.h index dd10b8c..ea9a6b6 100644 --- a/src/wxJSON/jsonreader.h +++ b/src/jsonreader.h @@ -10,11 +10,11 @@ #if !defined( _WX_JSONREADER_H ) #define _WX_JSONREADER_H - +#ifndef __WXOSX__ #ifdef __GNUG__ #pragma interface "jsonreader.h" #endif - +#endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" diff --git a/src/wxJSON/jsonval.cpp b/src/jsonval.cpp similarity index 96% rename from src/wxJSON/jsonval.cpp rename to src/jsonval.cpp index 98a8739..397b249 100644 --- a/src/wxJSON/jsonval.cpp +++ b/src/jsonval.cpp @@ -7,11 +7,11 @@ // Copyright: (c) 2007 Luciano Cattani // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// - +#ifndef __WXOSX__ #ifdef __GNUG__ #pragma implementation "jsonval.cpp" #endif - +#endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -24,7 +24,7 @@ #include #include -#include +#include "jsonval.h" WX_DEFINE_OBJARRAY( wxJSONInternalArray ); @@ -66,7 +66,7 @@ wxJSONRefData::wxJSONRefData() { m_lineNo = -1; m_refCount = 1; - m_memBuff = 0; + m_memBuff = 0; #if defined( WXJSON_USE_VALUE_COUNTER ) m_progr = sm_progr; @@ -78,9 +78,9 @@ wxJSONRefData::wxJSONRefData() // Dtor wxJSONRefData::~wxJSONRefData() -{ - if ( m_memBuff ) { - delete m_memBuff; +{ + if ( m_memBuff ) { + delete m_memBuff; } } @@ -146,14 +146,14 @@ The following is an example: wxJSONvalue aString( "this is a static string" ); aString = 10; \endcode - To know more about this topic see \ref json_internals_cstring. - - Starting from version 1.3 the class can hold binary memory buffers - as an extension to the JSON syntax. Memory buffers are stored as - \b wxMemoryBuffer objects which contain binary data. The class - uses reference counting for the copy and assignment operation but - it is not a \e copy-on-write structure. - To know more about memory buffers read \ref wxjson_tutorial_memorybuff + To know more about this topic see \ref json_internals_cstring. + + Starting from version 1.3 the class can hold binary memory buffers + as an extension to the JSON syntax. Memory buffers are stored as + \b wxMemoryBuffer objects which contain binary data. The class + uses reference counting for the copy and assignment operation but + it is not a \e copy-on-write structure. + To know more about memory buffers read \ref wxjson_tutorial_memorybuff \sa the \ref wxjson_tutorial. */ @@ -358,39 +358,39 @@ wxJSONValue::wxJSONValue( unsigned long int ul ) } } -//! Construct a JSON value object of type \e memory \e buffer -/*! - Note that this ctor makes a deep copy of \c buff so changes made - to the original buffer does not reflect to the buffer stored in this - JSON value. +//! Construct a JSON value object of type \e memory \e buffer +/*! + Note that this ctor makes a deep copy of \c buff so changes made + to the original buffer does not reflect to the buffer stored in this + JSON value. */ wxJSONValue::wxJSONValue( const wxMemoryBuffer& buff ) { m_refData = 0; wxJSONRefData* data = Init( wxJSONTYPE_MEMORYBUFF ); wxJSON_ASSERT( data ); - if ( data != 0 ) { - data->m_memBuff = new wxMemoryBuffer(); - const void* ptr = buff.GetData(); - size_t buffLen = buff.GetDataLen(); + if ( data != 0 ) { + data->m_memBuff = new wxMemoryBuffer(); + const void* ptr = buff.GetData(); + size_t buffLen = buff.GetDataLen(); if ( buffLen > 0 ) { - data->m_memBuff->AppendData( ptr, buffLen ); + data->m_memBuff->AppendData( ptr, buffLen ); } } } -//! Construct a JSON value object of type \e memory \e buffer -/*! - Note that this ctor makes a deep copy of \c buff so changes made - to the original buffer does not reflect to the buffer stored in this - JSON value. +//! Construct a JSON value object of type \e memory \e buffer +/*! + Note that this ctor makes a deep copy of \c buff so changes made + to the original buffer does not reflect to the buffer stored in this + JSON value. */ wxJSONValue::wxJSONValue( const void* buff, size_t len ) { m_refData = 0; wxJSONRefData* data = Init( wxJSONTYPE_MEMORYBUFF ); wxJSON_ASSERT( data ); - if ( data != 0 && len > 0 ) { + if ( data != 0 && len > 0 ) { data->m_memBuff = new wxMemoryBuffer(); data->m_memBuff->AppendData( buff, len ); } @@ -929,10 +929,10 @@ wxJSONValue::AsDouble() const \li if the value is a NULL value the \b null literal string is returned. \li if the value is of type wxJSONTYPE_INVALID, the literal string \b <invalid> - is returned. Note that this is NOT a valid JSON text. - - \li if the value is of type wxJSONTYPE_MEMORYBUFF the string returned contains the - hexadecimal digits of the first 5 bytes preceeded by the length of the buffer, + is returned. Note that this is NOT a valid JSON text. + + \li if the value is of type wxJSONTYPE_MEMORYBUFF the string returned contains the + hexadecimal digits of the first 5 bytes preceeded by the length of the buffer, enclosed in parenthesis If the value is an array or map, the returned string is the number of @@ -960,7 +960,7 @@ wxJSONValue::AsString() const case wxJSONTYPE_CSTRING : s.assign( data->m_value.m_valCString); break; - case wxJSONTYPE_INT : + /* case wxJSONTYPE_INT : #if defined( wxJSON_64BIT_INT ) s.Printf( _T("%") wxLongLongFmtSpec _T("i"), data->m_value.m_valInt64 ); @@ -975,7 +975,7 @@ wxJSONValue::AsString() const #else s.Printf( _T("%lu"), data->m_value.m_valULong ); #endif - break; + break;*/ case wxJSONTYPE_DOUBLE : s.Printf( _T("%.10g"), data->m_value.m_valDouble ); break; @@ -1286,9 +1286,9 @@ wxJSONValue::AsDouble( double& d ) const a string also when this object does not contain a string. In that case, a string representation of this value is returned. This function, instead, returns TRUE only if this object contains a string, that is - only if \c IsString() returns TRUE. - Also note that the string value is only stored in \c str if this object actually - contains a \b string or \b c-string value. + only if \c IsString() returns TRUE. + Also note that the string value is only stored in \c str if this object actually + contains a \b string or \b c-string value. \c str will never contain a string representation of other types. */ bool @@ -1318,8 +1318,8 @@ wxJSONValue::AsCString( wxChar* ch ) const Note that as of wxWidgets 2.8 and 2.9 the \b wxMemoryBuffer object uses reference counting when copying the actual buffer but the class itself is not a \e copy-on-write structure so changes made to one buffer affects - all other copies made from it. - This means that if you make a change to the returned copy of the memory + all other copies made from it. + This means that if you make a change to the returned copy of the memory buffer, the change affects also the memory buffer stored in this JSON value. If this JSON object does not contain a \e wxJSONTYPE_MEMORYBUFF type @@ -1335,9 +1335,9 @@ wxJSONValue::AsMemoryBuff() const { wxJSONRefData* data = GetRefData(); wxJSON_ASSERT( data ); - wxMemoryBuffer buff; - if ( data->m_memBuff ) { - buff = *(data->m_memBuff); + wxMemoryBuffer buff; + if ( data->m_memBuff ) { + buff = *(data->m_memBuff); } wxJSON_ASSERT( IsMemoryBuff()); @@ -1352,8 +1352,8 @@ wxJSONValue::AsMemoryBuff() const Note that as of wxWidgets 2.8 and 2.9 the \b wxMemoryBuffer object uses reference counting when copying the actual buffer but the class itself is not a \e copy-on-write structure so changes made to one buffer affects - all other copies made from it. - This means that if you make a change to the returned copy of the memory + all other copies made from it. + This means that if you make a change to the returned copy of the memory buffer, the change affects also the memory buffer stored in this JSON value. If this JSON object does not contain a \e wxJSONTYPE_MEMORYBUFF type @@ -1671,7 +1671,7 @@ wxJSONValue::Cat( const wxString& str ) } return r; } - + //! Concatenate a memory buffer to this memory buffer object. /*! The function concatenates \c buff to the \b wxMemoryBuffer object contained @@ -1679,8 +1679,8 @@ wxJSONValue::Cat( const wxString& str ) If the value stored in this value is not a memory buffer object the function does nothing and returns FALSE. */ -bool -wxJSONValue::Cat( const wxMemoryBuffer& buff ) +bool +wxJSONValue::Cat( const wxMemoryBuffer& buff ) { wxJSONRefData* data = GetRefData(); wxJSON_ASSERT( data ); @@ -1694,7 +1694,7 @@ wxJSONValue::Cat( const wxMemoryBuffer& buff ) } return r; } - + //! \overload Cat( const wxString& ) bool @@ -1815,8 +1815,11 @@ wxJSONValue& wxJSONValue::Item( const wxString& key ) { wxLogTrace( traceMask, _T("(%s) searched key=\'%s\'"), __PRETTY_FUNCTION__, key.c_str()); +#ifdef __WXOSX__ +// wxLogTrace( traceMask, _T("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); +#else wxLogTrace( traceMask, _T("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); - +#endif wxJSONRefData* data = COW(); wxJSON_ASSERT( data ); @@ -1864,8 +1867,11 @@ wxJSONValue wxJSONValue::ItemAt( const wxString& key ) const { wxLogTrace( traceMask, _T("(%s) searched key=\'%s\'"), __PRETTY_FUNCTION__, key.c_str()); +#ifdef __WXOSX__ +// wxLogTrace( traceMask, _T("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); +#else wxLogTrace( traceMask, _T("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); - +#endif wxJSONRefData* data = GetRefData(); wxJSON_ASSERT( data ); @@ -2033,20 +2039,20 @@ wxJSONValue::operator = ( const wxString& str ) } -//! Assigns to this object a memory buffer type -/*! - As with the ctor, this function makes a deep copy of the - memory buffer \c buff so changes made to the original buffer - does not reflect to the memory buffer stored in this JSON value. +//! Assigns to this object a memory buffer type +/*! + As with the ctor, this function makes a deep copy of the + memory buffer \c buff so changes made to the original buffer + does not reflect to the memory buffer stored in this JSON value. */ wxJSONValue& wxJSONValue::operator = ( const wxMemoryBuffer& buff ) { - wxJSONRefData* data = SetType( wxJSONTYPE_MEMORYBUFF ); - data->m_memBuff = new wxMemoryBuffer(); - const void* ptr = buff.GetData(); - size_t len = buff.GetDataLen(); - if ( data->m_memBuff && len ) { + wxJSONRefData* data = SetType( wxJSONTYPE_MEMORYBUFF ); + data->m_memBuff = new wxMemoryBuffer(); + const void* ptr = buff.GetData(); + size_t len = buff.GetDataLen(); + if ( data->m_memBuff && len ) { data->m_memBuff->AppendData( ptr, len ); } return *this; @@ -2847,12 +2853,12 @@ wxJSONValue::SetType( wxJSONType type ) case wxJSONTYPE_OBJECT: data->m_valMap.clear(); break; - case wxJSONTYPE_MEMORYBUFF: - // we first have to delete the actual memory buffer, if any - if ( data->m_memBuff ) { - delete data->m_memBuff; - data->m_memBuff = 0; - } + case wxJSONTYPE_MEMORYBUFF: + // we first have to delete the actual memory buffer, if any + if ( data->m_memBuff ) { + delete data->m_memBuff; + data->m_memBuff = 0; + } break; default : // there is not need to clear primitive types @@ -3003,18 +3009,18 @@ wxJSONValue::CloneRefData( const wxJSONRefData* otherData ) const data->m_lineNo = other->m_lineNo; data->m_valString = other->m_valString; data->m_valArray = other->m_valArray; - data->m_valMap = other->m_valMap; - - // if the data contains a wxMemoryBuffer object, then we have - // to make a deep copy of the buffer by allocating a new one because - // wxMemoryBuffer is not a copy-on-write structure - if ( other->m_memBuff ) { - data->m_memBuff = new wxMemoryBuffer(); - const void* ptr = data->m_memBuff->GetData(); - size_t len = data->m_memBuff->GetDataLen(); - if ( data->m_memBuff && len ) { - data->m_memBuff->AppendData( ptr, len ); - } + data->m_valMap = other->m_valMap; + + // if the data contains a wxMemoryBuffer object, then we have + // to make a deep copy of the buffer by allocating a new one because + // wxMemoryBuffer is not a copy-on-write structure + if ( other->m_memBuff ) { + data->m_memBuff = new wxMemoryBuffer(); + const void* ptr = data->m_memBuff->GetData(); + size_t len = data->m_memBuff->GetDataLen(); + if ( data->m_memBuff && len ) { + data->m_memBuff->AppendData( ptr, len ); + } } wxLogTrace( cowTraceMask, _T("(%s) CloneRefData() PROGR: other=%d data=%d"), @@ -3089,8 +3095,8 @@ wxJSONValue::AllocExclusive() in the memory buffer; bytes are separated by a space character. The string starts with the actual lenght of the data enclosed in parenthesis. The string will contain \c len bytes if \c len is less than the length - of the actual data in \c buff. - Note that the (len) printed in the output referes to the length of the buffer + of the actual data in \c buff. + Note that the (len) printed in the output referes to the length of the buffer which may be greater than the length that has to be printed. \b Example: @@ -3115,29 +3121,29 @@ wxJSONValue::MemoryBuffToString( const wxMemoryBuffer& buff, size_t len ) binary memory buffer pointed to by \c buff for \c len bytes. The string is composed of two hexadecimal digits for every byte contained in the memory buffer; bytes are separated by a space character. - The string starts with pointer to binary data followed by the lenght of the + The string starts with pointer to binary data followed by the lenght of the data enclosed in parenthesis. \b Example: This is an example of printing ten bytes from a memory buffer: \code 0x80974653 (10) 00 01 02 03 04 05 06 07 08 09 - \endcode - - @param buff the pointer to the memory buffer data - @len the length of the data that has to be printed - @actualLen the real lenght of the memory buffer that has to be printed - just afetr the pointer; may be greater than \c len. If this parameter + \endcode + + @param buff the pointer to the memory buffer data + @len the length of the data that has to be printed + @actualLen the real lenght of the memory buffer that has to be printed + just afetr the pointer; may be greater than \c len. If this parameter is -1 then it is equal to \c len */ wxString wxJSONValue::MemoryBuffToString( const void* buff, size_t len, size_t actualLen ) { - wxString s; - size_t buffLen = actualLen; - if (buffLen == (size_t) -1 ) { - buffLen = len; - } + wxString s; + size_t buffLen = actualLen; + if (buffLen == (size_t) -1 ) { + buffLen = len; + } s.Printf( _T("%p (%u) "), buff, buffLen ); unsigned char* ptr = (unsigned char*) buff; for ( unsigned int i = 0; i < len; i++ ) { @@ -3257,7 +3263,7 @@ wxJSONValue::ArrayToMemoryBuff( const wxJSONValue& value ) if ( value.IsArray() ) { int len = value.Size(); for ( int i = 0; i < len; i++ ) { - short int byte; unsigned char c; + short int byte; unsigned char c; // we do not use opertaor [] because it is not const // bool r = value[i].AsShort( byte ); bool r = value.ItemAt(i).AsShort( byte ); diff --git a/src/wxJSON/jsonval.h b/src/jsonval.h similarity index 99% rename from src/wxJSON/jsonval.h rename to src/jsonval.h index e57f10e..4395630 100644 --- a/src/wxJSON/jsonval.h +++ b/src/jsonval.h @@ -10,11 +10,11 @@ #if !defined( _WX_JSONVAL_H ) #define _WX_JSONVAL_H - +#ifndef __WXOSX__ #ifdef __GNUG__ #pragma interface "jsonval.h" #endif - +#endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" diff --git a/src/wxJSON/jsonwriter.cpp b/src/jsonwriter.cpp similarity index 96% rename from src/wxJSON/jsonwriter.cpp rename to src/jsonwriter.cpp index 8073974..c14ea2d 100644 --- a/src/wxJSON/jsonwriter.cpp +++ b/src/jsonwriter.cpp @@ -7,13 +7,13 @@ // Copyright: (c) 2007 Luciano Cattani // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// - +#ifndef __WXOSX__ #ifdef __GNUG__ #pragma implementation "jsonwriter.cpp" #endif +#endif - -#include +#include "jsonwriter.h" #include #include @@ -428,7 +428,7 @@ wxJSONWriter::DoWrite( wxOutputStream& os, const wxJSONValue& value, const wxStr case wxJSONTYPE_CSTRING : lastChar = WriteStringValue( os, value.AsString()); break; - + case wxJSONTYPE_MEMORYBUFF : lastChar = WriteMemoryBuff( os, value.AsMemoryBuff()); break; @@ -931,7 +931,7 @@ wxJSONWriter::WriteIntValue( wxOutputStream& os, const wxJSONValue& value ) const char* cbData = cb.data(); len = strlen( cbData ); wxASSERT( len < 32 ); - memcpy( buffer, cbData, len ); + memcpy( buffer, cbData, len ); buffer[len] = 0; #endif #else @@ -1186,7 +1186,7 @@ wxJSONWriter::WriteMemoryBuff( wxOutputStream& os, const wxMemoryBuffer& buff ) } if (( bytesWritten >= MAX_BYTES_PER_ROW ) && ((buffLen - i ) >= 5 )) { - // split the string if we wrote 20 bytes, but only is we have to + // split the string if we wrote 20 bytes, but only is we have to // write at least 5 bytes os.Write( "\'\n", 2 ); int lastChar = WriteIndent( os, m_level + 2 ); // write indentation diff --git a/src/wxJSON/jsonwriter.h b/src/jsonwriter.h similarity index 96% rename from src/wxJSON/jsonwriter.h rename to src/jsonwriter.h index d17e949..af7a1ab 100644 --- a/src/wxJSON/jsonwriter.h +++ b/src/jsonwriter.h @@ -10,11 +10,11 @@ #if !defined( _WX_JSONWRITER_H ) #define _WX_JSONWRITER_H - +#ifndef __WXOSX__ #ifdef __GNUG__ #pragma interface "jsonwriter.h" #endif - +#endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" diff --git a/src/nmea0183/RMB.hpp b/src/nmea0183/RMB.hpp index 2e650e9..6691461 100644 --- a/src/nmea0183/RMB.hpp +++ b/src/nmea0183/RMB.hpp @@ -53,7 +53,7 @@ class RMB : public RESPONSE ** Data */ - NMEA0183_BOOLEAN IsDataValid; + NMEA0183P_BOOLEAN IsDataValid; double CrossTrackError; LEFTRIGHT DirectionToSteer; wxString To; @@ -62,7 +62,7 @@ class RMB : public RESPONSE double RangeToDestinationNauticalMiles; double BearingToDestinationDegreesTrue; double DestinationClosingVelocityKnots; - NMEA0183_BOOLEAN IsArrivalCircleEntered; + NMEA0183P_BOOLEAN IsArrivalCircleEntered; /* ** Methods diff --git a/src/nmea0183/RMC.HPP b/src/nmea0183/RMC.HPP index 668d6b1..34e9cd5 100644 --- a/src/nmea0183/RMC.HPP +++ b/src/nmea0183/RMC.HPP @@ -53,7 +53,7 @@ class RMC : public RESPONSE */ wxString UTCTime; - NMEA0183_BOOLEAN IsDataValid; + NMEA0183P_BOOLEAN IsDataValid; LATLONG Position; double SpeedOverGroundKnots; double TrackMadeGoodDegreesTrue; diff --git a/src/nmea0183/Response.hpp b/src/nmea0183/Response.hpp index 1dfb8a6..8dadaa3 100644 --- a/src/nmea0183/Response.hpp +++ b/src/nmea0183/Response.hpp @@ -41,14 +41,14 @@ ** You can use it any way you like. */ -class NMEA0183; +class NMEA0183P; class RESPONSE { private: - NMEA0183 *container_p; + NMEA0183P *container_p; public: @@ -71,7 +71,7 @@ class RESPONSE virtual bool Parse( const SENTENCE& sentence ) = 0; virtual const wxString& PlainEnglish( void ); virtual void SetErrorMessage( const wxString& ); - virtual void SetContainer( NMEA0183 *container ); + virtual void SetContainer( NMEA0183P *container ); virtual bool Write( SENTENCE& sentence ); }; diff --git a/src/nmea0183/Sentence.hpp b/src/nmea0183/Sentence.hpp index b44e276..2ce3ab0 100644 --- a/src/nmea0183/Sentence.hpp +++ b/src/nmea0183/Sentence.hpp @@ -62,7 +62,7 @@ class SENTENCE ** Methods */ - virtual NMEA0183_BOOLEAN Boolean( int field_number ) const; + virtual NMEA0183P_BOOLEAN Boolean( int field_number ) const; virtual unsigned char ComputeChecksum( void ) const; virtual COMMUNICATIONS_MODE CommunicationsMode( int field_number ) const; virtual double Double( int field_number ) const; @@ -71,7 +71,7 @@ class SENTENCE virtual void Finish( void ); virtual int GetNumberOfDataFields( void ) const; virtual int Integer( int field_number ) const; - virtual NMEA0183_BOOLEAN IsChecksumBad( int checksum_field_number ) const; + virtual NMEA0183P_BOOLEAN IsChecksumBad( int checksum_field_number ) const; virtual LEFTRIGHT LeftOrRight( int field_number ) const; virtual NORTHSOUTH NorthOrSouth( int field_number ) const; virtual REFERENCE Reference( int field_number ) const; @@ -91,7 +91,7 @@ class SENTENCE virtual const SENTENCE& operator += ( int value ); virtual const SENTENCE& operator += ( EASTWEST easting ); virtual const SENTENCE& operator += ( TRANSDUCER_TYPE transducer ); - virtual const SENTENCE& operator += ( NMEA0183_BOOLEAN boolean ); + virtual const SENTENCE& operator += ( NMEA0183P_BOOLEAN boolean ); virtual const SENTENCE& operator += ( LATLONG& source ); }; diff --git a/src/nmea0183/gll.cpp b/src/nmea0183/gll.cpp index f779953..c63ff72 100644 --- a/src/nmea0183/gll.cpp +++ b/src/nmea0183/gll.cpp @@ -88,7 +88,7 @@ bool GLL::Parse( const SENTENCE& sentence ) int target_field_count = 6; - NMEA0183_BOOLEAN check = sentence.IsChecksumBad( 7 ); + NMEA0183P_BOOLEAN check = sentence.IsChecksumBad( 7 ); if ( check == NTrue ) { diff --git a/src/nmea0183/gll.hpp b/src/nmea0183/gll.hpp index 6e1c6f9..d8963f4 100644 --- a/src/nmea0183/gll.hpp +++ b/src/nmea0183/gll.hpp @@ -54,7 +54,7 @@ class GLL : public RESPONSE */ wxString UTCTime; - NMEA0183_BOOLEAN IsDataValid; + NMEA0183P_BOOLEAN IsDataValid; LATLONG Position; /* diff --git a/src/nmea0183/mwv.hpp b/src/nmea0183/mwv.hpp index 160bb42..df77736 100644 --- a/src/nmea0183/mwv.hpp +++ b/src/nmea0183/mwv.hpp @@ -57,7 +57,7 @@ class MWV : public RESPONSE wxString Reference; double WindSpeed; wxString WindSpeedUnits; - NMEA0183_BOOLEAN IsDataValid; + NMEA0183P_BOOLEAN IsDataValid; /* ** Methods diff --git a/src/nmea0183/nmea0183.cpp b/src/nmea0183/nmea0183.cpp index 97069dd..446ce44 100644 --- a/src/nmea0183/nmea0183.cpp +++ b/src/nmea0183/nmea0183.cpp @@ -44,7 +44,7 @@ WX_DEFINE_LIST(MRL); -NMEA0183::NMEA0183() +NMEA0183P::NMEA0183P() { initialize(); @@ -136,19 +136,19 @@ NMEA0183::NMEA0183() set_container_pointers(); } -NMEA0183::~NMEA0183() +NMEA0183P::~NMEA0183P() { initialize(); } -void NMEA0183::initialize( void ) +void NMEA0183P::initialize( void ) { // ASSERT_VALID( this ); ErrorMessage.Empty(); } -void NMEA0183::set_container_pointers( void ) +void NMEA0183P::set_container_pointers( void ) { // ASSERT_VALID( this ); @@ -169,7 +169,7 @@ void NMEA0183::set_container_pointers( void ) } } -void NMEA0183::sort_response_table( void ) +void NMEA0183P::sort_response_table( void ) { // ASSERT_VALID( this ); @@ -211,7 +211,7 @@ void NMEA0183::sort_response_table( void ) ** Public Interface */ -bool NMEA0183::IsGood( void ) const +bool NMEA0183P::IsGood( void ) const { // ASSERT_VALID( this ); @@ -242,7 +242,7 @@ bool NMEA0183::IsGood( void ) const } -bool NMEA0183::PreParse( void ) +bool NMEA0183P::PreParse( void ) { if ( IsGood() ) { @@ -268,7 +268,7 @@ bool NMEA0183::PreParse( void ) } -bool NMEA0183::Parse( void ) +bool NMEA0183P::Parse( void ) { bool return_value = FALSE; @@ -350,7 +350,7 @@ bool NMEA0183::Parse( void ) return( return_value ); } -NMEA0183& NMEA0183::operator << ( wxString & source ) +NMEA0183P& NMEA0183P::operator << ( wxString & source ) { // ASSERT_VALID( this ); @@ -359,7 +359,7 @@ NMEA0183& NMEA0183::operator << ( wxString & source ) return( *this ); } -NMEA0183& NMEA0183::operator >> ( wxString& destination ) +NMEA0183P& NMEA0183P::operator >> ( wxString& destination ) { // ASSERT_VALID( this ); diff --git a/src/nmea0183/nmea0183.h b/src/nmea0183/nmea0183.h index e27a026..b61777d 100644 --- a/src/nmea0183/nmea0183.h +++ b/src/nmea0183/nmea0183.h @@ -63,12 +63,12 @@ #define LINE_FEED wxString(wxChar(0x0A)) -typedef enum _NMEA0183_BOOLEAN +typedef enum _NMEA0183P_BOOLEAN { Unknown0183 = 0, NTrue, NFalse -} NMEA0183_BOOLEAN; +} NMEA0183P_BOOLEAN; typedef enum _leftright { @@ -150,4 +150,4 @@ wxString& talker_id( const wxString& sentence ); #include "nmea0183.hpp" -#endif // NMEA0183_HEADER +#endif // NMEA0183P_HEADER diff --git a/src/nmea0183/nmea0183.hpp b/src/nmea0183/nmea0183.hpp index 72f22de..9a073c3 100644 --- a/src/nmea0183/nmea0183.hpp +++ b/src/nmea0183/nmea0183.hpp @@ -106,6 +106,7 @@ #include "mwv.hpp" #include "vhw.hpp" #include "vwr.hpp" +#include "vwt.hpp" #include "zda.hpp" /* #include "ROT.hpp" @@ -133,7 +134,7 @@ WX_DECLARE_LIST(RESPONSE, MRL); -class NMEA0183 +class NMEA0183P { private: @@ -151,8 +152,8 @@ class NMEA0183 public: - NMEA0183(); - virtual ~NMEA0183(); + NMEA0183P(); + virtual ~NMEA0183P(); /* ** NMEA 0183 Sentences we understand @@ -227,6 +228,7 @@ class NMEA0183 */ VTG Vtg; VWR Vwr; + VWT Vwt; /* WCV Wcv; WNC Wnc; @@ -255,8 +257,8 @@ class NMEA0183 virtual bool Parse( void ); virtual bool PreParse( void ); - NMEA0183& operator << ( wxString& source ); - NMEA0183& operator >> ( wxString& destination ); + NMEA0183P& operator << ( wxString& source ); + NMEA0183P& operator >> ( wxString& destination ); }; #endif // NMEA_0183_CLASS_HEADER diff --git a/src/nmea0183/response.cpp b/src/nmea0183/response.cpp index 0b1e428..d886cd1 100644 --- a/src/nmea0183/response.cpp +++ b/src/nmea0183/response.cpp @@ -54,7 +54,7 @@ RESPONSE::~RESPONSE() ErrorMessage.Empty(); } -void RESPONSE::SetContainer( NMEA0183 *container ) +void RESPONSE::SetContainer( NMEA0183P *container ) { container_p = container; } diff --git a/src/nmea0183/rmb.cpp b/src/nmea0183/rmb.cpp index 087b523..97addf2 100644 --- a/src/nmea0183/rmb.cpp +++ b/src/nmea0183/rmb.cpp @@ -99,7 +99,7 @@ bool RMB::Parse( const SENTENCE& sentence ) ** First we check the checksum... */ - NMEA0183_BOOLEAN check = sentence.IsChecksumBad( 14 ); + NMEA0183P_BOOLEAN check = sentence.IsChecksumBad( 14 ); if ( check == NTrue ) { @@ -155,7 +155,7 @@ bool RMB::Write( SENTENCE& sentence ) sentence.Finish(); -// NMEA0183_BOOLEAN check = sentence.IsChecksumBad( 14 ); +// NMEA0183P_BOOLEAN check = sentence.IsChecksumBad( 14 ); return( TRUE ); } diff --git a/src/nmea0183/rmc.cpp b/src/nmea0183/rmc.cpp index 9bf7efd..5ff1141 100644 --- a/src/nmea0183/rmc.cpp +++ b/src/nmea0183/rmc.cpp @@ -104,7 +104,7 @@ bool RMC::Parse( const SENTENCE& sentence ) ** First we check the checksum... */ - NMEA0183_BOOLEAN check = sentence.IsChecksumBad( 12 ); + NMEA0183P_BOOLEAN check = sentence.IsChecksumBad( 12 ); if ( check == NTrue ) { diff --git a/src/nmea0183/rsa.hpp b/src/nmea0183/rsa.hpp index 315b48a..0b78d84 100644 --- a/src/nmea0183/rsa.hpp +++ b/src/nmea0183/rsa.hpp @@ -55,9 +55,9 @@ class RSA : public RESPONSE */ double Starboard; - NMEA0183_BOOLEAN IsStarboardDataValid; + NMEA0183P_BOOLEAN IsStarboardDataValid; double Port; - NMEA0183_BOOLEAN IsPortDataValid; + NMEA0183P_BOOLEAN IsPortDataValid; /* ** Methods diff --git a/src/nmea0183/sentence.cpp b/src/nmea0183/sentence.cpp index 85e7a1b..9ec918b 100644 --- a/src/nmea0183/sentence.cpp +++ b/src/nmea0183/sentence.cpp @@ -51,7 +51,7 @@ SENTENCE::~SENTENCE() Sentence.Empty(); } -NMEA0183_BOOLEAN SENTENCE::Boolean( int field_number ) const +NMEA0183P_BOOLEAN SENTENCE::Boolean( int field_number ) const { // ASSERT_VALID( this ); @@ -266,7 +266,7 @@ int SENTENCE::Integer( int field_number ) const return( ::atoi( Field( field_number ).mb_str() ) ); } -NMEA0183_BOOLEAN SENTENCE::IsChecksumBad( int checksum_field_number ) const +NMEA0183P_BOOLEAN SENTENCE::IsChecksumBad( int checksum_field_number ) const { // ASSERT_VALID( this ); @@ -658,7 +658,7 @@ const SENTENCE& SENTENCE::operator += ( EASTWEST easting ) return( *this ); } -const SENTENCE& SENTENCE::operator += ( NMEA0183_BOOLEAN boolean ) +const SENTENCE& SENTENCE::operator += ( NMEA0183P_BOOLEAN boolean ) { // ASSERT_VALID( this ); diff --git a/src/nmea0183/vtg.cpp b/src/nmea0183/vtg.cpp index fe05b06..8da57fb 100644 --- a/src/nmea0183/vtg.cpp +++ b/src/nmea0183/vtg.cpp @@ -94,7 +94,7 @@ bool VTG::Parse( const SENTENCE& sentence ) int target_field_count = 8; - NMEA0183_BOOLEAN check = sentence.IsChecksumBad( 9 ); + NMEA0183P_BOOLEAN check = sentence.IsChecksumBad( 9 ); if ( check == NTrue ) { diff --git a/src/nmea0183/vwt.cpp b/src/nmea0183/vwt.cpp new file mode 100644 index 0000000..8a3581c --- /dev/null +++ b/src/nmea0183/vwt.cpp @@ -0,0 +1,139 @@ +/*************************************************************************** + * + * Project: OpenCPN + * Purpose: NMEA0183 Support Classes + * Author: Samuel R. Blackburn, David S. Register, Jean-Eudes Onfray + * + *************************************************************************** + * Copyright (C) 2010 by Samuel R. Blackburn, David S Register * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + *************************************************************************** + * + * S Blackburn's original source license: * + * "You can use it any way you like." * + * More recent (2010) license statement: * + * "It is BSD license, do with it what you will" * + */ + +#include "nmea0183.h" + +/* +** Author: Samuel R. Blackburn +** CI$: 76300,326 +** Internet: sammy@sed.csc.com +** +** You can use it any way you like. +*/ + +//IMPLEMENT_DYNAMIC( MWV, RESPONSE ) + +VWT::VWT() +{ + Mnemonic = _T("VWT"); + Empty(); +} + +VWT::~VWT() +{ + Mnemonic.Empty(); + Empty(); +} + +void VWT::Empty( void ) +{ +// ASSERT_VALID( this ); + + WindDirectionMagnitude = 0.0; + DirectionOfWind = LR_Unknown; + WindSpeedKnots = 0.0; + WindSpeedms = 0.0; + WindSpeedKmh = 0.0; +} + +bool VWT::Parse( const SENTENCE& sentence ) +{ +// ASSERT_VALID( this ); + + /* + ** VWT - Wind Speed and Angle + ** + ** 1 2 3 4 5 6 7 8 + ** | | | | | | | | + ** $--VWT,x.x,L,x.x,N,x.x,M,x.x,K,*hh + ** + ** 1) Wind direction magnitude in degrees + ** 2) Wind direction Left/Right of bow + ** 3) Speed + ** 4) N = Knots + ** 5) Speed + ** 6) M = Meters Per Second + ** 7) Speed + ** 8) K = Kilometers Per Hour + ** 9) Checksum + */ + + /* + ** First we check the checksum... + */ + + if ( sentence.IsChecksumBad( 9 ) == TRUE ) + { + SetErrorMessage( _T("Invalid Checksum") ); + return( FALSE ); + } + + WindDirectionMagnitude = sentence.Double( 1 ); + DirectionOfWind = sentence.LeftOrRight( 2 ); + WindSpeedKnots = sentence.Double( 3 ); + WindSpeedms = sentence.Double( 5 ); + WindSpeedKmh = sentence.Double( 7 ); + + return( TRUE ); +} + +bool VWT::Write( SENTENCE& sentence ) +{ +// ASSERT_VALID( this ); + + /* + ** Let the parent do its thing + */ + + RESPONSE::Write( sentence ); + + sentence += WindDirectionMagnitude; + sentence += DirectionOfWind; + sentence += WindSpeedKnots; + sentence += WindSpeedms; + sentence += WindSpeedms; + sentence += WindSpeedKmh; + + return( TRUE ); +} + +const VWT& VWT::operator = ( const VWT& source ) +{ +// ASSERT_VALID( this ); + + WindDirectionMagnitude = source.WindDirectionMagnitude; + DirectionOfWind = source.DirectionOfWind; + WindSpeedKnots = source.WindSpeedKnots; + WindSpeedms = source.WindSpeedms; + WindSpeedKmh = source.WindSpeedKmh; + + return( *this ); +} diff --git a/src/nmea0183/vwt.hpp b/src/nmea0183/vwt.hpp new file mode 100644 index 0000000..e848a4c --- /dev/null +++ b/src/nmea0183/vwt.hpp @@ -0,0 +1,77 @@ +/*************************************************************************** + * + * Project: OpenCPN + * Purpose: NMEA0183 Support Classes + * Author: Samuel R. Blackburn, David S. Register, Jean-Eudes Onfray + * + *************************************************************************** + * Copyright (C) 2010 by Samuel R. Blackburn, David S Register * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + *************************************************************************** + * + * S Blackburn's original source license: * + * "You can use it any way you like." * + * More recent (2010) license statement: * + * "It is BSD license, do with it what you will" * + */ + +#if ! defined( VWT_CLASS_HEADER ) +#define VWT_CLASS_HEADER + +/* +** Author: Samuel R. Blackburn +** CI$: 76300,326 +** Internet: sammy@sed.csc.com +** +** You can use it any way you like. +*/ + +class VWT : public RESPONSE +{ +// DECLARE_DYNAMIC( MWV ) + + public: + + VWT(); + ~VWT(); + + /* + ** Data + */ + + double WindDirectionMagnitude; + LEFTRIGHT DirectionOfWind; + double WindSpeedKnots; + double WindSpeedms; + double WindSpeedKmh; + + /* + ** Methods + */ + + virtual void Empty( void ); + virtual bool Parse( const SENTENCE& sentence ); + virtual bool Write( SENTENCE& sentence ); + + /* + ** Operators + */ + + virtual const VWT& operator = ( const VWT& source ); +}; + +#endif // VWT_CLASS_HEADER diff --git a/src/ocpn_plugin.h b/src/ocpn_plugin.h new file mode 100644 index 0000000..553f996 --- /dev/null +++ b/src/ocpn_plugin.h @@ -0,0 +1,558 @@ +/****************************************************************************** + * + * Project: OpenCPN + * Purpose: PlugIn Object Definition/API + * Author: David Register + * + *************************************************************************** + * Copyright (C) 2010 by David S. Register * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + *************************************************************************** + * + */ +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + + +#ifndef DECL_EXP +#ifdef __WXMSW__ +# define DECL_EXP __declspec(dllexport) +#else +# define DECL_EXP +#endif +#endif + + +#ifdef __GNUC__ +#undef DECL_EXP +#define DECL_EXP __attribute__((visibility("default"))) +#endif + +#include +#include + +// This is the most modern API Version number +// It is expected that the API will remain downward compatible, meaning that +// PlugIns conforming to API Version less then the most modern will also +// be correctly supported. +#define API_VERSION_MAJOR 1 +#define API_VERSION_MINOR 9 + +// Fwd Definitions +class wxFileConfig; +class wxNotebook; +class wxFont; +class wxAuiManager; + +//--------------------------------------------------------------------------------------------------------- +// +// Bitfield PlugIn Capabilites flag definition +// +//--------------------------------------------------------------------------------------------------------- +#define WANTS_OVERLAY_CALLBACK 0x00000001 +#define WANTS_CURSOR_LATLON 0x00000002 +#define WANTS_TOOLBAR_CALLBACK 0x00000004 +#define INSTALLS_TOOLBAR_TOOL 0x00000008 +#define WANTS_CONFIG 0x00000010 +#define INSTALLS_TOOLBOX_PAGE 0x00000020 +#define INSTALLS_CONTEXTMENU_ITEMS 0x00000040 +#define WANTS_NMEA_SENTENCES 0x00000080 +#define WANTS_NMEA_EVENTS 0x00000100 +#define WANTS_AIS_SENTENCES 0x00000200 +#define USES_AUI_MANAGER 0x00000400 +#define WANTS_PREFERENCES 0x00000800 +#define INSTALLS_PLUGIN_CHART 0x00001000 +#define WANTS_ONPAINT_VIEWPORT 0x00002000 +#define WANTS_PLUGIN_MESSAGING 0x00004000 +#define WANTS_OPENGL_OVERLAY_CALLBACK 0x00008000 +#define WANTS_DYNAMIC_OPENGL_OVERLAY_CALLBACK 0x00010000 + +//---------------------------------------------------------------------------------------------------------- +// Some PlugIn API interface object class definitions +//---------------------------------------------------------------------------------------------------------- +enum PI_ColorScheme +{ + PI_GLOBAL_COLOR_SCHEME_RGB, + PI_GLOBAL_COLOR_SCHEME_DAY, + PI_GLOBAL_COLOR_SCHEME_DUSK, + PI_GLOBAL_COLOR_SCHEME_NIGHT, + PI_N_COLOR_SCHEMES +}; + +class PlugIn_ViewPort +{ + public: + double clat; // center point + double clon; + double view_scale_ppm; + double skew; + double rotation; + + float chart_scale; // conventional chart displayed scale + + int pix_width; + int pix_height; + wxRect rv_rect; + bool b_quilt; + int m_projection_type; + + double lat_min, lat_max, lon_min, lon_max; + + bool bValid; // This VP is valid +}; + +class PlugIn_Position_Fix +{ + public: + double Lat; + double Lon; + double Cog; + double Sog; + double Var; // Variation, typically from RMC message + time_t FixTime; + int nSats; +}; + +class PlugIn_Position_Fix_Ex +{ + public: + double Lat; + double Lon; + double Cog; + double Sog; + double Var; // Variation, typically from RMC message + double Hdm; + double Hdt; + time_t FixTime; + int nSats; +}; + +// Describe AIS Alarm state +enum plugin_ais_alarm_type +{ + PI_AIS_NO_ALARM = 0, + PI_AIS_ALARM_SET, + PI_AIS_ALARM_ACKNOWLEDGED + +}; + + +class PlugIn_AIS_Target +{ + public: + + int MMSI; + int Class; + int NavStatus; + double SOG; + double COG; + double HDG; + double Lon; + double Lat; + int ROTAIS; + char CallSign[8]; // includes terminator + char ShipName[21]; + unsigned char ShipType; + int IMO; + + double Range_NM; + double Brg; + + // Per target collision parameters + bool bCPA_Valid; + double TCPA; // Minutes + double CPA; // Nautical Miles + + plugin_ais_alarm_type alarm_state; +}; + + +// ChartType constants +typedef enum ChartTypeEnumPI +{ + PI_CHART_TYPE_UNKNOWN = 0, + PI_CHART_TYPE_DUMMY, + PI_CHART_TYPE_DONTCARE, + PI_CHART_TYPE_KAP, + PI_CHART_TYPE_GEO, + PI_CHART_TYPE_S57, + PI_CHART_TYPE_CM93, + PI_CHART_TYPE_CM93COMP, + PI_CHART_TYPE_PLUGIN +}_ChartTypeEnumPI; + +// ChartFamily constants +typedef enum ChartFamilyEnumPI +{ + PI_CHART_FAMILY_UNKNOWN = 0, + PI_CHART_FAMILY_RASTER, + PI_CHART_FAMILY_VECTOR, + PI_CHART_FAMILY_DONTCARE +}_ChartFamilyEnumPI; + +// Depth unit type enum +typedef enum ChartDepthUnitTypePI +{ + PI_DEPTH_UNIT_UNKNOWN, + PI_DEPTH_UNIT_FEET, + PI_DEPTH_UNIT_METERS, + PI_DEPTH_UNIT_FATHOMS +}_ChartDepthUnitTypePI; + +// Projection type enum +typedef enum OcpnProjTypePI +{ + PI_PROJECTION_UNKNOWN, + PI_PROJECTION_MERCATOR, + PI_PROJECTION_TRANSVERSE_MERCATOR, + PI_PROJECTION_POLYCONIC +}_OcpnProjTypePI; + +typedef struct _ExtentPI{ + double SLAT; + double WLON; + double NLAT; + double ELON; +}ExtentPI; + +// PlugInChartBase::Init() init_flags constants +#define PI_FULL_INIT 0 +#define PI_HEADER_ONLY 1 +#define PI_THUMB_ONLY 2 + + +// ---------------------------------------------------------------------------- +// PlugInChartBase +// This class is the base class for Plug-able chart types +// ---------------------------------------------------------------------------- + +class DECL_EXP PlugInChartBase : public wxObject +{ + public: + // These methods Must be overriden in any derived class + PlugInChartBase(); + virtual ~PlugInChartBase(); + + virtual wxString GetFileSearchMask(void); + + virtual int Init( const wxString& full_path, int init_flags ); + virtual void SetColorScheme(int cs, bool bApplyImmediate); + + virtual double GetNormalScaleMin(double canvas_scale_factor, bool b_allow_overzoom); + virtual double GetNormalScaleMax(double canvas_scale_factor, int canvas_width); + virtual double GetNearestPreferredScalePPM(double target_scale_ppm); + + virtual bool GetChartExtent(ExtentPI *pext); + + virtual wxBitmap &RenderRegionView(const PlugIn_ViewPort& VPoint, const wxRegion &Region); + + virtual bool AdjustVP(PlugIn_ViewPort &vp_last, PlugIn_ViewPort &vp_proposed); + + virtual void GetValidCanvasRegion(const PlugIn_ViewPort& VPoint, wxRegion *pValidRegion); + + virtual int GetCOVREntries(){ return 0; } + virtual int GetCOVRTablePoints(int iTable) { return 0; } + virtual int GetCOVRTablenPoints(int iTable){ return 0; } + virtual float *GetCOVRTableHead(int iTable){ return (float *)NULL; } + + virtual wxBitmap *GetThumbnail(int tnx, int tny, int cs); + +// Accessors, need not be overridden in derived class if the member variables are maintained + virtual wxString GetFullPath() const { return m_FullPath;} + virtual ChartTypeEnumPI GetChartType() { return m_ChartType;} + virtual ChartFamilyEnumPI GetChartFamily() { return m_ChartFamily;} + virtual OcpnProjTypePI GetChartProjection() { return m_projection;} + virtual wxString GetName() { return m_Name;} + virtual wxString GetDescription() { return m_Description;} + virtual wxString GetID() { return m_ID;} + virtual wxString GetSE() { return m_SE;} + virtual wxString GetDepthUnits() { return m_DepthUnits;} + virtual wxString GetSoundingsDatum() { return m_SoundingsDatum;} + virtual wxString GetDatumString() { return m_datum_str;} + virtual wxString GetExtraInfo() { return m_ExtraInfo; } + virtual wxString GetPubDate() { return m_PubYear;} + virtual double GetChartErrorFactor() { return m_Chart_Error_Factor;} + virtual ChartDepthUnitTypePI GetDepthUnitId() { return m_depth_unit_id;} + virtual bool IsReadyToRender() { return m_bReadyToRender;} + virtual int GetNativeScale() { return m_Chart_Scale; }; + virtual double GetChartSkew() { return m_Chart_Skew; } + virtual wxDateTime GetEditionDate(void) { return m_EdDate;} + +// Methods pertaining to CHART_FAMILY_RASTER type PlugIn charts only + virtual void ComputeSourceRectangle(const PlugIn_ViewPort &vp, wxRect *pSourceRect); + virtual double GetRasterScaleFactor(); + virtual bool GetChartBits( wxRect& source, unsigned char *pPix, int sub_samp ); + virtual int GetSize_X(); + virtual int GetSize_Y(); + virtual void latlong_to_chartpix(double lat, double lon, double &pixx, double &pixy); + + protected: + ChartTypeEnumPI m_ChartType; + ChartFamilyEnumPI m_ChartFamily; + + wxString m_FullPath; + OcpnProjTypePI m_projection; + int m_Chart_Scale; + double m_Chart_Skew; + + wxDateTime m_EdDate; + bool m_bReadyToRender; + + wxString m_Name; + wxString m_Description; + wxString m_ID; + wxString m_SE; + wxString m_SoundingsDatum; + wxString m_datum_str; + wxString m_PubYear; + wxString m_DepthUnits; + wxString m_ExtraInfo; + + ChartDepthUnitTypePI m_depth_unit_id; + + double m_Chart_Error_Factor; + + +}; + + + + + +// Declare an array of PlugIn_AIS_Targets +WX_DEFINE_ARRAY_PTR(PlugIn_AIS_Target *, ArrayOfPlugIn_AIS_Targets); + + + +//---------------------------------------------------------------------------------------------------------- +// The Generic PlugIn Interface Class Definition +// +// This is a virtual class. +// opencpn PlugIns must derive from this class. +// There are two types of methods in this class +// a. Required...must be overridden and implemented by PlugIns +// b. Optional..may be overridden by PlugIns + +// PlugIns must implement optional method overrides consistent with their +// declared capabilities flag as returned by Init(). +//---------------------------------------------------------------------------------------------------------- +class DECL_EXP opencpn_plugin +{ + +public: + opencpn_plugin(void *pmgr) {} + virtual ~opencpn_plugin(); + + // Public API to the PlugIn class + + // This group of methods is required, and will be called by the opencpn host + // opencpn PlugIns must implement this group + virtual int Init(void); // Return the PlugIn Capabilites flag + virtual bool DeInit(void); + + virtual int GetAPIVersionMajor(); + virtual int GetAPIVersionMinor(); + virtual int GetPlugInVersionMajor(); + virtual int GetPlugInVersionMinor(); + virtual wxBitmap *GetPlugInBitmap(); + + // These three methods should produce valid, meaningful strings always + // ---EVEN IF--- the PlugIn has not (yet) been initialized. + // They are used by the PlugInManager GUI + virtual wxString GetCommonName(); + virtual wxString GetShortDescription(); + virtual wxString GetLongDescription(); + + // This group is optional. + // PlugIns may override any of these methods as required + + virtual void SetDefaults(void); //This will be called upon enabling a PlugIn via the user Dialog + //It gives a chance to setup any default options and behavior + + virtual int GetToolbarToolCount(void); + + virtual int GetToolboxPanelCount(void); + virtual void SetupToolboxPanel(int page_sel, wxNotebook* pnotebook); + virtual void OnCloseToolboxPanel(int page_sel, int ok_apply_cancel); + + virtual void ShowPreferencesDialog( wxWindow* parent ); + + virtual bool RenderOverlay(wxMemoryDC *pmdc, PlugIn_ViewPort *vp); + virtual void SetCursorLatLon(double lat, double lon); + virtual void SetCurrentViewPort(PlugIn_ViewPort &vp); + + virtual void SetPositionFix(PlugIn_Position_Fix &pfix); + virtual void SetNMEASentence(wxString &sentence); + virtual void SetAISSentence(wxString &sentence); + + virtual void ProcessParentResize(int x, int y); + virtual void SetColorScheme(PI_ColorScheme cs); + + virtual void OnToolbarToolCallback(int id); + virtual void OnContextMenuItemCallback(int id); + + virtual void UpdateAuiStatus(void); + + virtual wxArrayString GetDynamicChartClassNameArray(void); + + }; + + + // the types of the class factories used to create PlugIn instances + typedef opencpn_plugin* create_t(void*); + typedef void destroy_t(opencpn_plugin*); + + class DECL_EXP opencpn_plugin_16 : public opencpn_plugin + { + public: + opencpn_plugin_16(void *pmgr); + virtual ~opencpn_plugin_16(); + + virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp); + + virtual void SetPluginMessage(wxString &message_id, wxString &message_body); + + }; + +class DECL_EXP opencpn_plugin_17 : public opencpn_plugin +{ + public: + opencpn_plugin_17(void *pmgr); + virtual ~opencpn_plugin_17(); + + virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp); + virtual bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp); + + virtual void SetPluginMessage(wxString &message_id, wxString &message_body); + +}; + +class DECL_EXP opencpn_plugin_18 : public opencpn_plugin +{ + public: + opencpn_plugin_18(void *pmgr); + virtual ~opencpn_plugin_18(); + + virtual bool RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp); + virtual bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp); + + virtual void SetPluginMessage(wxString &message_id, wxString &message_body); + virtual void SetPositionFixEx(PlugIn_Position_Fix_Ex &pfix); + +}; + +class DECL_EXP opencpn_plugin_19 : public opencpn_plugin_18 +{ + public: + opencpn_plugin_19(void *pmgr); + virtual ~opencpn_plugin_19(); + + virtual void OnSetupOptions(void); +}; + +//---------------------------------------------------------------------------------------------------------- +// The PlugIn CallBack API Definition +// +// The API back up to the PlugIn Manager +// PlugIns may call these static functions as necessary for system services +// +//---------------------------------------------------------------------------------------------------------- + + +extern "C" DECL_EXP int InsertPlugInTool(wxString label, wxBitmap *bitmap, wxBitmap *bmpDisabled, wxItemKind kind, + wxString shortHelp, wxString longHelp, wxObject *clientData, int position, + int tool_sel, opencpn_plugin *pplugin); +extern "C" DECL_EXP void RemovePlugInTool(int tool_id); +extern "C" DECL_EXP void SetToolbarToolViz(int item, bool viz); // Temporarily change toolbar tool viz +extern "C" DECL_EXP void SetToolbarItemState(int item, bool toggle); +extern "C" DECL_EXP void SetToolbarToolBitmaps(int item, wxBitmap *bitmap, wxBitmap *bmpDisabled); + +extern "C" DECL_EXP int AddCanvasContextMenuItem(wxMenuItem *pitem, opencpn_plugin *pplugin ); +extern "C" DECL_EXP void RemoveCanvasContextMenuItem(int item); // Fully remove this item +extern "C" DECL_EXP void SetCanvasContextMenuItemViz(int item, bool viz); // Temporarily change context menu ptions +extern "C" DECL_EXP void SetCanvasContextMenuItemGrey(int item, bool grey); + + +extern "C" DECL_EXP wxFileConfig *GetOCPNConfigObject(void); + +extern "C" DECL_EXP void RequestRefresh(wxWindow *); +extern "C" DECL_EXP bool GetGlobalColor(wxString colorName, wxColour *pcolour); + +extern "C" DECL_EXP void GetCanvasPixLL(PlugIn_ViewPort *vp, wxPoint *pp, double lat, double lon); +extern "C" DECL_EXP void GetCanvasLLPix( PlugIn_ViewPort *vp, wxPoint p, double *plat, double *plon); + +extern "C" DECL_EXP wxWindow *GetOCPNCanvasWindow(); + +extern "C" DECL_EXP wxFont *OCPNGetFont(wxString TextElement, int default_size); + +extern "C" DECL_EXP wxString *GetpSharedDataLocation(); + +extern "C" DECL_EXP ArrayOfPlugIn_AIS_Targets *GetAISTargetArray(void); + +extern "C" DECL_EXP wxAuiManager *GetFrameAuiManager(void); + +extern "C" DECL_EXP bool AddLocaleCatalog( wxString catalog ); + +extern "C" DECL_EXP void PushNMEABuffer( wxString str ); + +extern DECL_EXP wxXmlDocument GetChartDatabaseEntryXML(int dbIndex, bool b_getGeom); + +extern DECL_EXP bool UpdateChartDBInplace(wxArrayString dir_array, + bool b_force_update, + bool b_ProgressDialog); +extern DECL_EXP wxArrayString GetChartDBDirArrayString(); + +extern "C" DECL_EXP void SendPluginMessage( wxString message_id, wxString message_body ); + +extern "C" DECL_EXP void DimeWindow(wxWindow *); + +extern "C" DECL_EXP void JumpToPosition(double lat, double lon, double scale); + +/* API 1.9 adds some common cartographic fucntions to avoid unnecessary code duplication */ +/* Study the original OpenCPN source (georef.c) for functional definitions */ + +extern "C" void DistanceBearingMercator(double lat0, double lon0, double lat1, double lon1, double *brg, double *dist); +extern "C" double DistGreatCircle(double slat, double slon, double dlat, double dlon); + +extern "C" void toTM(float lat, float lon, float lat0, float lon0, double *x, double *y); +extern "C" void fromTM(double x, double y, double lat0, double lon0, double *lat, double *lon); +extern "C" void toSM(double lat, double lon, double lat0, double lon0, double *x, double *y); +extern "C" void fromSM(double x, double y, double lat0, double lon0, double *lat, double *lon); +extern "C" void toSM_ECC(double lat, double lon, double lat0, double lon0, double *x, double *y); +extern "C" void fromSM_ECC(double x, double y, double lat0, double lon0, double *lat, double *lon); + +extern "C" DECL_EXP bool DecodeSingleVDOMessage( const wxString& str, PlugIn_Position_Fix_Ex *pos, wxString *acc ); + + +/* API 1.9 */ +typedef enum OptionsParentPI +{ + PI_OPTIONS_PARENT_DISPLAY, + PI_OPTIONS_PARENT_CONNECTIONS, + PI_OPTIONS_PARENT_CHARTS, + PI_OPTIONS_PARENT_SHIPS, + PI_OPTIONS_PARENT_UI, + PI_OPTIONS_PARENT_PLUGINS +}_OptionsParentPI; +extern DECL_EXP wxScrolledWindow *AddOptionsPage( OptionsParentPI parent, wxString title ); +extern DECL_EXP bool DeleteOptionsPage( wxScrolledWindow* page ); + +extern "C" DECL_EXP int GetChartbarHeight( void ); +extern "C" DECL_EXP bool GetActiveRoutepointGPX( char *buffer, unsigned int buffer_length ); + +#endif // _PLUGIN_H_ + diff --git a/src/polar_pi.cpp b/src/polar_pi.cpp index a6c62d2..4cb5010 100644 --- a/src/polar_pi.cpp +++ b/src/polar_pi.cpp @@ -71,7 +71,7 @@ extern "C" DECL_EXP void destroy_pi(opencpn_plugin* p) //--------------------------------------------------------------------------------------------------------- polar_pi::polar_pi(void *ppimgr) - :opencpn_plugin_17(ppimgr) + :opencpn_plugin_19(ppimgr) { // Create the PlugIn icons initialize_images(); @@ -296,7 +296,6 @@ void polar_pi::OnToolbarToolCallback(int id) // Qualify the Polar dialog position bool b_reset_pos = false; - #ifdef __WXMSW__ // Support MultiMonitor setups which an allow negative window positions. // If the requested window does not intersect any installed monitor, diff --git a/src/polar_pi.h b/src/polar_pi.h index 3442fce..30efd25 100644 --- a/src/polar_pi.h +++ b/src/polar_pi.h @@ -33,13 +33,13 @@ #include "wx/wx.h" #endif //precompiled headers -#define PLUGIN_VERSION_MAJOR 0 -#define PLUGIN_VERSION_MINOR 6 +#define PLUGIN_VERSION_MAJOR 1 +#define PLUGIN_VERSION_MINOR 0 #define MY_API_VERSION_MAJOR 1 -#define MY_API_VERSION_MINOR 7 +#define MY_API_VERSION_MINOR 9 -#include "../../../include/ocpn_plugin.h" +#include "ocpn_plugin.h" #include "PolarDialog.h" #include "Options.h" @@ -50,7 +50,7 @@ #define POLAR_TOOL_POSITION -1 // Request default positioning of toolbar tool -class polar_pi : public opencpn_plugin_17 +class polar_pi : public opencpn_plugin_19 { public: polar_pi(void *ppimgr);