[qmapshack] 06/11: Imported Upstream version 0.8.2

Bas Couwenberg sebastic at xs4all.nl
Sat Dec 13 14:11:34 UTC 2014


This is an automated email from the git hooks/post-receive script.

sebastic-guest pushed a commit to branch master
in repository qmapshack.

commit dd602b9433106596cb8849146e33b7d8f84b1d30
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Dec 13 01:32:21 2014 +0100

    Imported Upstream version 0.8.2
---
 .hg_archival.txt                                |   4 +-
 .hgtags                                         |   1 +
 CMakeLists.txt                                  |   2 +-
 changelog.txt                                   |   7 +
 nsi/3rdparty.txt                                |   9 +-
 nsi/QMapShack_Installer32.nsi                   | 265 +++++++++++
 nsi/copyfiles.bat                               |   1 +
 nsi/{copyfiles.bat => copyfiles32.bat}          |  19 +-
 src/CMakeLists.txt                              |   7 +-
 src/canvas/CCanvas.cpp                          |   2 +-
 src/canvas/CCanvas.h                            |   4 +-
 src/gis/CGisListDB.cpp                          |   2 +-
 src/gis/CGisListWks.cpp                         | 587 ++++++++++++++----------
 src/gis/CGisListWks.h                           |   2 +
 src/gis/CGisWidget.cpp                          |  39 +-
 src/gis/CGisWidget.h                            |  27 +-
 src/gis/IGisItem.cpp                            |  71 ++-
 src/gis/IGisItem.h                              |  25 +-
 src/gis/db/CDBProject.h                         |   2 +-
 src/gis/gpx/CGpxProject.h                       |   2 +-
 src/gis/gpx/serialization.cpp                   |  18 +-
 src/gis/ovl/CGisItemOvlArea.cpp                 |  42 +-
 src/gis/ovl/CGisItemOvlArea.h                   |   6 +-
 src/gis/ovl/CScrOptOvlArea.cpp                  |   6 +-
 src/gis/ovl/CScrOptOvlArea.h                    |   4 +-
 src/gis/prj/CDetailsPrj.cpp                     | 122 +++++
 src/gis/{rte/CScrOptRte.h => prj/CDetailsPrj.h} |  31 +-
 src/gis/prj/IDetailsPrj.ui                      |  85 ++++
 src/gis/{ => prj}/IGisProject.cpp               |  88 +++-
 src/gis/{ => prj}/IGisProject.h                 |  26 +-
 src/gis/qms/CQmsProject.h                       |   2 +-
 src/gis/qms/serialization.cpp                   |  14 +-
 src/gis/rte/CGisItemRte.cpp                     |   9 +-
 src/gis/rte/CGisItemRte.h                       |   2 +-
 src/gis/rte/CScrOptRte.cpp                      |   4 +-
 src/gis/rte/CScrOptRte.h                        |   3 +-
 src/gis/search/CSearchGoogle.h                  |   2 +-
 src/gis/trk/CCombineTrk.cpp                     |  34 +-
 src/gis/trk/CCombineTrk.h                       |   5 +-
 src/gis/trk/CGisItemTrk.cpp                     |  15 +-
 src/gis/trk/CGisItemTrk.h                       |   4 +-
 src/gis/trk/CScrOptTrk.cpp                      |   3 +-
 src/gis/trk/CScrOptTrk.h                        |   3 +-
 src/gis/wpt/CGisItemWpt.cpp                     |   8 +-
 src/gis/wpt/CGisItemWpt.h                       |   2 +-
 src/gis/wpt/CProjWpt.cpp                        |   2 +-
 src/gis/wpt/CScrOptWpt.cpp                      |   5 +-
 src/gis/wpt/CScrOptWpt.h                        |   3 +-
 src/grid/CGrid.cpp                              |   7 +-
 src/helpers/CHistoryListWidget.cpp              |   1 +
 src/helpers/CHistoryListWidget.h                |   2 +-
 src/helpers/CSelectProjectDialog.cpp            |   2 +-
 src/mouse/CMouseEditArea.cpp                    |  14 +-
 src/mouse/CMouseEditArea.h                      |   4 +-
 src/mouse/CMouseEditTrk.cpp                     |  12 +-
 src/mouse/CMouseEditTrk.h                       |   3 +-
 src/mouse/CMouseMoveWpt.cpp                     |   8 +-
 src/mouse/CMouseMoveWpt.h                       |   3 +-
 src/mouse/CMouseNormal.cpp                      |  11 +-
 src/mouse/CMouseRangeTrk.cpp                    |  10 +-
 src/mouse/CMouseRangeTrk.h                      |   3 +-
 src/mouse/CScrOptUnclutter.cpp                  |   7 +-
 src/mouse/CScrOptUnclutter.h                    |   7 +-
 src/units/CUnitImperial.cpp                     |  15 +
 src/units/CUnitImperial.h                       |   1 +
 src/units/CUnitMetric.cpp                       |  14 +
 src/units/CUnitMetric.h                         |   1 +
 src/units/CUnitNautic.cpp                       |  15 +
 src/units/CUnitNautic.h                         |   1 +
 src/units/IUnit.h                               |   2 +
 70 files changed, 1317 insertions(+), 452 deletions(-)

diff --git a/.hg_archival.txt b/.hg_archival.txt
index 0cbe63a..9b979dc 100644
--- a/.hg_archival.txt
+++ b/.hg_archival.txt
@@ -1,4 +1,4 @@
 repo: 9d6ee306235c77d65d21797124dfc82760eb94e8
-node: ef016d14cfedfd7ef049e654b8ba51ddd0596550
+node: ab336ed933234bea7ae829acce0f915af0bf03a7
 branch: default
-tag: V 0.8.1
+tag: V 0.8.2
diff --git a/.hgtags b/.hgtags
index 0248458..9219266 100644
--- a/.hgtags
+++ b/.hgtags
@@ -16,3 +16,4 @@ c0720884e8fdba0b812a76e8620f972f302e4162 V 0.5.0
 d7d2ddcbb62525558535f27ebffb1f9a54133441 V 0.6.0
 60688b74ffb725c9c4503e61557365f83300f678 V 0.7.0
 c77136ce6df5377999c5c4fa3b8030a34e67e9a0 V 0.8.0
+ef016d14cfedfd7ef049e654b8ba51ddd0596550 V 0.8.1
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3e8b77..808ec86 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,7 +21,7 @@ set(APPLICATION_NAME qmapshack)
 
 set(APPLICATION_VERSION_MAJOR "0")
 set(APPLICATION_VERSION_MINOR "8")
-set(APPLICATION_VERSION_PATCH "1")
+set(APPLICATION_VERSION_PATCH "2")
 
 add_definitions(-DVER_MAJOR=${APPLICATION_VERSION_MAJOR} -DVER_MINOR=${APPLICATION_VERSION_MINOR} -DVER_STEP=${APPLICATION_VERSION_PATCH} -DAPPLICATION_NAME=${PROJECT_NAME})
 
diff --git a/changelog.txt b/changelog.txt
index 3724bc6..498cc05 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,10 @@
+V 0.8.2
+* Calculate area covered by area overlays
+* Change coordinate format for long/lat grid from dd mm.mm to dd.dddddd
+* Add edit widget for project details
+* Add drag-n-drop for multiple GIS items
+* Enhance delete of multiple items
+
 V 0.8.1
 * Handle "no data" values in DEM files
 * Garmin maps: read copyright information 
diff --git a/nsi/3rdparty.txt b/nsi/3rdparty.txt
index cea56d8..2b0f0df 100644
--- a/nsi/3rdparty.txt
+++ b/nsi/3rdparty.txt
@@ -46,10 +46,10 @@ Compile instructions - to be verified
 2.) Compile the PROJ library http://trac.osgeo.org/proj/
 - Download the source code of the version 4.8 (or latest) from http://trac.osgeo.org/proj/ and unzip
 - In nmake.opt, adapt the following lines, according to your build environment [my settings are given as example]
-  INSTDIR=M:\lib\\PROJ
+  INSTDIR=M:\lib\PROJ
 - From the start menu, enter the VS2013, x64 native command prompt
 - nmake /f makefile.vc
-- nmake /f makefile.vc devinstall
+- nmake /f makefile.vc install-all
 
 3.) Install QT5.3 or later 
 - Download and run the Qt5 Windows Online Installer from http://qt-project.org/downloads
@@ -69,7 +69,10 @@ Note: you might have to install TortoiseHG
 6.) Open the generated QMapShack.sln with VS2013
 - Compile the Release Version
 
-7.) Create the installer by executing
+7.) Download the VC redistributable installer 
+  from http://www.microsoft.com/en-us/download/details.aspx?id=40784
+
+8.) Create the installer by executing
 - nsi/copyfiles.bat
   Note: In copyfiles.bat, you may have to adapt the directories where you have installed Qt5, GDAL and PROJ.4.
 - nsi/QMapShack_Installer.nsi
diff --git a/nsi/QMapShack_Installer32.nsi b/nsi/QMapShack_Installer32.nsi
new file mode 100644
index 0000000..76dcaf9
--- /dev/null
+++ b/nsi/QMapShack_Installer32.nsi
@@ -0,0 +1,265 @@
+;NSIS Installer Script for https://bitbucket.org/maproom/qmapshack/wiki/Home
+
+;NSIS References/Documentation 
+;http://nsis.sourceforge.net/Docs/Modern%20UI%202/Readme.html
+;http://nsis.sourceforge.net/Docs/Modern%20UI/Readme.html
+;http://nsis.sourceforge.net/Docs/Chapter4.html
+;http://nsis.sourceforge.net/Many_Icons_Many_shortcuts
+
+;Deployment issues
+;Deploying Qt5 for Windows:
+;  http://qt-project.org/doc/qt-5/windows-deployment.html
+;Deploying MSVC runtime libraries
+;  http://msdn.microsoft.com/en-us/library/dd293574.aspx ==> Central Deployment is preferred: by using a redistributable package enables automatic updating by Microsoft.
+;  http://msdn.microsoft.com/en-us/library/8kche8ah.aspx ==> Distribute msvcr120.dll and msvcp120.dll
+;  http://www.microsoft.com/en-us/download/details.aspx?id=40784 ==> Download the vcredist_x64.exe from here !!!
+;  http://msdn.microsoft.com/en-us/vstudio/dn501987.aspx ==> Legal stuff
+
+;Revision Log
+; 14-Nov-2014 32-bit variant Installer forked from 64-bit original
+; 03-Aug-2014 First version of QMapShack installer based on the existing QLandkarteGT installer
+
+;=================== BEGIN SCRIPT ====================
+; Include for nice Setup UI, see http://nsis.sourceforge.net/Docs/Modern%20UI%202/Readme.html
+!include MUI2.nsh
+
+;------------------------------------------------------------------------
+; Modern UI2 definition                                                  -
+;------------------------------------------------------------------------
+; Description
+Name "QMapShack32"
+
+;Default installation folder
+InstallDir "$PROGRAMFiles32\QMapShack32"
+
+;Get installation folder from registry if available
+InstallDirRegKey HKCU "Software\QMapShack32" ""
+
+;Request application privileges for Windows Vista
+RequestExecutionLevel admin
+
+
+; The file to write
+OutFile "QMapShack_Install32.exe"
+
+;------------------------------------------------------------------------
+; Modern UI definition                                                    -
+;------------------------------------------------------------------------
+;!define MUI_COMPONENTSPAGE_SMALLDESC ;No value
+!define MUI_INSTFILESPAGE_COLORS "FFFFFF 000000" ;Two colors
+
+!define MUI_ICON "QMapShack.ico"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "MUI_HEADERIMAGE.bmp"
+!define MUI_WELCOMEFINISHPAGE_BITMAP "MUI_WELCOMEFINISHPAGE.bmp"
+
+; Page welcome description
+!define MUI_WELCOMEPAGE_TITLE "QMapShack"
+!define MUI_WELCOMEPAGE_TITLE_3LINES
+!define MUI_WELCOMEPAGE_TEXT "QMapShack provides a versatile and fast display of raster and vector maps with visualization of GIS data such as tracks and waypoints. It allows the use of several workspaces and of several maps on a workspace. GIS data is handled project-oriented and can be exchanged with the device by drag-n-drop."
+
+!define MUI_LICENSEPAGE_CHECKBOX
+
+;------------------------------------------------------------------------
+; Pages definition order                                                -
+;------------------------------------------------------------------------
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_LICENSE "..\LICENSE"
+!insertmacro MUI_PAGE_COMPONENTS
+!insertmacro MUI_PAGE_DIRECTORY
+Var StartMenuFolder
+!insertmacro MUI_PAGE_STARTMENU "Application" $StartMenuFolder
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+;------------------------------------------------------------------------
+
+;------------------------------------------------------------------------
+;Uninstaller                                                            -
+;------------------------------------------------------------------------
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+
+; Language settings
+!insertmacro MUI_LANGUAGE "English"
+!insertmacro MUI_LANGUAGE "German"
+
+
+;------------------------------------------------------------------------
+; Component add                                                            -
+;------------------------------------------------------------------------
+;Components description
+
+Section "MSVC++ 2013 SP1 Runtime" MSVC
+
+  SetOutPath $INSTDIR
+  File Files32\vcredist_x86.exe
+  ExecWait '"$INSTDIR\vcredist_x86.exe"'
+  Delete "$INSTDIR\vcredist_x86.exe"
+  
+SectionEnd
+LangString DESC_MSVC ${LANG_ENGLISH} "Microsoft Visual C++ 2013 SP1 Runtime Libraries. Typically already installed on your PC. You only need to install them if it doesn't work without ;-)."
+LangString DESC_MSVC ${LANG_GERMAN} "Microsoft Visual C++ 2013 SP1 Laufzeitbibliotheken. Diese sind meist bereits auf dem Rechner installiert. Versuchen Sie die Installation zun�chst einmal ohne dies."
+
+Section "QMapShack" QMapShack
+
+  ;Install for all users
+  SetShellVarContext all
+
+  ;BEGIN QMapShack Files    
+  SetOutPath $INSTDIR
+    File Files32\qmapshack.exe
+    File Files32\qmapshack_*.qm
+	File Files32\*.ico
+	;File Files32\*.png
+    File Files32\qt_??.qm
+  ;END QMapShack Files    
+   
+  ;BEGIN Qt Files
+  SetOutPath $INSTDIR
+    File Files32\Qt5Core.dll
+    File Files32\Qt5Gui.dll
+	File Files32\Qt5Multimedia.dll
+	File Files32\Qt5MultimediaWidgets.dll
+    File Files32\Qt5Network.dll
+    File Files32\Qt5OpenGL.dll
+	File Files32\Qt5Positioning.dll
+	File Files32\Qt5PrintSupport.dll
+	File Files32\Qt5Qml.dll
+	File Files32\Qt5Quick.dll
+    File Files32\Qt5Script.dll
+	File Files32\Qt5Sensors.dll
+    File Files32\Qt5Sql.dll
+    File Files32\Qt5Svg.dll
+    File Files32\Qt5WebKit.dll
+    File Files32\Qt5Widgets.dll 
+    File Files32\Qt5WebKitWidgets.dll	
+    File Files32\Qt5Xml.dll
+	File Files32\icudt52.dll
+	File Files32\icuin52.dll
+	File Files32\icuuc52.dll
+	File Files32\libEGL.dll
+	File Files32\libGLESv2.dll
+
+  SetOutPath "$INSTDIR\imageformats\"
+    File Files32\imageformats\qgif.dll
+    File Files32\imageformats\qjpeg.dll
+    File Files32\imageformats\qmng.dll
+    File Files32\imageformats\qsvg.dll
+    File Files32\imageformats\qtiff.dll
+    File Files32\imageformats\qico.dll
+    File Files32\imageformats\qtga.dll
+
+  SetOutPath "$INSTDIR\sqldrivers\"
+    File Files32\sqldrivers\qsqlite.dll
+
+  SetOutPath "$INSTDIR\platforms\"
+    File Files32\platforms\qwindows.dll	
+	
+	;END Qt Files
+    
+  ;BEGIN GDAL and PROJ.4 Files    
+  SetOutPath $INSTDIR
+    File Files32\gdal*.dll
+    File Files32\gdal*.exe
+	File Files32\nearblack.exe
+	File Files32\ogr*.exe
+	File Files32\testepsg.exe
+  SetOutPath "$INSTDIR\data\"
+    File /r Files32\data\*.*
+  ;END GDAL and PROJ.4 Files        
+
+  ;BEGIN PROJ.4 Files    
+  SetOutPath $INSTDIR
+    File Files32\proj*.dll
+    File Files32\proj*.exe
+  SetOutPath "$INSTDIR\share\"
+	File /r Files32\share\*.*
+  ;END PROJ.4 Files        
+
+  
+  ;BEGIN additional Files    
+  SetOutPath $INSTDIR
+    File Files32\3rdparty.txt
+    ;File Files32\libexif-12.dll
+  ;END additional Files    
+    
+  ;the last "SetOutPath" will be the default directory
+  SetOutPath $INSTDIR    
+  
+
+  WriteUninstaller "$INSTDIR\Uninstall.exe"
+SectionEnd
+LangString DESC_QMapShack ${LANG_ENGLISH} "View GeoTiff and Garmin Maps. Visualize and analyze GPX files and much more!"
+LangString DESC_QMapShack ${LANG_GERMAN}  "Landkarten im GeoTiff und Garmin Format betrachten. GPX Dateien visualisieren und analysieren und vieles mehr!"
+
+
+Section "StartMenue" StartMenue
+  ;create batch file for a GDAL shell
+  fileOpen $0 "$INSTDIR\gdal_shell.bat" w
+  fileWrite $0 "@cd /D %USERPROFILE%$\r$\n" 
+  fileWrite $0 "@SET PATH=$INSTDIR;%PATH%$\r$\n"
+  fileWrite $0 "@SET GDAL_DATA=$INSTDIR\data$\r$\n"
+  fileWrite $0 "@SET PROJ_LIB=$INSTDIR\share$\r$\n"
+  fileClose $0
+
+  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+     ;Create shortcuts
+    CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
+    CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
+    CreateShortCut "$SMPROGRAMS\$StartMenuFolder\QMapShack.lnk" "$INSTDIR\qmapshack.exe" "" "$INSTDIR\QMapShack.ico"
+    CreateShortCut "$SMPROGRAMS\$StartMenuFolder\qmapshack.org.lnk" "https://bitbucket.org/maproom/qmapshack/wiki/Home" "" "$INSTDIR\kfm_home.ico"
+    CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Help.lnk" "https://bitbucket.org/maproom/qmapshack/wiki/DocMain" "" "$INSTDIR\Help.ico"
+    CreateShortCut "$SMPROGRAMS\$StartMenuFolder\gdal.org.lnk" "http://www.gdal.org/" "" "$INSTDIR\gdalicon.ico"
+    CreateShortCut "$SMPROGRAMS\$StartMenuFolder\GDAL shell.lnk" %COMSPEC% "/k $\"$INSTDIR\gdal_shell.bat$\"" "" "" "" "" "GDAL shell"
+   !insertmacro MUI_STARTMENU_WRITE_END
+
+  ;Create registry entries
+  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QMapShack" "DisplayName" "QMapShack (remove only)"
+  WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QMapShack" "UninstallString" "$INSTDIR\Uninstall.exe"
+
+SectionEnd
+LangString DESC_StartMenue ${LANG_ENGLISH} "Create Start Menue (deselect if you want install QMapShack as portable app)"
+LangString DESC_StartMenue ${LANG_GERMAN}  "Erzeuge Start Men� (weglassen, wenn QMapShack als portable app installiert werden soll)"
+
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+   !insertmacro MUI_DESCRIPTION_TEXT ${QMapShack} $(DESC_QMapShack)
+   !insertmacro MUI_DESCRIPTION_TEXT ${StartMenue} $(DESC_StartMenue)
+   !insertmacro MUI_DESCRIPTION_TEXT ${MSVC} $(DESC_MSVC)
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+;------------------------------------------------------------------------
+;Uninstaller Sections                                                    -
+;------------------------------------------------------------------------
+Section "Uninstall"
+
+  ;Install for all users
+  SetShellVarContext all
+
+  Delete "$INSTDIR\Uninstall.exe"
+
+  SetOutPath $TEMP
+
+  RMDir /r $INSTDIR
+
+  !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
+
+  Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk"
+  Delete "$SMPROGRAMS\$StartMenuFolder\QMapShack.lnk"
+  Delete "$SMPROGRAMS\$StartMenuFolder\qmapshack.org.lnk"
+  Delete "$SMPROGRAMS\$StartMenuFolder\Help.lnk"
+  Delete "$SMPROGRAMS\$StartMenuFolder\gdal.org.lnk"
+  Delete "$SMPROGRAMS\$StartMenuFolder\GDAL shell.lnk"
+  
+  RMDir "$SMPROGRAMS\$StartMenuFolder"
+
+  DeleteRegKey /ifempty HKCU "Software\QMapShack"
+  DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\QMapShack"
+
+SectionEnd
+
+Function .onInit
+  # set section 'MSVC' as unselected
+  SectionSetFlags ${MSVC} 0
+FunctionEnd
+
diff --git a/nsi/copyfiles.bat b/nsi/copyfiles.bat
index c77dc9f..cbcca43 100644
--- a/nsi/copyfiles.bat
+++ b/nsi/copyfiles.bat
@@ -7,6 +7,7 @@ rem http://vlaurie.com/computers2/Articles/environment.htm
 
 rem Section 1.) Define path to Qt, MSVC, .... installations
 set QMSI_QT_PATH="C:\Qt5\5.3\msvc2013_64"
+rem get the VC redistributable installer from http://www.microsoft.com/en-us/download/details.aspx?id=40784
 set QMSI_VCREDIST_PATH="M:\deploy"
 rem set QLGTI_LIBEXIF_PATH="D:\qlgt\tools\libexif"
 set QMSI_GDAL_PATH="M:\lib\gdal"
diff --git a/nsi/copyfiles.bat b/nsi/copyfiles32.bat
similarity index 85%
copy from nsi/copyfiles.bat
copy to nsi/copyfiles32.bat
index c77dc9f..aa60e26 100644
--- a/nsi/copyfiles.bat
+++ b/nsi/copyfiles32.bat
@@ -6,16 +6,17 @@ rem http://technet.microsoft.com/en-us/library/bb491035.aspx
 rem http://vlaurie.com/computers2/Articles/environment.htm
 
 rem Section 1.) Define path to Qt, MSVC, .... installations
-set QMSI_QT_PATH="C:\Qt5\5.3\msvc2013_64"
+set QMSI_QT_PATH="C:\Qt5\5.3\msvc2013"
+rem get the VC redistributable installer from http://www.microsoft.com/en-us/download/details.aspx?id=40784
 set QMSI_VCREDIST_PATH="M:\deploy"
 rem set QLGTI_LIBEXIF_PATH="D:\qlgt\tools\libexif"
-set QMSI_GDAL_PATH="M:\lib\gdal"
-set QMSI_PROJ_PATH="M:\lib\PROJ"
+set QMSI_GDAL_PATH="M:\lib32\gdal"
+set QMSI_PROJ_PATH="M:\lib32\PROJ"
 
 rem Section 2.) Copy Files
-del /s/q Files
-mkdir Files
-cd Files
+del /s/q Files32
+mkdir Files32
+cd Files32
 
 rem Section 2.1) Copy Qt files
 copy %QMSI_QT_PATH%\bin\Qt5Core.dll
@@ -77,12 +78,12 @@ copy %QMSI_PROJ_PATH%\bin\*.dll
 copy %QMSI_PROJ_PATH%\bin\proj.exe
 
 rem section 2.3) Copy MSVC Redist Files
-copy %QMSI_VCREDIST_PATH%\vcredist_x64.exe
+copy %QMSI_VCREDIST_PATH%\vcredist_x86.exe
 rem section 2.4) Copy libexif Files
 rem copy %QLGTI_LIBEXIF_PATH%\libexif-12.dll
 rem section 2.5) Copy QMapShack GT Files
-copy ..\..\build\bin\Release\qmapshack.exe
-copy ..\..\build\src\*.qm
+copy ..\..\build32\bin\Release\qmapshack.exe
+copy ..\..\build32\src\*.qm
 copy ..\*.ico
 rem section 2.6) 3rd party SW description
 copy ..\3rdparty.txt
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c3fb21e..36350b7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -95,7 +95,8 @@ set( SRCS
     gis/CGisWidget.cpp
     gis/CGisListDB.cpp
     gis/CGisListWks.cpp
-    gis/IGisProject.cpp
+    gis/prj/IGisProject.cpp
+    gis/prj/CDetailsPrj.cpp
     gis/gpx/CGpxProject.cpp
     gis/gpx/serialization.cpp
     gis/qms/CQmsProject.cpp
@@ -217,7 +218,8 @@ set( HDRS
     gis/CGisDraw.h
     gis/IGisItem.h
     gis/IGisLine.h
-    gis/IGisProject.h
+    gis/prj/IGisProject.h
+    gis/prj/CDetailsPrj.h
     gis/CGisWidget.h
     gis/CGisListDB.h
     gis/CGisListWks.h
@@ -283,6 +285,7 @@ set( UIS
     mouse/IScrOptRange.ui
     mouse/IScrOptRangeTrk.ui
     gis/IGisWidget.ui
+    gis/prj/IDetailsPrj.ui
     gis/db/ISetupDB.ui
     gis/db/ISetupFolder.ui
     gis/wpt/IScrOptWpt.ui
diff --git a/src/canvas/CCanvas.cpp b/src/canvas/CCanvas.cpp
index 0fcee24..6e93255 100644
--- a/src/canvas/CCanvas.cpp
+++ b/src/canvas/CCanvas.cpp
@@ -592,7 +592,7 @@ void CCanvas::slotToolTip()
 
 void CCanvas::slotCheckTrackOnFocus()
 {
-    const QString& key = CGisItemTrk::getKeyUserFocus();
+    const IGisItem::key_t& key = CGisItemTrk::getKeyUserFocus();
 
     // any changes?
     if(key != keyTrackOnFocus)
diff --git a/src/canvas/CCanvas.h b/src/canvas/CCanvas.h
index 973c693..5fe344f 100644
--- a/src/canvas/CCanvas.h
+++ b/src/canvas/CCanvas.h
@@ -24,6 +24,8 @@
 #include <QPointer>
 #include <QMap>
 
+#include "gis/IGisItem.h"
+
 class CMapDraw;
 class CGrid;
 class CDemDraw;
@@ -192,7 +194,7 @@ class CCanvas : public QWidget
         /// timer to poll for track gaining/loosing focus
         QTimer * timerTrackOnFocus;
         /// the key of the currentl focused track
-        QString keyTrackOnFocus;
+        IGisItem::key_t keyTrackOnFocus;
         /// the track profile plot
         QPointer<IPlot>  plotTrackProfile;
 
diff --git a/src/gis/CGisListDB.cpp b/src/gis/CGisListDB.cpp
index 9e20b9a..281ab5c 100644
--- a/src/gis/CGisListDB.cpp
+++ b/src/gis/CGisListDB.cpp
@@ -241,7 +241,7 @@ void CGisListDB::slotAddFolder()
     query.bindValue(":child", idChild);
     QUERY_EXEC(return);
 
-    IDBFolder * childFolder = IDBFolder::createFolderByType(type, idChild, parentFolder);
+    IDBFolder::createFolderByType(type, idChild, parentFolder);
 }
 
 void CGisListDB::slotItemExpanded(QTreeWidgetItem * item)
diff --git a/src/gis/CGisListWks.cpp b/src/gis/CGisListWks.cpp
index 37fa44c..e1fb5bd 100644
--- a/src/gis/CGisListWks.cpp
+++ b/src/gis/CGisListWks.cpp
@@ -20,7 +20,7 @@
 #include "gis/CGisListWks.h"
 #include "gis/CGisWidget.h"
 #include "gis/IGisItem.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/db/macros.h"
 #include "gis/gpx/CGpxProject.h"
 #include "gis/ovl/CGisItemOvlArea.h"
@@ -46,6 +46,7 @@ CGisListWks::CGisListWks(QWidget *parent)
     menuProject     = new QMenu(this);
     actionSaveAs    = menuProject->addAction(QIcon("://icons/32x32/SaveGISAs.png"),tr("Save As..."), this, SLOT(slotSaveAsProject()));
     actionSave      = menuProject->addAction(QIcon("://icons/32x32/SaveGIS.png"),tr("Save"), this, SLOT(slotSaveProject()));
+    actionEditPrj   = menuProject->addAction(QIcon("://icons/32x32/EditDetails.png"),tr("Edit.."), this, SLOT(slotEditPrj()));
     actionClose     = menuProject->addAction(QIcon("://icons/32x32/Close.png"),tr("Close"), this, SLOT(slotCloseProject()));
 
     connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotContextMenu(QPoint)));
@@ -93,87 +94,96 @@ void CGisListWks::setExternalMenu(QMenu * project)
 
 void CGisListWks::dragMoveEvent (QDragMoveEvent  * e )
 {
-    /*
-        What's happening here?
 
-        1) Cast current item and item under cursor to GIS item type
-        2) If type matches for both test for common parent
-        2.1) common parent->  move
-        2.1) different parent -> copy
-        3) go on with dragMoveEvent();
-
-     */
+    QTreeWidgetItem * item1 = currentItem();
+    QTreeWidgetItem * item2 = itemAt(e->pos());
 
-    CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(currentItem());
-    CGisItemTrk * trk2 = dynamic_cast<CGisItemTrk*>(itemAt(e->pos()));
 
-    if(trk1 && trk2)
+    // changeing the item order is only valid for single selected items
+    if(selectedItems().count() == 1)
     {
-        if(trk1->parent() == trk2->parent())
-        {
-            e->setDropAction(Qt::MoveAction);
-        }
-        else
-        {
-            e->setDropAction(Qt::CopyAction);
-        }
-        QTreeWidget::dragMoveEvent(e);
-        return;
-    }
+        /*
+            What's happening here?
 
-    CGisItemWpt * wpt1 = dynamic_cast<CGisItemWpt*>(currentItem());
-    CGisItemWpt * wpt2 = dynamic_cast<CGisItemWpt*>(itemAt(e->pos()));
+            1) Cast current item and item under cursor to GIS item type
+            2) If type matches for both test for common parent
+            2.1) common parent->  move
+            2.1) different parent -> copy
+            3) go on with dragMoveEvent();
 
-    if(wpt1 && wpt2)
-    {
-        if(wpt1->parent() == wpt2->parent())
-        {
-            e->setDropAction(Qt::MoveAction);
-        }
-        else
-        {
-            e->setDropAction(Qt::CopyAction);
-        }
-        QTreeWidget::dragMoveEvent(e);
-        return;
-    }
+         */
 
-    CGisItemRte * rte1 = dynamic_cast<CGisItemRte*>(currentItem());
-    CGisItemRte * rte2 = dynamic_cast<CGisItemRte*>(itemAt(e->pos()));
+        CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(item1);
+        CGisItemTrk * trk2 = dynamic_cast<CGisItemTrk*>(item2);
 
-    if(rte1 && rte2)
-    {
-        if(rte1->parent() == rte2->parent())
+        if(trk1 && trk2)
         {
-            e->setDropAction(Qt::MoveAction);
+            if(trk1->parent() == trk2->parent())
+            {
+                e->setDropAction(Qt::MoveAction);
+            }
+            else
+            {
+                e->setDropAction(Qt::CopyAction);
+            }
+            QTreeWidget::dragMoveEvent(e);
+            return;
         }
-        else
+
+        CGisItemWpt * wpt1 = dynamic_cast<CGisItemWpt*>(item1);
+        CGisItemWpt * wpt2 = dynamic_cast<CGisItemWpt*>(item2);
+
+        if(wpt1 && wpt2)
         {
-            e->setDropAction(Qt::CopyAction);
+            if(wpt1->parent() == wpt2->parent())
+            {
+                e->setDropAction(Qt::MoveAction);
+            }
+            else
+            {
+                e->setDropAction(Qt::CopyAction);
+            }
+            QTreeWidget::dragMoveEvent(e);
+            return;
         }
-        QTreeWidget::dragMoveEvent(e);
-        return;
-    }
 
-    CGisItemOvlArea * area1 = dynamic_cast<CGisItemOvlArea*>(currentItem());
-    CGisItemOvlArea * area2 = dynamic_cast<CGisItemOvlArea*>(itemAt(e->pos()));
+        CGisItemRte * rte1 = dynamic_cast<CGisItemRte*>(item1);
+        CGisItemRte * rte2 = dynamic_cast<CGisItemRte*>(item2);
 
-    if(area1 && area2)
-    {
-        if(area1->parent() == area2->parent())
+        if(rte1 && rte2)
         {
-            e->setDropAction(Qt::MoveAction);
+            if(rte1->parent() == rte2->parent())
+            {
+                e->setDropAction(Qt::MoveAction);
+            }
+            else
+            {
+                e->setDropAction(Qt::CopyAction);
+            }
+            QTreeWidget::dragMoveEvent(e);
+            return;
         }
-        else
+
+        CGisItemOvlArea * area1 = dynamic_cast<CGisItemOvlArea*>(item1);
+        CGisItemOvlArea * area2 = dynamic_cast<CGisItemOvlArea*>(item2);
+
+        if(area1 && area2)
         {
-            e->setDropAction(Qt::CopyAction);
+            if(area1->parent() == area2->parent())
+            {
+                e->setDropAction(Qt::MoveAction);
+            }
+            else
+            {
+                e->setDropAction(Qt::CopyAction);
+            }
+            QTreeWidget::dragMoveEvent(e);
+            return;
         }
-        QTreeWidget::dragMoveEvent(e);
-        return;
     }
 
-    IGisProject * proj = dynamic_cast<IGisProject*>(itemAt(e->pos()));
-    if(proj && proj != currentItem()->parent())
+    IGisProject * proj = dynamic_cast<IGisProject*>(item2);
+    if(proj && (proj != currentItem()->parent()))
     {
         e->setDropAction(Qt::CopyAction);
         QTreeWidget::dragMoveEvent(e);
@@ -186,55 +196,85 @@ void CGisListWks::dragMoveEvent (QDragMoveEvent  * e )
 
 void CGisListWks::dropEvent ( QDropEvent  * e )
 {
-    // block out items with same key (duplicats)
-    IGisItem * item1 = dynamic_cast<IGisItem*>(currentItem());
-    IGisItem * item2 = dynamic_cast<IGisItem*>(itemAt(e->pos()));
-    if(item1 && item2)
+    QList<QTreeWidgetItem*> duplicate;
+    QList<QTreeWidgetItem*> items   = selectedItems();
+    QTreeWidgetItem * item2         = itemAt(e->pos());
+
+    int cnt = 1;
+    int N   = items.size();
+    QProgressDialog progress("Check for duplicat...", "Abort check", 0, 100, this);
+    progress.setWindowModality(Qt::WindowModal);
+
+    // collect duplicat items
+    foreach(QTreeWidgetItem * item1, items)
     {
-        // if it is a drop on an item and the other item is in another project
-        if(item1->parent() != item2->parent())
+        progress.setValue((100 * cnt++) / N);
+        if (progress.wasCanceled())
         {
-            // iterate over all items of the target project and check keys
-            QTreeWidgetItem * parent = item2->parent();
-            for(int i = 0; i < parent->childCount(); i++)
+            return;
+        }
+
+        IGisItem * gisItem1 = dynamic_cast<IGisItem*>(item1);
+        IGisItem * gisItem2 = dynamic_cast<IGisItem*>(item2);
+        if(gisItem1 && gisItem2)
+        {
+            // if it is a drop on an item and the other item is in another project
+            if(gisItem1->parent() != gisItem2->parent())
             {
-                IGisItem * item = dynamic_cast<IGisItem*>(parent->child(i));
-                if(item)
+                // iterate over all items of the target project and check keys
+                QTreeWidgetItem * parent = gisItem2->parent();
+                for(int i = 0; i < parent->childCount(); i++)
                 {
-                    if(item->getKey() == item1->getKey())
+                    IGisItem * gisItem = dynamic_cast<IGisItem*>(parent->child(i));
+                    if(gisItem)
                     {
-                        return;
+                        if(gisItem->getKey().item == gisItem1->getKey().item)
+                        {
+                            duplicate << gisItem1;
+                        }
                     }
                 }
             }
         }
-    }
-    else
-    {
-        // if it is a drop on a project the project is different from the source item's project
-        IGisProject * parent = dynamic_cast<IGisProject*>(itemAt(e->pos()));
-        if(parent && item1 && item1->parent() != parent)
+        else
         {
-            // iterate over all items of the target project and check keys
-            for(int i = 0; i < parent->childCount(); i++)
+            // if it is a drop on a project and the project is different from the source item's project
+            IGisProject * parent = dynamic_cast<IGisProject*>(itemAt(e->pos()));
+            if(parent && gisItem1 && gisItem1->parent() != parent)
             {
-                IGisItem * item = dynamic_cast<IGisItem*>(parent->child(i));
-                if(item)
+                // iterate over all items of the target project and check keys
+                for(int i = 0; i < parent->childCount(); i++)
                 {
-                    if(item->getKey() == item1->getKey())
+                    IGisItem * gisItem = dynamic_cast<IGisItem*>(parent->child(i));
+                    if(gisItem)
                     {
-                        return;
+                        if(gisItem->getKey().item == gisItem1->getKey().item)
+                        {
+                            duplicate << gisItem1;
+                        }
                     }
                 }
             }
         }
     }
 
-    // go on with item insertion
+    // finally, remove all duplicat items from local list of selected item
+    foreach(QTreeWidgetItem * item, duplicate)
+    {
+        items.removeAll(item);
+    }
 
+    if(items.isEmpty())
+    {
+        return;
+    }
+
+
+    // go on with item insertion        
     /*
         What's happening here?
 
+        for single selected items do:
         1) Test if item will be inserted above ore below item under cursor.
         2) Cast current item and item under cursor to GIS item type
         3) If type matches for both test for common parent
@@ -242,122 +282,148 @@ void CGisListWks::dropEvent ( QDropEvent  * e )
         3.1) different parent -> create a copy and insert it index
         4) signal change of project
 
+        for single and multiple selected items, do:
         5) Test if item under cursor is a project
         6) If project and project is not item's project create a copy
 
      */
 
-    // calc. index offset (below/above item)
-    QRect r = visualItemRect(itemAt(e->pos()));
-    int y1 = r.top() + r.height()/2;
-    int y2 = e->pos().y();
-    int off = y2 > y1 ? 1 : 0;
+    if(items.size() == 1)
+    {
+        // calc. index offset (below/above item)
+        QRect r = visualItemRect(itemAt(e->pos()));
+        int y1 = r.top() + r.height()/2;
+        int y2 = e->pos().y();
+        int off = y2 > y1 ? 1 : 0;
 
-    CGisItemWpt * wpt1 = dynamic_cast<CGisItemWpt*>(currentItem());
-    CGisItemWpt * wpt2 = dynamic_cast<CGisItemWpt*>(itemAt(e->pos()));
+        CGisItemWpt * wpt1 = dynamic_cast<CGisItemWpt*>(currentItem());
+        CGisItemWpt * wpt2 = dynamic_cast<CGisItemWpt*>(itemAt(e->pos()));
 
-    if(wpt1 && wpt2)
-    {
-        if(wpt1->parent() == wpt2->parent())
-        {
-            QTreeWidget::dropEvent(e);
-        }
-        else
+        if(wpt1 && wpt2)
         {
-            IGisProject * project = dynamic_cast<IGisProject*>(wpt2->parent());
-            if(project)
+            if(wpt1->parent() == wpt2->parent())
+            {
+                QTreeWidget::dropEvent(e);
+            }
+            else
             {
-                new CGisItemWpt(*wpt1,project, project->indexOfChild(wpt2) + off);
+                IGisProject * project = dynamic_cast<IGisProject*>(wpt2->parent());
+                if(project)
+                {
+                    new CGisItemWpt(*wpt1,project, project->indexOfChild(wpt2) + off);
+                }
             }
+            emit sigChanged();
+            return;
         }
-        emit sigChanged();
-        return;
-    }
 
-    CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(currentItem());
-    CGisItemTrk * trk2 = dynamic_cast<CGisItemTrk*>(itemAt(e->pos()));
+        CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(currentItem());
+        CGisItemTrk * trk2 = dynamic_cast<CGisItemTrk*>(itemAt(e->pos()));
 
-    if(trk1 && trk2)
-    {
-        if(trk1->parent() == trk2->parent())
+        if(trk1 && trk2)
         {
-            QTreeWidget::dropEvent(e);
-        }
-        else
-        {
-            IGisProject * project = dynamic_cast<IGisProject*>(trk2->parent());
-            if(project)
+            if(trk1->parent() == trk2->parent())
             {
-                new CGisItemTrk(*trk1,project, project->indexOfChild(trk2) + off);
+                QTreeWidget::dropEvent(e);
             }
+            else
+            {
+                IGisProject * project = dynamic_cast<IGisProject*>(trk2->parent());
+                if(project)
+                {
+                    new CGisItemTrk(*trk1,project, project->indexOfChild(trk2) + off);
+                }
+            }
+            emit sigChanged();
+            return;
         }
-        emit sigChanged();
-        return;
-    }
 
-    CGisItemRte * rte1 = dynamic_cast<CGisItemRte*>(currentItem());
-    CGisItemRte * rte2 = dynamic_cast<CGisItemRte*>(itemAt(e->pos()));
+        CGisItemRte * rte1 = dynamic_cast<CGisItemRte*>(currentItem());
+        CGisItemRte * rte2 = dynamic_cast<CGisItemRte*>(itemAt(e->pos()));
 
-    if(rte1 && rte2)
-    {
-        if(rte1->parent() == rte2->parent())
-        {
-            QTreeWidget::dropEvent(e);
-        }
-        else
+        if(rte1 && rte2)
         {
-            IGisProject * project = dynamic_cast<IGisProject*>(rte2->parent());
-            if(project)
+            if(rte1->parent() == rte2->parent())
+            {
+                QTreeWidget::dropEvent(e);
+            }
+            else
             {
-                new CGisItemRte(*rte1,project, project->indexOfChild(rte2) + off);
+                IGisProject * project = dynamic_cast<IGisProject*>(rte2->parent());
+                if(project)
+                {
+                    new CGisItemRte(*rte1,project, project->indexOfChild(rte2) + off);
+                }
             }
+            emit sigChanged();
+            return;
         }
-        emit sigChanged();
-        return;
-    }
 
-    CGisItemOvlArea * area1 = dynamic_cast<CGisItemOvlArea*>(currentItem());
-    CGisItemOvlArea * area2 = dynamic_cast<CGisItemOvlArea*>(itemAt(e->pos()));
+        CGisItemOvlArea * area1 = dynamic_cast<CGisItemOvlArea*>(currentItem());
+        CGisItemOvlArea * area2 = dynamic_cast<CGisItemOvlArea*>(itemAt(e->pos()));
 
-    if(area1 && area2)
-    {
-        if(area1->parent() == area2->parent())
+        if(area1 && area2)
         {
-            QTreeWidget::dropEvent(e);
-        }
-        else
-        {
-            IGisProject * project = dynamic_cast<IGisProject*>(area2->parent());
-            if(project)
+            if(area1->parent() == area2->parent())
             {
-                new CGisItemOvlArea(*area1,project, project->indexOfChild(area2) + off);
+                QTreeWidget::dropEvent(e);
             }
+            else
+            {
+                IGisProject * project = dynamic_cast<IGisProject*>(area2->parent());
+                if(project)
+                {
+                    new CGisItemOvlArea(*area1,project, project->indexOfChild(area2) + off);
+                }
+            }
+            emit sigChanged();
+            return;
         }
-        emit sigChanged();
-        return;
     }
 
-
+    // check if item at position is a project and insert a copy of all selected items
     IGisProject * project = dynamic_cast<IGisProject*>(itemAt(e->pos()));
-    if(project && project != currentItem()->parent())
+    if(project)
     {
-        if(wpt1 != 0)
-        {
-            new CGisItemWpt(*wpt1, project, -1);
-        }
-        else if(trk1 != 0)
-        {
-            new CGisItemTrk(*trk1, project, -1);
-        }
-        else if(rte1 != 0)
-        {
-            new CGisItemRte(*rte1, project, -1);
-        }
-        else if(area1 != 0)
+        int cnt = 1;
+        int N   = items.size();
+        QProgressDialog progress("Drop items...", "Abort drop", 0, 100, this);
+        progress.setWindowModality(Qt::WindowModal);
+
+        foreach(QTreeWidgetItem * item, items)
         {
-            new CGisItemOvlArea(*area1, project, -1);
+            progress.setValue((100 * cnt++) / N);
+            if (progress.wasCanceled())
+            {
+                break;
+            }
+
+            if(project != item->parent())
+            {
+                if(item->type() == IGisItem::eTypeWpt)
+                {
+                    CGisItemWpt * wpt1 = dynamic_cast<CGisItemWpt*>(item);
+                    new CGisItemWpt(*wpt1, project, -1);
+                }
+                if(item->type() == IGisItem::eTypeTrk)
+                {
+                    CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(item);
+                    new CGisItemTrk(*trk1, project, -1);
+                }
+                if(item->type() == IGisItem::eTypeRte)
+                {
+                    CGisItemRte * rte1 = dynamic_cast<CGisItemRte*>(item);
+                    new CGisItemRte(*rte1, project, -1);
+                }
+                if(item->type() == IGisItem::eTypeOvl)
+                {
+                    CGisItemOvlArea * area1 = dynamic_cast<CGisItemOvlArea*>(item);
+                    new CGisItemOvlArea(*area1, project, -1);
+                }
+            }
         }
     }
+    emit sigChanged();
 }
 
 
@@ -493,67 +559,105 @@ void CGisListWks::slotContextMenu(const QPoint& point)
         return;
     }
 
-    IGisProject * project = dynamic_cast<IGisProject*>(currentItem());
-    if(project != 0)
+    if(selectedItems().count() > 1)
     {
-        QPoint p = mapToGlobal(point);
-        menuProject->exec(p);
-        return;
-    }
-
-    IGisItem * gisItem = dynamic_cast<IGisItem*>(currentItem());
-    if(gisItem != 0)
-    {
-        // try to cast item to waypoint and hide/show actions on result
-        CGisItemWpt * wpt = dynamic_cast<CGisItemWpt*>(gisItem);
-        if(wpt == 0)
-        {
-            actionProjWpt->setVisible(false);
-            actionMoveWpt->setVisible(false);
-        }
-        else
+        IGisProject * project = dynamic_cast<IGisProject*>(currentItem());
+        if(project != 0)
         {
-            actionProjWpt->setVisible(true);
-            actionMoveWpt->setVisible(true);
-            actionMoveWpt->setEnabled(!wpt->isReadOnly());
-            actionProjWpt->setEnabled(!wpt->isGeocache());
+            actionEditPrj->setVisible(false);
+
+            QPoint p = mapToGlobal(point);
+            menuProject->exec(p);
+            return;
         }
 
-        // try to cast item to track and hide/show actions on result
-        CGisItemTrk * trk = dynamic_cast<CGisItemTrk*>(gisItem);
-        if(trk == 0)
+        IGisItem * gisItem = dynamic_cast<IGisItem*>(currentItem());
+        if(gisItem != 0)
         {
+            actionEditDetails->setVisible(false);
+            actionProjWpt->setVisible(false);
+            actionMoveWpt->setVisible(false);
             actionFocusTrk->setVisible(false);
             actionEditTrk->setVisible(false);
             actionReverseTrk->setVisible(false);
             actionCombineTrk->setVisible(false);
             actionRangeTrk->setVisible(false);
+            actionEditArea->setVisible(false);
+
+            QPoint p = mapToGlobal(point);
+            menuItem->exec(p);
         }
-        else
-        {
-            actionFocusTrk->setVisible(true);
-            actionEditTrk->setVisible(true);
-            actionReverseTrk->setVisible(true);
-            actionCombineTrk->setVisible(true);
-            actionRangeTrk->setVisible(true);
-            actionFocusTrk->setChecked(trk->hasUserFocus());
-            actionEditTrk->setEnabled(!trk->isReadOnly());
-        }
+        return;
+    }
 
-        // try to cast item to track and hide/show actions on result
-        CGisItemOvlArea * area = dynamic_cast<CGisItemOvlArea*>(gisItem);
-        if(area == 0)
+    if(selectedItems().count() == 1)
+    {
+        IGisProject * project = dynamic_cast<IGisProject*>(currentItem());
+        if(project != 0)
         {
-            actionEditArea->setVisible(false);
+            actionEditPrj->setVisible(true);
+
+            QPoint p = mapToGlobal(point);
+            menuProject->exec(p);
+            return;
         }
-        else
+
+        IGisItem * gisItem = dynamic_cast<IGisItem*>(currentItem());
+        if(gisItem != 0)
         {
-            actionEditArea->setVisible(true);
+            actionEditDetails->setVisible(true);
+
+            // try to cast item to waypoint and hide/show actions on result
+            CGisItemWpt * wpt = dynamic_cast<CGisItemWpt*>(gisItem);
+            if(wpt == 0)
+            {
+                actionProjWpt->setVisible(false);
+                actionMoveWpt->setVisible(false);
+            }
+            else
+            {
+                actionProjWpt->setVisible(true);
+                actionMoveWpt->setVisible(true);
+                actionMoveWpt->setEnabled(!wpt->isReadOnly());
+                actionProjWpt->setEnabled(!wpt->isGeocache());
+            }
+
+            // try to cast item to track and hide/show actions on result
+            CGisItemTrk * trk = dynamic_cast<CGisItemTrk*>(gisItem);
+            if(trk == 0)
+            {
+                actionFocusTrk->setVisible(false);
+                actionEditTrk->setVisible(false);
+                actionReverseTrk->setVisible(false);
+                actionCombineTrk->setVisible(false);
+                actionRangeTrk->setVisible(false);
+            }
+            else
+            {
+                actionFocusTrk->setVisible(true);
+                actionEditTrk->setVisible(true);
+                actionReverseTrk->setVisible(true);
+                actionCombineTrk->setVisible(true);
+                actionRangeTrk->setVisible(true);
+                actionFocusTrk->setChecked(trk->hasUserFocus());
+                actionEditTrk->setEnabled(!trk->isReadOnly());
+            }
+
+            // try to cast item to track and hide/show actions on result
+            CGisItemOvlArea * area = dynamic_cast<CGisItemOvlArea*>(gisItem);
+            if(area == 0)
+            {
+                actionEditArea->setVisible(false);
+            }
+            else
+            {
+                actionEditArea->setVisible(true);
+            }
+            // display menu
+            QPoint p = mapToGlobal(point);
+            menuItem->exec(p);
+            return;
         }
-        // display menu
-        QPoint p = mapToGlobal(point);
-        menuItem->exec(p);
-        return;
     }
 }
 
@@ -606,6 +710,19 @@ void CGisListWks::slotSaveAsProject()
     IGisItem::mutexItems.unlock();
 }
 
+void CGisListWks::slotEditPrj()
+{
+    IGisItem::mutexItems.lock();
+
+    IGisProject * project = dynamic_cast<IGisProject*>(currentItem());
+    if(project != 0)
+    {
+        project->edit();
+    }
+
+    IGisItem::mutexItems.unlock();
+}
+
 void CGisListWks::slotItemDoubleClicked(QTreeWidgetItem * item, int )
 {
     IGisItem::mutexItems.lock();
@@ -624,8 +741,7 @@ void CGisListWks::slotEditItem()
     IGisItem * gisItem = dynamic_cast<IGisItem*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().editItemByKey(key);
+        CGisWidget::self().editItemByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -633,14 +749,23 @@ void CGisListWks::slotEditItem()
 void CGisListWks::slotDeleteItem()
 {
     IGisItem::mutexItems.lock();
+    QList<QTreeWidgetItem*> items       = selectedItems();
+    QMessageBox::StandardButtons last   = QMessageBox::NoButton;
 
-    foreach(QTreeWidgetItem * item, selectedItems())
+    foreach(QTreeWidgetItem * item, items)
     {
         IGisItem * gisItem = dynamic_cast<IGisItem*>(item);
         if(gisItem != 0)
         {
-            QString key = gisItem->getKey();
-            CGisWidget::self().delItemByKey(key);
+            IGisProject * project = dynamic_cast<IGisProject*>(gisItem->parent());
+            if(project)
+            {
+                project->delItemByKey(gisItem->getKey(), last);
+            }
+            if(last == QMessageBox::Cancel)
+            {
+                break;
+            }
         }
     }
     IGisItem::mutexItems.unlock();
@@ -652,8 +777,7 @@ void CGisListWks::slotProjWpt()
     CGisItemWpt * gisItem = dynamic_cast<CGisItemWpt*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().projWptByKey(key);
+        CGisWidget::self().projWptByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -663,9 +787,8 @@ void CGisListWks::slotMoveWpt()
     IGisItem::mutexItems.lock();
     CGisItemWpt * gisItem = dynamic_cast<CGisItemWpt*>(currentItem());
     if(gisItem != 0)
-    {
-        QString key = gisItem->getKey();
-        CGisWidget::self().moveWptByKey(key);
+    {        
+        CGisWidget::self().moveWptByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -676,8 +799,7 @@ void CGisListWks::slotFocusTrk(bool on)
     CGisItemTrk * gisItem = dynamic_cast<CGisItemTrk*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().focusTrkByKey(on, key);
+        CGisWidget::self().focusTrkByKey(on, gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -688,8 +810,7 @@ void CGisListWks::slotEditTrk()
     CGisItemTrk * gisItem = dynamic_cast<CGisItemTrk*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().editTrkByKey(key);
+        CGisWidget::self().editTrkByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -700,8 +821,7 @@ void CGisListWks::slotReverseTrk()
     CGisItemTrk * gisItem = dynamic_cast<CGisItemTrk*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().reverseTrkByKey(key);
+        CGisWidget::self().reverseTrkByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -712,8 +832,7 @@ void CGisListWks::slotCombineTrk()
     CGisItemTrk * gisItem = dynamic_cast<CGisItemTrk*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().combineTrkByKey(key);
+        CGisWidget::self().combineTrkByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -724,8 +843,7 @@ void CGisListWks::slotRangeTrk()
     CGisItemTrk * gisItem = dynamic_cast<CGisItemTrk*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().rangeTrkByKey(key);
+        CGisWidget::self().rangeTrkByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
@@ -736,8 +854,7 @@ void CGisListWks::slotEditArea()
     CGisItemOvlArea * gisItem = dynamic_cast<CGisItemOvlArea*>(currentItem());
     if(gisItem != 0)
     {
-        QString key = gisItem->getKey();
-        CGisWidget::self().editAreaByKey(key);
+        CGisWidget::self().editAreaByKey(gisItem->getKey());
     }
     IGisItem::mutexItems.unlock();
 }
diff --git a/src/gis/CGisListWks.h b/src/gis/CGisListWks.h
index 9ee83e3..0e2c1ea 100644
--- a/src/gis/CGisListWks.h
+++ b/src/gis/CGisListWks.h
@@ -49,6 +49,7 @@ class CGisListWks : public QTreeWidget
         void slotContextMenu(const QPoint& point);
         void slotSaveProject();
         void slotSaveAsProject();
+        void slotEditPrj();
         void slotCloseProject();
         void slotItemDoubleClicked(QTreeWidgetItem * item, int);
         void slotEditItem();
@@ -72,6 +73,7 @@ class CGisListWks : public QTreeWidget
         QMenu * menuProject;
         QAction  * actionSave;
         QAction  * actionSaveAs;
+        QAction  * actionEditPrj;
         QAction  * actionClose;
 
         QMenu * menuItem;
diff --git a/src/gis/CGisWidget.cpp b/src/gis/CGisWidget.cpp
index 275d47d..956a662 100644
--- a/src/gis/CGisWidget.cpp
+++ b/src/gis/CGisWidget.cpp
@@ -20,7 +20,7 @@
 #include "gis/CGisDraw.h"
 #include "gis/CGisWidget.h"
 #include "gis/IGisItem.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/gpx/CGpxProject.h"
 #include "gis/ovl/CGisItemOvlArea.h"
 #include "gis/qms/CQmsProject.h"
@@ -168,7 +168,7 @@ void CGisWidget::getItemsByPos(const QPointF& pos, QList<IGisItem*>& items)
     IGisItem::mutexItems.unlock();
 }
 
-IGisItem * CGisWidget::getItemByKey(const QString& key)
+IGisItem * CGisWidget::getItemByKey(const IGisItem::key_t& key)
 {
     IGisItem * item = 0;
     IGisItem::mutexItems.lock();
@@ -179,6 +179,12 @@ IGisItem * CGisWidget::getItemByKey(const QString& key)
         {
             continue;
         }
+
+        if(project->getKey() != key.project)
+        {
+            continue;
+        }
+
         item = project->getItemByKey(key);
         if(item != 0)
         {
@@ -189,9 +195,10 @@ IGisItem * CGisWidget::getItemByKey(const QString& key)
     return(item);
 }
 
-void CGisWidget::delItemByKey(const QString& key)
+void CGisWidget::delItemByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
+    QMessageBox::StandardButtons last = QMessageBox::NoButton;
     for(int i = 0; i < treeWks->topLevelItemCount(); i++)
     {
         IGisProject * project = dynamic_cast<IGisProject*>(treeWks->topLevelItem(i));
@@ -199,14 +206,18 @@ void CGisWidget::delItemByKey(const QString& key)
         {
             continue;
         }
-        project->delItemByKey(key);
+        project->delItemByKey(key, last);
+        if(last == QMessageBox::Cancel)
+        {
+            break;
+        }
     }
 
     IGisItem::mutexItems.unlock();
     emit sigChanged();
 }
 
-void CGisWidget::editItemByKey(const QString& key)
+void CGisWidget::editItemByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
     for(int i = 0; i < treeWks->topLevelItemCount(); i++)
@@ -223,7 +234,7 @@ void CGisWidget::editItemByKey(const QString& key)
     emit sigChanged();
 }
 
-void CGisWidget::projWptByKey(const QString& key)
+void CGisWidget::projWptByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -238,7 +249,7 @@ void CGisWidget::projWptByKey(const QString& key)
     emit sigChanged();
 }
 
-void CGisWidget::moveWptByKey(const QString& key)
+void CGisWidget::moveWptByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
     CGisItemWpt * wpt = dynamic_cast<CGisItemWpt*>(getItemByKey(key));
@@ -253,7 +264,7 @@ void CGisWidget::moveWptByKey(const QString& key)
     IGisItem::mutexItems.unlock();
 }
 
-void CGisWidget::focusTrkByKey(bool yes, const QString& key)
+void CGisWidget::focusTrkByKey(bool yes, const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -267,7 +278,7 @@ void CGisWidget::focusTrkByKey(bool yes, const QString& key)
     emit sigChanged();
 }
 
-void CGisWidget::cutTrkByKey(const QString& key)
+void CGisWidget::cutTrkByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -280,7 +291,7 @@ void CGisWidget::cutTrkByKey(const QString& key)
     emit sigChanged();
 }
 
-void CGisWidget::reverseTrkByKey(const QString& key)
+void CGisWidget::reverseTrkByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -293,7 +304,7 @@ void CGisWidget::reverseTrkByKey(const QString& key)
     emit sigChanged();
 }
 
-void CGisWidget::combineTrkByKey(const QString& key)
+void CGisWidget::combineTrkByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -306,7 +317,7 @@ void CGisWidget::combineTrkByKey(const QString& key)
     emit sigChanged();
 }
 
-void CGisWidget::editTrkByKey(const QString& key)
+void CGisWidget::editTrkByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -323,7 +334,7 @@ void CGisWidget::editTrkByKey(const QString& key)
     IGisItem::mutexItems.unlock();
 }
 
-void CGisWidget::rangeTrkByKey(const QString& key)
+void CGisWidget::rangeTrkByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
@@ -340,7 +351,7 @@ void CGisWidget::rangeTrkByKey(const QString& key)
     IGisItem::mutexItems.unlock();
 }
 
-void CGisWidget::editAreaByKey(const QString& key)
+void CGisWidget::editAreaByKey(const IGisItem::key_t& key)
 {
     IGisItem::mutexItems.lock();
 
diff --git a/src/gis/CGisWidget.h b/src/gis/CGisWidget.h
index 5f3924e..030887f 100644
--- a/src/gis/CGisWidget.h
+++ b/src/gis/CGisWidget.h
@@ -22,8 +22,9 @@
 #include <QWidget>
 #include "ui_IGisWidget.h"
 
+#include "gis/IGisItem.h"
+
 class CGisDraw;
-class IGisItem;
 class IGisProject;
 
 class CGisWidget : public QWidget, private Ui::IGisWidget
@@ -74,7 +75,7 @@ class CGisWidget : public QWidget, private Ui::IGisWidget
            @param key       the item's key as it is returned from IGisItem::getKey()
            @return If no item is found 0 is returned.
         */
-        IGisItem * getItemByKey(const QString& key);
+        IGisItem * getItemByKey(const IGisItem::key_t &key);
 
         /**
            @brief Delete all items with matching key from workspace
@@ -84,45 +85,45 @@ class CGisWidget : public QWidget, private Ui::IGisWidget
 
            @param key       the item's key as it is returned from IGisItem::getKey()
          */
-        void delItemByKey(const QString& key);
+        void delItemByKey(const IGisItem::key_t &key);
 
         /**
            @brief Edit / view item details
            @param key       the item's key as it is returned from IGisItem::getKey()
          */
-        void editItemByKey(const QString& key);
+        void editItemByKey(const IGisItem::key_t &key);
 
         /**
            @brief Clone waypoint and move clone
            @param key       the item's key as it is returned from IGisItem::getKey()
          */
-        void projWptByKey(const QString& key);
+        void projWptByKey(const IGisItem::key_t &key);
 
         /**
            @brief Move waypoint via mouse
            @param key       the item's key as it is returned from IGisItem::getKey()
          */
-        void moveWptByKey(const QString& key);
+        void moveWptByKey(const IGisItem::key_t &key);
 
         /**
            @brief Set user focus to track
            @param yes       true if focus is set
            @param key       the item's key as it is returned from IGisItem::getKey()
          */
-        void focusTrkByKey(bool yes, const QString& key);
+        void focusTrkByKey(bool yes, const IGisItem::key_t &key);
 
 
-        void cutTrkByKey(const QString& key);
+        void cutTrkByKey(const IGisItem::key_t &key);
 
-        void editTrkByKey(const QString& key);
+        void editTrkByKey(const IGisItem::key_t &key);
 
-        void reverseTrkByKey(const QString& key);
+        void reverseTrkByKey(const IGisItem::key_t &key);
 
-        void combineTrkByKey(const QString& key);
+        void combineTrkByKey(const IGisItem::key_t &key);
 
-        void rangeTrkByKey(const QString& key);
+        void rangeTrkByKey(const IGisItem::key_t &key);
 
-        void editAreaByKey(const QString& key);
+        void editAreaByKey(const IGisItem::key_t &key);
 
 
 
diff --git a/src/gis/IGisItem.cpp b/src/gis/IGisItem.cpp
index 7865aaa..3daee5b 100644
--- a/src/gis/IGisItem.cpp
+++ b/src/gis/IGisItem.cpp
@@ -17,7 +17,7 @@
 **********************************************************************************************/
 
 #include "gis/IGisItem.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/trk/CGisItemTrk.h"
 #include "gis/wpt/CGisItemWpt.h"
 #include "gis/rte/CGisItemRte.h"
@@ -30,6 +30,8 @@
 
 QMutex IGisItem::mutexItems(QMutex::Recursive);
 
+QString IGisItem::noKey;
+
 const IGisItem::color_t IGisItem::colorMap[] =
 {
      {"Black",       QColor(Qt::black)}
@@ -53,12 +55,15 @@ const IGisItem::color_t IGisItem::colorMap[] =
 
 };
 
-IGisItem::IGisItem(QTreeWidgetItem *parent, type_e typ, int idx)
+IGisItem::IGisItem(IGisProject *parent, type_e typ, int idx)
     : QTreeWidgetItem(parent, typ)
     , flags(0)
 {
+    int n;
     setFlags(QTreeWidgetItem::flags() & ~Qt::ItemIsDropEnabled);
 
+    key.project = parent->getKey();
+
     if(idx >= 0)
     {
         parent->removeChild(this);
@@ -68,7 +73,7 @@ IGisItem::IGisItem(QTreeWidgetItem *parent, type_e typ, int idx)
     {        
         if(type() == eTypeTrk)
         {
-            for(int n = parent->childCount() - 2; n >= 0; n--)
+            for(n = parent->childCount() - 2; n >= 0; n--)
             {
                 /** @note   The order of item types to test is given by the order items read from
                             the GPX file in the CGpxProject constructor.  */
@@ -84,7 +89,7 @@ IGisItem::IGisItem(QTreeWidgetItem *parent, type_e typ, int idx)
         }
         else if(type() == eTypeRte)
         {
-            for(int n = parent->childCount() - 2; n >= 0; n--)
+            for(n = parent->childCount() - 2; n >= 0; n--)
             {
                 /** @note   The order of item types to test is given by the order items read from
                             the GPX file in the CGpxProject constructor.  */
@@ -100,7 +105,7 @@ IGisItem::IGisItem(QTreeWidgetItem *parent, type_e typ, int idx)
         }
         else if(type() == eTypeWpt)
         {
-            for(int n = parent->childCount() - 2; n >= 0; n--)
+            for(n = parent->childCount() - 2; n >= 0; n--)
             {
                 /** @note   The order of item types to test is given by the order items read from
                             the GPX file in the CGpxProject constructor.  */
@@ -116,7 +121,7 @@ IGisItem::IGisItem(QTreeWidgetItem *parent, type_e typ, int idx)
         }
         else if(type() == eTypeOvl)
         {
-            for(int n = parent->childCount() - 2; n >= 0; n--)
+            for(n = parent->childCount() - 2; n >= 0; n--)
             {
                 /** @note   The order of item types to test is given by the order items read from
                             the GPX file in the CGpxProject constructor.  */
@@ -131,6 +136,11 @@ IGisItem::IGisItem(QTreeWidgetItem *parent, type_e typ, int idx)
             }
         }
 
+        if(n < 0)
+        {
+            parent->removeChild(this);
+            parent->insertChild(0, this);
+        }
     }
 }
 
@@ -141,7 +151,7 @@ IGisItem::~IGisItem()
 
 void IGisItem::genKey()
 {
-    if(key.isEmpty())
+    if(key.item.isEmpty())
     {
         QByteArray buffer;
         QDataStream stream(&buffer, QIODevice::WriteOnly);
@@ -152,8 +162,19 @@ void IGisItem::genKey()
 
         QCryptographicHash md5(QCryptographicHash::Md5);
         md5.addData(buffer);
-        key = md5.result().toHex();
+        key.item = md5.result().toHex();
+    }
+}
+
+QString IGisItem::getNameEx()
+{
+    QString str = getName();
+    IGisProject * project = dynamic_cast<IGisProject*>(parent());
+    if(project)
+    {
+        str += " @ " + project->getName();
     }
+    return str;
 }
 
 void IGisItem::updateDecoration(mark_e enable, mark_e disable)
@@ -339,9 +360,9 @@ void IGisItem::setReadOnlyMode(bool readOnly)
 }
 
 
-const QString& IGisItem::getKey()
+const IGisItem::key_t &IGisItem::getKey()
 {
-    if(key.isEmpty())
+    if(key.item.isEmpty())
     {
         genKey();
     }
@@ -545,3 +566,33 @@ QString IGisItem::createText(bool isReadOnly, const QString& cmt, const QString&
 
     return str;
 }
+
+QString IGisItem::createText(bool isReadOnly, const QString& desc, const QList<link_t>& links)
+{
+    QString str;
+
+    str += toLink(isReadOnly, "description", QObject::tr("<h4>Description:</h4>"));
+    if(removeHtml(desc).simplified().isEmpty())
+    {
+        str += QObject::tr("<p>--- no description ---</p>");
+    }
+    else
+    {
+        str += desc;
+    }
+
+    str += toLink(isReadOnly, "links", QObject::tr("<h4>Links:</h4>"));
+    if(links.isEmpty())
+    {
+        str += QObject::tr("<p>--- no links ---</p>");
+    }
+    else
+    {
+        foreach(const link_t& link, links)
+        {
+            str += QString("<p><a href='%1'>%2</a></p>").arg(link.uri.toString()).arg(link.text);
+        }
+    }
+
+    return str;
+}
diff --git a/src/gis/IGisItem.h b/src/gis/IGisItem.h
index f88b0b7..d2a8871 100644
--- a/src/gis/IGisItem.h
+++ b/src/gis/IGisItem.h
@@ -36,6 +36,7 @@
 class CGisDraw;
 class IScrOpt;
 class IMouse;
+class IGisProject;
 
 class IGisItem : public QTreeWidgetItem
 {
@@ -120,8 +121,16 @@ class IGisItem : public QTreeWidgetItem
             ,eMarkChanged   = 0x00000001
         };
 
+        struct key_t
+        {
+            bool operator==(const key_t& k) const {return ((item == k.item) && (project == k.project));}
+            bool operator!=(const key_t& k) const {return ((item != k.item) || (project != k.project));}
+            void clear(){item.clear(); project.clear();}
+            QString item;
+            QString project;
+        };
 
-        IGisItem(QTreeWidgetItem * parent, type_e typ, int idx);
+        IGisItem(IGisProject *parent, type_e typ, int idx);
         virtual ~IGisItem();
 
         /// this mutex has to be locked when ever the item list is accessed.
@@ -144,7 +153,8 @@ class IGisItem : public QTreeWidgetItem
            @brief Get key string to identify object
            @return
          */
-        const QString& getKey();
+        const key_t& getKey();
+
         /**
            @brief Get the icon attached to object
            @return
@@ -157,6 +167,12 @@ class IGisItem : public QTreeWidgetItem
         virtual const QString& getName() = 0;
 
         /**
+           @brief Get name of this item extended by the project name
+           @return A string object.
+        */
+        virtual QString getNameEx();
+
+        /**
            @brief Get a short string with the items properties to be displayed in tool tips or similar
            @return A string object.
         */
@@ -266,8 +282,11 @@ class IGisItem : public QTreeWidgetItem
 
         static QString removeHtml(const QString &str);
         static QString createText(bool isReadOnly, const QString& cmt, const QString& desc, const QList<link_t>& links);
+        static QString createText(bool isReadOnly, const QString& desc, const QList<link_t>& links);
         static QString toLink(bool isReadOnly, const QString& href, const QString& str);
 
+        static QString noKey;
+
     protected:
         struct color_t;
 
@@ -293,7 +312,7 @@ class IGisItem : public QTreeWidgetItem
         virtual void changed(const QString& what, const QString& icon);
 
         quint32 flags;
-        QString key;
+        key_t   key;
         QString hash;
         QPixmap icon;
         QRectF boundingRect;
diff --git a/src/gis/db/CDBProject.h b/src/gis/db/CDBProject.h
index 71156a0..1834fea 100644
--- a/src/gis/db/CDBProject.h
+++ b/src/gis/db/CDBProject.h
@@ -19,7 +19,7 @@
 #ifndef CDBPROJECT_H
 #define CDBPROJECT_H
 
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 
 class CDBProject : public IGisProject
 {
diff --git a/src/gis/gpx/CGpxProject.h b/src/gis/gpx/CGpxProject.h
index 6ff7899..d012f63 100644
--- a/src/gis/gpx/CGpxProject.h
+++ b/src/gis/gpx/CGpxProject.h
@@ -19,7 +19,7 @@
 #ifndef CGPXPROJECT_H
 #define CGPXPROJECT_H
 
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 
 #include <QDomElement>
 #include <QDateTime>
diff --git a/src/gis/gpx/serialization.cpp b/src/gis/gpx/serialization.cpp
index 7028828..817f340 100644
--- a/src/gis/gpx/serialization.cpp
+++ b/src/gis/gpx/serialization.cpp
@@ -16,7 +16,7 @@
 
 **********************************************************************************************/
 
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/wpt/CGisItemWpt.h"
 #include "gis/trk/CGisItemTrk.h"
 #include "gis/rte/CGisItemRte.h"
@@ -453,7 +453,7 @@ void CGisItemWpt::readGpx(const QDomNode& xml)
     if(xml.namedItem("extensions").isElement())
     {
         const QDomNode& ext = xml.namedItem("extensions");
-        readXml(ext, "ql:key", key);
+        readXml(ext, "ql:key", key.item);
         readXml(ext, "ql:flags", flags);
         readXml(ext, history);
 
@@ -485,7 +485,7 @@ void CGisItemWpt::save(QDomNode& gpx)
     // write the key as extension tag
     QDomElement xmlExt  = doc.createElement("extensions");
     xmlWpt.appendChild(xmlExt);
-    writeXml(xmlExt, "ql:key", key);
+    writeXml(xmlExt, "ql:key", key.item);
     writeXml(xmlExt, "ql:flags", flags);
     writeXml(xmlExt, history);
 
@@ -664,7 +664,7 @@ void CGisItemTrk::readTrk(const QDomNode& xml, trk_t& trk)
     const QDomNode& ext = xml.namedItem("extensions");
     if(ext.isElement())
     {
-        readXml(ext, "ql:key", key);
+        readXml(ext, "ql:key", key.item);
         readXml(ext, "ql:flags", flags);
         readXml(ext, history);
 
@@ -695,7 +695,7 @@ void CGisItemTrk::save(QDomNode& gpx)
     // write the key as extension tag
     QDomElement xmlExt  = doc.createElement("extensions");
     xmlTrk.appendChild(xmlExt);
-    writeXml(xmlExt, "ql:key", key);
+    writeXml(xmlExt, "ql:key", key.item);
     writeXml(xmlExt, "ql:flags", flags);
     writeXml(xmlExt, history);
 
@@ -760,7 +760,7 @@ void CGisItemRte::readRte(const QDomNode& xml, rte_t& rte)
     if(xml.namedItem("extensions").isElement())
     {
         const QDomNode& ext = xml.namedItem("extensions");
-        readXml(ext, "ql:key", key);
+        readXml(ext, "ql:key", key.item);
     }
 }
 
@@ -783,7 +783,7 @@ void CGisItemRte::save(QDomNode& gpx)
     // write the key as extension tag
     QDomElement xmlExt  = doc.createElement("extensions");
     xmlRte.appendChild(xmlExt);
-    writeXml(xmlExt, "ql:key", key);
+    writeXml(xmlExt, "ql:key", key.item);
 
     foreach(const rtept_t& pt, rte.pts)
     {
@@ -807,7 +807,7 @@ void CGisItemOvlArea::readArea(const QDomNode& xml, area_t& area)
     readXml(xml, "ql:width", area.width);
     readXml(xml, "ql:style", area.style);
     readXml(xml, "ql:opacity", area.opacity);
-    readXml(xml, "ql:key", key);
+    readXml(xml, "ql:key", key.item);
     readXml(xml, "ql:flags", flags);
     readXml(xml, history);
 
@@ -847,7 +847,7 @@ void CGisItemOvlArea::save(QDomNode& gpx)
     writeXml(xmlArea, "ql:width", area.width);
     writeXml(xmlArea, "ql:style", area.style);
     writeXml(xmlArea, "ql:opacity", area.opacity);
-    writeXml(xmlArea, "ql:key", key);
+    writeXml(xmlArea, "ql:key", key.item);
     writeXml(xmlArea, "ql:flags", flags);
     writeXml(xmlArea, history);
 
diff --git a/src/gis/ovl/CGisItemOvlArea.cpp b/src/gis/ovl/CGisItemOvlArea.cpp
index 117d7f6..dbf3e7e 100644
--- a/src/gis/ovl/CGisItemOvlArea.cpp
+++ b/src/gis/ovl/CGisItemOvlArea.cpp
@@ -19,8 +19,9 @@
 #include "gis/ovl/CGisItemOvlArea.h"
 #include "gis/ovl/CScrOptOvlArea.h"
 #include "gis/ovl/CDetailsOvlArea.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/CGisDraw.h"
+#include "GeoMath.h"
 
 #include <QtWidgets>
 #include <proj_api.h>
@@ -110,7 +111,7 @@ const Qt::BrushStyle CGisItemOvlArea::brushStyles[OVL_N_STYLES] =
 };
 
 
-QString CGisItemOvlArea::keyUserFocus;
+IGisItem::key_t CGisItemOvlArea::keyUserFocus;
 
 CGisItemOvlArea::CGisItemOvlArea(const QPolygonF& line, const QString &name, IGisProject * project, int idx)
     : IGisItem(project, eTypeOvl, idx)
@@ -130,15 +131,12 @@ CGisItemOvlArea::CGisItemOvlArea(const QPolygonF& line, const QString &name, IGi
 }
 
 CGisItemOvlArea::CGisItemOvlArea(const CGisItemOvlArea& parentArea, IGisProject * project, int idx)
-    : IGisItem(project, eTypeTrk, idx)
+    : IGisItem(project, eTypeOvl, idx)
     , penForeground(Qt::blue, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)
     , penBackground(Qt::white, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)
 {
     *this = parentArea;
 
-    key.clear();
-    genKey();
-
     setupHistory();
     updateDecoration(eMarkChanged, eMarkNone);
 }
@@ -260,6 +258,32 @@ void CGisItemOvlArea::deriveSecondaryData()
     }
 
     boundingRect = QRectF(QPointF(west * DEG_TO_RAD, north * DEG_TO_RAD), QPointF(east * DEG_TO_RAD,south * DEG_TO_RAD));
+
+    QPolygonF line(area.pts.size());
+    for(int i = 1; i < area.pts.size(); i++)
+    {
+        qreal a1, a2, d;
+        const pt_t& pt11 = area.pts[i - 1];
+        const pt_t& pt12 = area.pts[i];
+
+        QPointF& pt21    = line[i - 1];
+        QPointF& pt22    = line[i];
+
+        d = GPS_Math_Distance(pt11.lon * DEG_TO_RAD, pt11.lat * DEG_TO_RAD, pt12.lon * DEG_TO_RAD, pt12.lat * DEG_TO_RAD, a1, a2);
+
+        pt22.rx() = pt21.x() + cos(a1 * DEG_TO_RAD) * d;
+        pt22.ry() = pt21.y() + sin(a1 * DEG_TO_RAD) * d;
+    }
+
+    area.area = 0;
+    int j = line.size() - 1;
+    for(int i = 0; i < line.size(); i++)
+    {
+        area.area += (line[j].x() + line[i].x())*(line[j].y() - line[i].y());
+        j = i;
+    }
+
+    area.area = qAbs(area.area/2);
 }
 
 void CGisItemOvlArea::drawItem(QPainter& p, const QRectF& viewport, QList<QRectF>& blockedAreas, CGisDraw * gis)
@@ -326,7 +350,7 @@ void CGisItemOvlArea::drawHighlight(QPainter& p)
 
 void CGisItemOvlArea::gainUserFocus(bool yes)
 {
-    keyUserFocus = yes ? key : "";
+    keyUserFocus = yes ? key : key_t();
 }
 
 QPointF CGisItemOvlArea::getPolygonCentroid(const QPolygonF& polygon)
@@ -363,8 +387,12 @@ const QString& CGisItemOvlArea::getName()
 
 QString CGisItemOvlArea::getInfo()
 {
+    QString unit, val;
     QString str = getName();
 
+    IUnit::self().meter2area(area.area, val, unit);
+    str += "\n" + QObject::tr("Area: %1%2").arg(val).arg(unit);
+
     QString desc = removeHtml(area.desc).simplified();
     if(desc.count())
     {
diff --git a/src/gis/ovl/CGisItemOvlArea.h b/src/gis/ovl/CGisItemOvlArea.h
index f595b5e..e47b3ed 100644
--- a/src/gis/ovl/CGisItemOvlArea.h
+++ b/src/gis/ovl/CGisItemOvlArea.h
@@ -115,6 +115,9 @@ class CGisItemOvlArea : public IGisItem, public IGisLine
             qint32 width;
             qint32 style;
             bool opacity;
+
+            // secondary data;
+            qreal area;
         };
 
         const area_t& getAreaData() const{return area;}
@@ -129,7 +132,8 @@ class CGisItemOvlArea : public IGisItem, public IGisLine
 
         area_t area;
 
-        static QString keyUserFocus;
+
+        static key_t keyUserFocus;
 
         QPen penForeground;
         QPen penBackground;
diff --git a/src/gis/ovl/CScrOptOvlArea.cpp b/src/gis/ovl/CScrOptOvlArea.cpp
index 874db8f..5d40359 100644
--- a/src/gis/ovl/CScrOptOvlArea.cpp
+++ b/src/gis/ovl/CScrOptOvlArea.cpp
@@ -24,10 +24,10 @@
 #include "CMainWindow.h"
 
 CScrOptOvlArea::CScrOptOvlArea(CGisItemOvlArea *area, const QPoint &point, IMouse *parent)
-    : IScrOpt(parent->getCanvas())
-    , key(area->getKey())
-
+    : IScrOpt(parent->getCanvas())    
 {
+    key = area->getKey();
+
     setupUi(this);
     setOrigin(point);
     label->setFont(CMainWindow::self().getMapFont());
diff --git a/src/gis/ovl/CScrOptOvlArea.h b/src/gis/ovl/CScrOptOvlArea.h
index 6b2d37f..12a740d 100644
--- a/src/gis/ovl/CScrOptOvlArea.h
+++ b/src/gis/ovl/CScrOptOvlArea.h
@@ -20,6 +20,8 @@
 #define CSCROPTOVLAREA_H
 
 #include "mouse/IScrOpt.h"
+#include "gis/IGisItem.h"
+
 #include "ui_IScrOptOvlArea.h"
 
 class CGisItemOvlArea;
@@ -40,7 +42,7 @@ class CScrOptOvlArea : public IScrOpt, private Ui::IScrOptOvlArea
         void slotEdit();
 
     private:
-        QString key;
+        IGisItem::key_t key;
         QPointF anchor;
 
 };
diff --git a/src/gis/prj/CDetailsPrj.cpp b/src/gis/prj/CDetailsPrj.cpp
new file mode 100644
index 0000000..1e38c13
--- /dev/null
+++ b/src/gis/prj/CDetailsPrj.cpp
@@ -0,0 +1,122 @@
+/**********************************************************************************************
+    Copyright (C) 2014 Oliver Eichler oliver.eichler at gmx.de
+
+    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 3 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, see <http://www.gnu.org/licenses/>.
+
+**********************************************************************************************/
+
+#include "gis/prj/CDetailsPrj.h"
+#include "gis/prj/IGisProject.h"
+#include "gis/IGisItem.h"
+#include "helpers/CTextEditWidget.h"
+#include "helpers/CLinksDialog.h"
+
+#include <QtWidgets>
+
+CDetailsPrj::CDetailsPrj(IGisProject &prj, QWidget *parent)
+    : QWidget(parent)
+    , prj(prj)
+{
+    setupUi(this);
+    setupGui();
+
+    connect(labelName, SIGNAL(linkActivated(QString)), this, SLOT(slotLinkActivated(QString)));
+    connect(labelKeywords, SIGNAL(linkActivated(QString)), this, SLOT(slotLinkActivated(QString)));
+    connect(textDesc, SIGNAL(anchorClicked(QUrl)), this, SLOT(slotLinkActivated(QUrl)));
+}
+
+CDetailsPrj::~CDetailsPrj()
+{
+
+}
+
+void CDetailsPrj::setupGui()
+{
+    bool isReadOnly = false;
+
+    setWindowTitle(prj.getName());
+
+    labelName->setText(IGisItem::toLink(isReadOnly, "name", prj.getName()));
+    labelTime->setText(IUnit::datetime2string(prj.getTime(), false));
+
+    QString keywords = prj.getKeywords();
+    if(keywords.isEmpty())
+    {
+        keywords = tr("none");
+    }
+    labelKeywords->setText(IGisItem::toLink(isReadOnly, "keywords", keywords));
+
+    textDesc->document()->clear();
+    textDesc->append(IGisItem::createText(isReadOnly, prj.getDescription(), prj.getLinks()));
+    textDesc->moveCursor(QTextCursor::Start) ;
+    textDesc->ensureCursorVisible() ;
+}
+
+void CDetailsPrj::slotLinkActivated(const QString& link)
+{
+    if(link == "name")
+    {
+        QString name = QInputDialog::getText(0, tr("Edit name..."), tr("Enter new waypoint name."), QLineEdit::Normal, prj.getName());
+        if(name.isEmpty())
+        {
+            return;
+        }
+        prj.setName(name);
+    }
+    else if(link == "keywords")
+    {
+        QString keywords = QInputDialog::getText(0, tr("Edit keywords..."), tr("Enter keywords."), QLineEdit::Normal, prj.getKeywords());
+        if(keywords.isEmpty())
+        {
+            return;
+        }
+        if(keywords == tr("none"))
+        {
+            keywords.clear();
+        }
+        prj.setKeywords(keywords);
+    }
+    setupGui();
+}
+
+void CDetailsPrj::slotLinkActivated(const QUrl& url)
+{
+    if(url.toString() == "description")
+    {
+        CTextEditWidget dlg(0);
+        dlg.setHtml(prj.getDescription());
+        if(dlg.exec() == QDialog::Accepted)
+        {
+            prj.setDescription(dlg.getHtml());
+        }
+        setupGui();
+    }
+    else if(url.toString() == "links")
+    {
+        QList<IGisItem::link_t> links = prj.getLinks();
+        CLinksDialog dlg(links, 0);
+        if(dlg.exec() == QDialog::Accepted)
+        {
+            prj.setLinks(links);
+        }
+        setupGui();
+    }
+    else
+    {
+        QDesktopServices::openUrl(url);
+    }
+}
+
+
+
diff --git a/src/gis/rte/CScrOptRte.h b/src/gis/prj/CDetailsPrj.h
similarity index 68%
copy from src/gis/rte/CScrOptRte.h
copy to src/gis/prj/CDetailsPrj.h
index d3f6633..4e05aff 100644
--- a/src/gis/rte/CScrOptRte.h
+++ b/src/gis/prj/CDetailsPrj.h
@@ -16,33 +16,32 @@
 
 **********************************************************************************************/
 
-#ifndef CSCROPTRTE_H
-#define CSCROPTRTE_H
-
-#include "mouse/IScrOpt.h"
+#ifndef CDETAILSPRJ_H
+#define CDETAILSPRJ_H
 
 #include <QWidget>
-#include "ui_IScrOptRte.h"
+#include <QPointer>
+#include "ui_IDetailsPrj.h"
 
-class CGisItemRte;
-class IMouse;
+class CDetailsPrj;
+class IGisProject;
 
-class CScrOptRte : public IScrOpt, private Ui::IScrOptRte
+class CDetailsPrj : public QWidget, private Ui::IDetailsPrj
 {
     Q_OBJECT
     public:
-        CScrOptRte(CGisItemRte * rte, const QPoint &point, IMouse *parent);
-        virtual ~CScrOptRte();
-
-        void draw(QPainter& p);
+        CDetailsPrj(IGisProject& prj, QWidget * parent);
+        virtual ~CDetailsPrj();
 
     private slots:
-        void slotDelete();
+        void slotLinkActivated(const QString& link);
+        void slotLinkActivated(const QUrl& url);
 
     private:
-        QString key;
-        QPointF anchor;
+        void setupGui();
+
+        IGisProject& prj;
 };
 
-#endif //CSCROPTRTE_H
+#endif //CDETAILSPRJ_H
 
diff --git a/src/gis/prj/IDetailsPrj.ui b/src/gis/prj/IDetailsPrj.ui
new file mode 100644
index 0000000..717b050
--- /dev/null
+++ b/src/gis/prj/IDetailsPrj.ui
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>IDetailsPrj</class>
+ <widget class="QWidget" name="IDetailsPrj">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>795</width>
+    <height>511</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>3</number>
+   </property>
+   <property name="leftMargin">
+    <number>3</number>
+   </property>
+   <property name="topMargin">
+    <number>3</number>
+   </property>
+   <property name="rightMargin">
+    <number>3</number>
+   </property>
+   <property name="bottomMargin">
+    <number>3</number>
+   </property>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="labelName">
+       <property name="text">
+        <string>-</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="labelTime">
+       <property name="text">
+        <string>-</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Keywords:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="labelKeywords">
+       <property name="text">
+        <string>-</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QTextBrowser" name="textDesc">
+     <property name="openExternalLinks">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/gis/IGisProject.cpp b/src/gis/prj/IGisProject.cpp
similarity index 77%
rename from src/gis/IGisProject.cpp
rename to src/gis/prj/IGisProject.cpp
index efd3d79..0db35dc 100644
--- a/src/gis/IGisProject.cpp
+++ b/src/gis/prj/IGisProject.cpp
@@ -16,10 +16,13 @@
 
 **********************************************************************************************/
 
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
+#include "gis/prj/CDetailsPrj.h"
 #include "gis/IGisItem.h"
 #include "gis/CGisListWks.h"
 #include "gis/CGisDraw.h"
+#include "CMainWindow.h"
+
 
 #include <QtWidgets>
 
@@ -35,7 +38,7 @@ IGisProject::IGisProject(type_e type, const QString &filename, CGisListWks *pare
 
 IGisProject::~IGisProject()
 {
-
+    delete dlgDetails;
 }
 
 void IGisProject::genKey()
@@ -55,6 +58,49 @@ void IGisProject::genKey()
     }
 }
 
+
+void IGisProject::edit()
+{
+    if(dlgDetails.isNull())
+    {
+        dlgDetails = new CDetailsPrj(*this, 0);
+        dlgDetails->setObjectName(getName());
+    }
+
+    CMainWindow::self().addWidgetToTab(dlgDetails);
+}
+
+void IGisProject::setName(const QString& str)
+{
+    metadata.name = str;
+    setText(0, str);
+    changed();
+}
+
+void IGisProject::setKeywords(const QString& str)
+{
+    metadata.keywords = str;
+    changed();
+}
+
+void IGisProject::setDescription(const QString& str)
+{
+    metadata.desc = str;
+    changed();
+}
+
+void IGisProject::setLinks(const QList<IGisItem::link_t>& links)
+{
+    metadata.links = links;
+    changed();
+}
+
+void IGisProject::changed()
+{
+    setText(1,"*");
+}
+
+
 void IGisProject::setupName(const QString &defaultName)
 {
     if(metadata.name.isEmpty())
@@ -143,7 +189,7 @@ QString IGisProject::getInfo()
     return str;
 }
 
-IGisItem * IGisProject::getItemByKey(const QString& key)
+IGisItem * IGisProject::getItemByKey(const IGisItem::key_t& key)
 {
     for(int i = 0; i < childCount(); i++)
     {
@@ -181,7 +227,7 @@ void IGisProject::getItemByPos(const QPointF& pos, QList<IGisItem *> &items)
 }
 
 
-void IGisProject::delItemByKey(const QString& key)
+void IGisProject::delItemByKey(const IGisItem::key_t& key, QMessageBox::StandardButtons& last)
 {
     QList<QTreeWidgetItem*> items;
     for(int i = childCount(); i > 0; i--)
@@ -194,13 +240,15 @@ void IGisProject::delItemByKey(const QString& key)
 
         if(item->getKey() == key)
         {
-            QString msg = QObject::tr("Are you sure you want to delete '%1' from project '%2'?").arg(item->getName()).arg(text(0));
-            QMessageBox::StandardButtons res = QMessageBox::question(0, QObject::tr("Delete..."), msg, QMessageBox::Ok|QMessageBox::No, QMessageBox::Ok);
-            if(res != QMessageBox::Ok)
+            if(last != QMessageBox::YesToAll)
             {
-                continue;
+                QString msg = QObject::tr("Are you sure you want to delete '%1' from project '%2'?").arg(item->getName()).arg(text(0));
+                last = QMessageBox::question(0, QObject::tr("Delete..."), msg, QMessageBox::YesToAll|QMessageBox::Cancel|QMessageBox::Ok|QMessageBox::No, QMessageBox::Ok);
+                if((last == QMessageBox::No) || (last == QMessageBox::Cancel))
+                {
+                    continue;
+                }
             }
-
             items << takeChild(i-1);
             setText(1,"*");
         }
@@ -208,7 +256,7 @@ void IGisProject::delItemByKey(const QString& key)
     qDeleteAll(items);
 }
 
-void IGisProject::editItemByKey(const QString& key)
+void IGisProject::editItemByKey(const IGisItem::key_t& key)
 {
     for(int i = childCount(); i > 0; i--)
     {
@@ -240,11 +288,11 @@ void IGisProject::drawItem(QPainter& p, const QRectF& viewport, QList<QRectF>& b
             continue;
         }
 
-        if(seenKeys.contains(item->getKey()))
-        {
-            continue;
-        }
-        seenKeys << item->getKey();
+//        if(seenKeys.contains(item->getKey()))
+//        {
+//            continue;
+//        }
+//        seenKeys << item->getKey();
 
         item->drawItem(p, viewport, blockedAreas, gis);
     }
@@ -284,11 +332,11 @@ void IGisProject::drawLabel(QPainter& p, const QRectF& viewport, QList<QRectF>&
             continue;
         }
 
-        if(seenKeys.contains(item->getKey()))
-        {
-            continue;
-        }
-        seenKeys << item->getKey();
+//        if(seenKeys.contains(item->getKey()))
+//        {
+//            continue;
+//        }
+//        seenKeys << item->getKey();
 
         item->drawLabel(p, viewport, blockedAreas, fm, gis);
     }
diff --git a/src/gis/IGisProject.h b/src/gis/prj/IGisProject.h
similarity index 86%
rename from src/gis/IGisProject.h
rename to src/gis/prj/IGisProject.h
index de68e04..21910f7 100644
--- a/src/gis/IGisProject.h
+++ b/src/gis/prj/IGisProject.h
@@ -21,12 +21,14 @@
 
 #include "gis/IGisItem.h"
 #include <QTreeWidgetItem>
-
+#include <QPointer>
+#include <QMessageBox>
 
 class CGisListWks;
 class IGisItem;
 class CGisDraw;
 class QDataStream;
+class CDetailsPrj;
 
 class IGisProject : public QTreeWidgetItem
 {
@@ -72,6 +74,8 @@ class IGisProject : public QTreeWidgetItem
         IGisProject(type_e type, const QString& filename, CGisListWks * parent);
         virtual ~IGisProject();
 
+        void edit();
+
         virtual void save() = 0;
         virtual void saveAs() = 0;
 
@@ -85,6 +89,17 @@ class IGisProject : public QTreeWidgetItem
            @return A MD5 hash string
          */
         const QString& getKey(){genKey(); return key;}
+        const QString& getName(){return metadata.name;}
+        const QDateTime& getTime(){return metadata.time;}
+        const QString& getKeywords(){return metadata.keywords;}
+        const QString& getDescription(){return metadata.desc;}
+        const QList<IGisItem::link_t>& getLinks(){return metadata.links;}
+
+
+        void setName(const QString& str);
+        void setKeywords(const QString& str);
+        void setDescription(const QString& str);
+        void setLinks(const QList<IGisItem::link_t>& links);
 
         /**
            @brief Get a short metadata summary
@@ -96,7 +111,7 @@ class IGisProject : public QTreeWidgetItem
            @param key
            @return If no item is found 0 is returned.
         */
-        IGisItem * getItemByKey(const QString& key);
+        IGisItem * getItemByKey(const IGisItem::key_t &key);
 
         /**
            @brief Get a list of items that are close to a given pixel coordinate of the screen
@@ -112,14 +127,14 @@ class IGisProject : public QTreeWidgetItem
            @brief Delete items with matching key
            @param key
         */
-        void delItemByKey(const QString& key);
+        void delItemByKey(const IGisItem::key_t &key, QMessageBox::StandardButtons &last);
 
         /**
            @brief Call IGisItem::edit() method for items with given key
 
            @param key   a MD5 hash key
          */
-        void editItemByKey(const QString& key);
+        void editItemByKey(const IGisItem::key_t &key);
 
         /**
            @brief Check if the project was initialized correctly.
@@ -166,6 +181,7 @@ class IGisProject : public QTreeWidgetItem
         void setupName(const QString& defaultName);
         void markAsSaved();
         void readMetadata(const QDomNode& xml, metadata_t& metadata);
+        void changed();
 
         // Those are the URIs of the GPX extensions we support
         static const QString gpxx_ns;
@@ -185,6 +201,8 @@ class IGisProject : public QTreeWidgetItem
 
         metadata_t metadata;
 
+        QPointer<CDetailsPrj> dlgDetails;
+
 };
 
 #endif //IGISPROJECT_H
diff --git a/src/gis/qms/CQmsProject.h b/src/gis/qms/CQmsProject.h
index 14a8fb2..0ffc628 100644
--- a/src/gis/qms/CQmsProject.h
+++ b/src/gis/qms/CQmsProject.h
@@ -19,7 +19,7 @@
 #ifndef CQMSPROJECT_H
 #define CQMSPROJECT_H
 
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 
 class CQmsProject : public IGisProject
 {
diff --git a/src/gis/qms/serialization.cpp b/src/gis/qms/serialization.cpp
index 375c5b3..34a03ce 100644
--- a/src/gis/qms/serialization.cpp
+++ b/src/gis/qms/serialization.cpp
@@ -16,7 +16,7 @@
 
 **********************************************************************************************/
 
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/trk/CGisItemTrk.h"
 #include "gis/wpt/CGisItemWpt.h"
 #include "gis/rte/CGisItemRte.h"
@@ -358,7 +358,7 @@ QDataStream& CGisItemTrk::operator>>(QDataStream& stream)
     out.setByteOrder(QDataStream::LittleEndian);
     out.setVersion(QDataStream::Qt_5_2);
 
-    out << key;
+    out << key.item;
     out << flags;
     out << trk.name;
     out << trk.cmt;
@@ -400,7 +400,7 @@ QDataStream& CGisItemTrk::operator<<(QDataStream& stream)
     in.setByteOrder(QDataStream::LittleEndian);
     in.setVersion(QDataStream::Qt_5_2);
 
-    in >> key;
+    in >> key.item;
     in >> flags;
     in >> trk.name;
     in >> trk.cmt;
@@ -446,7 +446,7 @@ QDataStream& CGisItemWpt::operator<<(QDataStream& stream)
     in.setByteOrder(QDataStream::LittleEndian);
     in.setVersion(QDataStream::Qt_5_2);
 
-    in >> key;
+    in >> key.item;
     in >> flags;
     in >> proximity;
     in >> wpt;
@@ -467,7 +467,7 @@ QDataStream& CGisItemWpt::operator>>(QDataStream& stream)
     out.setByteOrder(QDataStream::LittleEndian);
     out.setVersion(QDataStream::Qt_5_2);
 
-    out << key;
+    out << key.item;
     out << flags;
     out << proximity;
     out << wpt;
@@ -516,7 +516,7 @@ QDataStream& CGisItemOvlArea::operator<<(QDataStream& stream)
     in.setByteOrder(QDataStream::LittleEndian);
     in.setVersion(QDataStream::Qt_5_2);
 
-    in >> key;
+    in >> key.item;
     in >> flags;
     in >> area.name;
     in >> area.cmt;
@@ -547,7 +547,7 @@ QDataStream& CGisItemOvlArea::operator>>(QDataStream& stream)
     out.setByteOrder(QDataStream::LittleEndian);
     out.setVersion(QDataStream::Qt_5_2);
 
-    out << key;
+    out << key.item;
     out << flags;
     out << area.name;
     out << area.cmt;
diff --git a/src/gis/rte/CGisItemRte.cpp b/src/gis/rte/CGisItemRte.cpp
index 2bbb4ec..2fb2930 100644
--- a/src/gis/rte/CGisItemRte.cpp
+++ b/src/gis/rte/CGisItemRte.cpp
@@ -18,7 +18,7 @@
 
 #include "gis/rte/CGisItemRte.h"
 #include "gis/rte/CScrOptRte.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/WptIcons.h"
 #include "gis/CGisDraw.h"
 #include "canvas/CCanvas.h"
@@ -28,7 +28,7 @@
 #include <proj_api.h>
 
 const QPen CGisItemRte::penBackground(Qt::white, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
-QString CGisItemRte::keyUserFocus;
+IGisItem::key_t CGisItemRte::keyUserFocus;
 
 /// used to create a copy of route with new parent
 CGisItemRte::CGisItemRte(const CGisItemRte& parentRte, IGisProject * project, int idx)
@@ -37,9 +37,6 @@ CGisItemRte::CGisItemRte(const CGisItemRte& parentRte, IGisProject * project, in
 {
     *this = parentRte;
 
-    key.clear();
-    genKey();
-
     setupHistory();
     updateDecoration(eMarkChanged, eMarkNone);
 }
@@ -127,7 +124,7 @@ bool CGisItemRte::isCloseTo(const QPointF& pos)
 
 void CGisItemRte::gainUserFocus(bool yes)
 {
-    keyUserFocus = yes ? key : "";
+    keyUserFocus = yes ? key : key_t();
 }
 
 
diff --git a/src/gis/rte/CGisItemRte.h b/src/gis/rte/CGisItemRte.h
index 4b8cc45..1c47b56 100644
--- a/src/gis/rte/CGisItemRte.h
+++ b/src/gis/rte/CGisItemRte.h
@@ -57,7 +57,7 @@ class CGisItemRte : public IGisItem, public IGisLine
         void setSymbol();
         void readRte(const QDomNode& xml, rte_t& rte);
 
-        static QString keyUserFocus;
+        static key_t keyUserFocus;
 
         struct rtept_t : public wpt_t
         {
diff --git a/src/gis/rte/CScrOptRte.cpp b/src/gis/rte/CScrOptRte.cpp
index 63610cd..1b64362 100644
--- a/src/gis/rte/CScrOptRte.cpp
+++ b/src/gis/rte/CScrOptRte.cpp
@@ -25,8 +25,10 @@
 
 CScrOptRte::CScrOptRte(CGisItemRte *rte, const QPoint& point, IMouse *parent)
     : IScrOpt(parent->getCanvas())
-    , key(rte->getKey())
+
 {
+    key = rte->getKey();
+
     setupUi(this);
     setOrigin(point);
     label->setFont(CMainWindow::self().getMapFont());
diff --git a/src/gis/rte/CScrOptRte.h b/src/gis/rte/CScrOptRte.h
index d3f6633..43c9286 100644
--- a/src/gis/rte/CScrOptRte.h
+++ b/src/gis/rte/CScrOptRte.h
@@ -20,6 +20,7 @@
 #define CSCROPTRTE_H
 
 #include "mouse/IScrOpt.h"
+#include "gis/IGisItem.h"
 
 #include <QWidget>
 #include "ui_IScrOptRte.h"
@@ -40,7 +41,7 @@ class CScrOptRte : public IScrOpt, private Ui::IScrOptRte
         void slotDelete();
 
     private:
-        QString key;
+        IGisItem::key_t key;
         QPointF anchor;
 };
 
diff --git a/src/gis/search/CSearchGoogle.h b/src/gis/search/CSearchGoogle.h
index 49f9396..e541d87 100644
--- a/src/gis/search/CSearchGoogle.h
+++ b/src/gis/search/CSearchGoogle.h
@@ -19,7 +19,7 @@
 #ifndef CSEARCHGOOGLE_H
 #define CSEARCHGOOGLE_H
 
-#include <gis/IGisProject.h>
+#include <gis/prj/IGisProject.h>
 
 #include <QObject>
 #include <QNetworkAccessManager>
diff --git a/src/gis/trk/CCombineTrk.cpp b/src/gis/trk/CCombineTrk.cpp
index ecbc535..71ed329 100644
--- a/src/gis/trk/CCombineTrk.cpp
+++ b/src/gis/trk/CCombineTrk.cpp
@@ -18,7 +18,7 @@
 
 #include "gis/trk/CCombineTrk.h"
 #include "gis/trk/CGisItemTrk.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "plot/CPlotTrack.h"
 
 #include <QtWidgets>
@@ -44,16 +44,20 @@ CCombineTrk::CCombineTrk(CGisItemTrk& trk, IGisProject& project, QWidget * paren
             continue;
         }
 
+        const IGisItem::key_t& key = trk1->getKey();
         QListWidgetItem * item = new QListWidgetItem(listAvailable);
         item->setText(trk1->getName());
         item->setIcon(trk1->getIcon());
-        item->setData(Qt::UserRole, trk1->getKey());
+        item->setData(Qt::UserRole + 1, key.item);
+        item->setData(Qt::UserRole + 2, key.project);
     }
 
+    const IGisItem::key_t& key = trk.getKey();
     QListWidgetItem * item = new QListWidgetItem(listSelected);
     item->setText(trk.getName());
     item->setIcon(trk.getIcon());
-    item->setData(Qt::UserRole, trk.getKey());
+    item->setData(Qt::UserRole + 1, key.item);
+    item->setData(Qt::UserRole + 2, key.project);
 
     connect(listAvailable, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()));
     connect(listSelected, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()));
@@ -79,7 +83,9 @@ void CCombineTrk::accept()
 {
     for(int i = 0; i < listSelected->count(); i++)
     {
-        QString key = listSelected->item(i)->data(Qt::UserRole).toString();
+        IGisItem::key_t key;
+        key.item    = listSelected->item(i)->data(Qt::UserRole + 1).toString();
+        key.project = listSelected->item(i)->data(Qt::UserRole + 2).toString();
         CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(project.getItemByKey(key));
         if(trk1 == 0)
         {
@@ -139,11 +145,21 @@ void CCombineTrk::slotRemove()
     QListWidgetItem * item;
     item = listSelected->currentItem();
 
-    if((item == 0) || (item->data(Qt::UserRole).toString() == trk.getKey()))
+    if(item == 0)
+    {
+        return;
+    }
+
+    IGisItem::key_t key;
+    key.item    = item->data(Qt::UserRole + 1).toString();
+    key.project = item->data(Qt::UserRole + 2).toString();
+
+    if(key == trk.getKey())
     {
         return;
     }
 
+
     listSelected->takeItem(listSelected->row(item));
     listAvailable->addItem(item);
 
@@ -187,8 +203,12 @@ void CCombineTrk::updatePreview()
 {
     QPolygonF line;
     for(int i = 0; i < listSelected->count(); i++)
-    {
-        QString key = listSelected->item(i)->data(Qt::UserRole).toString();
+    {      
+        IGisItem::key_t key;
+        key.item    = listSelected->item(i)->data(Qt::UserRole + 1).toString();
+        key.project = listSelected->item(i)->data(Qt::UserRole + 2).toString();
+
+
         CGisItemTrk * trk1 = dynamic_cast<CGisItemTrk*>(project.getItemByKey(key));
         if(trk1 == 0)
         {
diff --git a/src/gis/trk/CCombineTrk.h b/src/gis/trk/CCombineTrk.h
index ff434d8..5d77032 100644
--- a/src/gis/trk/CCombineTrk.h
+++ b/src/gis/trk/CCombineTrk.h
@@ -20,6 +20,7 @@
 #define CCOMBINETRK_H
 
 #include <QDialog>
+#include "gis/IGisItem.h"
 #include "ui_ICombineTrk.h"
 
 class CGisItemTrk;
@@ -32,7 +33,7 @@ class CCombineTrk : public QDialog, private Ui::ICombineTrk
         CCombineTrk(CGisItemTrk& trk, IGisProject &project, QWidget * parent);
         virtual ~CCombineTrk();
 
-        const QStringList& getTrackKeys(){return keys;}
+        const QList<IGisItem::key_t>& getTrackKeys(){return keys;}
 
     public slots:
         void accept();
@@ -49,7 +50,7 @@ class CCombineTrk : public QDialog, private Ui::ICombineTrk
         CGisItemTrk& trk;
         IGisProject& project;
 
-        QStringList keys;
+        QList<IGisItem::key_t> keys;
 };
 
 #endif //CCOMBINETRK_H
diff --git a/src/gis/trk/CGisItemTrk.cpp b/src/gis/trk/CGisItemTrk.cpp
index e3d1e68..fb453e4 100644
--- a/src/gis/trk/CGisItemTrk.cpp
+++ b/src/gis/trk/CGisItemTrk.cpp
@@ -20,7 +20,7 @@
 #include "GeoMath.h"
 #include "gis/CGisDraw.h"
 #include "gis/CGisWidget.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/trk/CCombineTrk.h"
 #include "gis/trk/CDetailsTrk.h"
 #include "gis/trk/CGisItemTrk.h"
@@ -98,7 +98,7 @@ const QString CGisItemTrk::bulletColors[TRK_N_COLORS] =
 
 const QPen CGisItemTrk::penBackground(Qt::white, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
 
-QString CGisItemTrk::keyUserFocus;
+IGisItem::key_t CGisItemTrk::keyUserFocus;
 
 /// used to create a new track from a part of an existing track
 CGisItemTrk::CGisItemTrk(const QString &name, qint32 idx1, qint32 idx2, const trk_t& srctrk, IGisProject * project)
@@ -158,8 +158,6 @@ CGisItemTrk::CGisItemTrk(const CGisItemTrk& parentTrk, IGisProject *project, int
 {
     *this = parentTrk;
 
-    key.clear();
-    genKey();
     setupHistory();
     updateDecoration(eMarkChanged, eMarkNone);
 }
@@ -771,7 +769,8 @@ bool CGisItemTrk::isCloseTo(const QPointF& pos)
 
 void CGisItemTrk::gainUserFocus(bool yes)
 {
-    keyUserFocus = yes ? key : "";
+    keyUserFocus    = yes ? key : key_t();
+
 }
 
 void CGisItemTrk::edit()
@@ -863,7 +862,7 @@ void CGisItemTrk::combine()
     CCombineTrk dlg(*this, *project, 0);
     dlg.exec();
 
-    QStringList keys = dlg.getTrackKeys();
+    QList<IGisItem::key_t> keys = dlg.getTrackKeys();
     if(keys.isEmpty())
     {
         return;
@@ -879,7 +878,7 @@ void CGisItemTrk::combine()
 
     trk1->trk.name = name1;
     trk1->trk.segs.clear();
-    foreach(const QString &key, keys)
+    foreach(const IGisItem::key_t &key, keys)
     {
         CGisItemTrk * trk2 = dynamic_cast<CGisItemTrk*>(project->getItemByKey(key));
         if(trk2 == 0)
@@ -1223,7 +1222,7 @@ void CGisItemTrk::drawLabel(QPainter& p, const QRectF& viewport, QList<QRectF> &
 
 void CGisItemTrk::drawHighlight(QPainter& p)
 {
-    if(lineSimple.isEmpty() || key == keyUserFocus)
+    if(lineSimple.isEmpty() || (key == keyUserFocus))
     {
         return;
     }
diff --git a/src/gis/trk/CGisItemTrk.h b/src/gis/trk/CGisItemTrk.h
index 361bf6b..ff797f4 100644
--- a/src/gis/trk/CGisItemTrk.h
+++ b/src/gis/trk/CGisItemTrk.h
@@ -167,7 +167,7 @@ class CGisItemTrk : public IGisItem, public IGisLine
 
            @return If no track has the focus an empty string is returned
          */
-        static const QString& getKeyUserFocus(){return keyUserFocus;}
+        static const key_t& getKeyUserFocus(){return keyUserFocus;}
 
         /**
            @brief Each plot widget that operates on the track must register during it's contruction
@@ -361,7 +361,7 @@ class CGisItemTrk : public IGisItem, public IGisLine
     private:
         trk_t trk;
 
-        static QString keyUserFocus;
+        static key_t keyUserFocus;
         static const QPen penBackground;
 
         QPen penForeground;
diff --git a/src/gis/trk/CScrOptTrk.cpp b/src/gis/trk/CScrOptTrk.cpp
index b504ba7..de120c1 100644
--- a/src/gis/trk/CScrOptTrk.cpp
+++ b/src/gis/trk/CScrOptTrk.cpp
@@ -25,8 +25,9 @@
 
 CScrOptTrk::CScrOptTrk(CGisItemTrk * trk, const QPoint& point, IMouse *parent)
     : IScrOpt(parent->getCanvas())
-    , key(trk->getKey())
 {
+    key         = trk->getKey();
+
     setupUi(this);    
     setOrigin(point);
     label->setFont(CMainWindow::self().getMapFont());
diff --git a/src/gis/trk/CScrOptTrk.h b/src/gis/trk/CScrOptTrk.h
index 5ac73d2..355c3c3 100644
--- a/src/gis/trk/CScrOptTrk.h
+++ b/src/gis/trk/CScrOptTrk.h
@@ -20,6 +20,7 @@
 #define CSCROPTTRK_H
 
 #include "mouse/IScrOpt.h"
+#include "gis/IGisItem.h"
 #include "ui_IScrOptTrk.h"
 
 class CGisItemTrk;
@@ -46,7 +47,7 @@ class CScrOptTrk : public IScrOpt, private Ui::IScrOptTrk
 
 
     private:
-        QString key;
+        IGisItem::key_t key;
         QPointF anchor;
 };
 
diff --git a/src/gis/wpt/CGisItemWpt.cpp b/src/gis/wpt/CGisItemWpt.cpp
index 7719d33..8cca197 100644
--- a/src/gis/wpt/CGisItemWpt.cpp
+++ b/src/gis/wpt/CGisItemWpt.cpp
@@ -20,7 +20,7 @@
 #include "gis/wpt/CDetailsWpt.h"
 #include "gis/wpt/CDetailsGeoCache.h"
 #include "gis/wpt/CScrOptWpt.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "gis/CGisDraw.h"
 #include "gis/WptIcons.h"
 #include "gis/CGisListWks.h"
@@ -36,7 +36,7 @@
 #include <QtWidgets>
 #include <QtXml>
 
-QString CGisItemWpt::keyUserFocus;
+IGisItem::key_t CGisItemWpt::keyUserFocus;
 QString CGisItemWpt::lastName;
 QString CGisItemWpt::lastIcon;
 
@@ -96,8 +96,6 @@ CGisItemWpt::CGisItemWpt(const CGisItemWpt &parentWpt, IGisProject *project, int
 {
     *this = parentWpt;
 
-    key.clear();
-    genKey();
     setupHistory();
     updateDecoration(eMarkChanged, eMarkNone);
 }
@@ -346,7 +344,7 @@ bool CGisItemWpt::isCloseTo(const QPointF& pos)
 
 void CGisItemWpt::gainUserFocus(bool yes)
 {
-    keyUserFocus = yes ? key : "";
+    keyUserFocus = yes ? key : key_t();
 }
 
 void CGisItemWpt::edit()
diff --git a/src/gis/wpt/CGisItemWpt.h b/src/gis/wpt/CGisItemWpt.h
index 35aeba0..2bdcd62 100644
--- a/src/gis/wpt/CGisItemWpt.h
+++ b/src/gis/wpt/CGisItemWpt.h
@@ -166,7 +166,7 @@ class CGisItemWpt : public IGisItem
         void readGcExt(const QDomNode& xmlCache);
         void writeGcExt(QDomNode& xmlCache);
 
-        static QString keyUserFocus;
+        static key_t keyUserFocus;
         static QString lastName;
         static QString lastIcon;
 
diff --git a/src/gis/wpt/CProjWpt.cpp b/src/gis/wpt/CProjWpt.cpp
index f6a8190..e613b92 100644
--- a/src/gis/wpt/CProjWpt.cpp
+++ b/src/gis/wpt/CProjWpt.cpp
@@ -19,7 +19,7 @@
 #include "gis/wpt/CProjWpt.h"
 #include "gis/wpt/CGisItemWpt.h"
 #include "helpers/CWptIconDialog.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "units/IUnit.h"
 #include "GeoMath.h"
 #include "CMainWindow.h"
diff --git a/src/gis/wpt/CScrOptWpt.cpp b/src/gis/wpt/CScrOptWpt.cpp
index 84f7c8f..c9687ec 100644
--- a/src/gis/wpt/CScrOptWpt.cpp
+++ b/src/gis/wpt/CScrOptWpt.cpp
@@ -28,9 +28,10 @@
 #include <QtWidgets>
 
 CScrOptWpt::CScrOptWpt(CGisItemWpt *wpt, const QPoint& point, IMouse *parent)
-    : IScrOpt(parent->getCanvas())
-    , key(wpt->getKey())
+    : IScrOpt(parent->getCanvas())    
 {
+    key         = wpt->getKey();
+
     setupUi(this);
     setOrigin(point);
     label->setFont(CMainWindow::self().getMapFont());
diff --git a/src/gis/wpt/CScrOptWpt.h b/src/gis/wpt/CScrOptWpt.h
index 4c25445..6b12523 100644
--- a/src/gis/wpt/CScrOptWpt.h
+++ b/src/gis/wpt/CScrOptWpt.h
@@ -20,6 +20,7 @@
 #define CSCROPTWPT_H
 
 #include "mouse/IScrOpt.h"
+#include "gis/IGisItem.h"
 
 #include <QWidget>
 #include "ui_IScrOptWpt.h"
@@ -43,7 +44,7 @@ class CScrOptWpt : public IScrOpt , private Ui::IScrOptWpt
         void slotProj();
 
     private:
-        QString key;
+        IGisItem::key_t key;
         QPointF anchor;
 };
 
diff --git a/src/grid/CGrid.cpp b/src/grid/CGrid.cpp
index a134a4f..f0b582d 100644
--- a/src/grid/CGrid.cpp
+++ b/src/grid/CGrid.cpp
@@ -55,10 +55,11 @@ void CGrid::convertPos2Str(const QPointF& pos, QString& info)
 
     if(pj_is_latlong(pjGrid))
     {
-        QString str;
+        QString lat,lng;
         pt *= RAD_TO_DEG;
-        GPS_Math_Deg_To_Str(pt.x(), pt.y(), str);
-        info += tr("[Grid: %1] ").arg(str);
+        lat = pt.y() < 0 ? "S" : "N";
+        lng = pt.x() < 0 ? "W" : "E";
+        info += tr("[Grid: %1%2%5 %3%4%5] ").arg(lat).arg(qAbs(pt.y()), 0, 'f', 6).arg(lng).arg(qAbs(pt.x()), 0, 'f', 6).arg(QChar('\260'));
     }
     else
     {
diff --git a/src/helpers/CHistoryListWidget.cpp b/src/helpers/CHistoryListWidget.cpp
index 1ec3fea..f556169 100644
--- a/src/helpers/CHistoryListWidget.cpp
+++ b/src/helpers/CHistoryListWidget.cpp
@@ -98,6 +98,7 @@ void CHistoryListWidget::slotContextMenu(const QPoint& point)
     menu->exec(p);
 }
 
+
 void CHistoryListWidget::slotCutHistory()
 {
     if(currentRow() == (count() - 1))
diff --git a/src/helpers/CHistoryListWidget.h b/src/helpers/CHistoryListWidget.h
index 02ea2ed..b93c087 100644
--- a/src/helpers/CHistoryListWidget.h
+++ b/src/helpers/CHistoryListWidget.h
@@ -40,7 +40,7 @@ class CHistoryListWidget : public QListWidget
         void slotCutHistory();
 
     private:
-        QString key;
+        IGisItem::key_t key;
         QMenu * menu;
         QAction * actionCutHistory;
 };
diff --git a/src/helpers/CSelectProjectDialog.cpp b/src/helpers/CSelectProjectDialog.cpp
index e73ddbb..ddddfc5 100644
--- a/src/helpers/CSelectProjectDialog.cpp
+++ b/src/helpers/CSelectProjectDialog.cpp
@@ -17,7 +17,7 @@
 **********************************************************************************************/
 
 #include "helpers/CSelectProjectDialog.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "helpers/CSettings.h"
 
 #include <QtWidgets>
diff --git a/src/mouse/CMouseEditArea.cpp b/src/mouse/CMouseEditArea.cpp
index dc77d0b..2b34f23 100644
--- a/src/mouse/CMouseEditArea.cpp
+++ b/src/mouse/CMouseEditArea.cpp
@@ -34,18 +34,18 @@ CMouseEditArea::CMouseEditArea(CGisItemOvlArea &area, CGisDraw * gis, CCanvas *
     : IMouseEditLine(area, gis, parent)
 {
     cursor = cursor1 = QCursor(QPixmap(":/cursors/cursorMoveArea.png"),0,0);
-    key    = area.getKey();
-    canvas->reportStatus(key, tr("<b>Edit Area</b><br/>Select a corner point for more options.<br/>"));
+    key         = area.getKey();
+    canvas->reportStatus(key.item, tr("<b>Edit Area</b><br/>Select a corner point for more options.<br/>"));
 }
 
 CMouseEditArea::~CMouseEditArea()
 {
-    canvas->reportStatus(key, "");
+    canvas->reportStatus(key.item, "");
 }
 
 void CMouseEditArea::mousePressEvent(QMouseEvent * e)
 {
-    canvas->reportStatus(key, "");
+    canvas->reportStatus(key.item, "");
     IMouseEditLine::mousePressEvent(e);
 }
 
@@ -65,19 +65,19 @@ IGisLine * CMouseEditArea::getGisLine()
 
 void CMouseEditArea::slotAbort()
 {
-    canvas->reportStatus(key,"");
+    canvas->reportStatus(key.item,"");
     IMouseEditLine::slotAbort();
 }
 
 void CMouseEditArea::slotCopyToOrig()
 {
-    canvas->reportStatus(key,"");
+    canvas->reportStatus(key.item,"");
     IMouseEditLine::slotCopyToOrig();
 }
 
 void CMouseEditArea::slotCopyToNew()
 {
-    canvas->reportStatus(key,"");
+    canvas->reportStatus(key.item,"");
 
     if(coords1.size() < 3)
     {
diff --git a/src/mouse/CMouseEditArea.h b/src/mouse/CMouseEditArea.h
index 5f5a07b..e1cb241 100644
--- a/src/mouse/CMouseEditArea.h
+++ b/src/mouse/CMouseEditArea.h
@@ -20,6 +20,7 @@
 #define CMOUSEEDITAREA_H
 
 #include "mouse/IMouseEditLine.h"
+#include "gis/IGisItem.h"
 
 class CGisItemOvlArea;
 
@@ -43,8 +44,7 @@ class CMouseEditArea : public IMouseEditLine
         IGisLine * getGisLine();
 
     private:
-        QString     key;
-
+        IGisItem::key_t key;
 };
 
 #endif //CMOUSEEDITAREA_H
diff --git a/src/mouse/CMouseEditTrk.cpp b/src/mouse/CMouseEditTrk.cpp
index 6887578..3ca12d9 100644
--- a/src/mouse/CMouseEditTrk.cpp
+++ b/src/mouse/CMouseEditTrk.cpp
@@ -33,7 +33,7 @@ CMouseEditTrk::CMouseEditTrk(CGisItemTrk &trk, CGisDraw * gis, CCanvas * parent)
     : IMouseEditLine(trk, gis, parent)
 {
     cursor = cursor1 = QCursor(QPixmap(":/cursors/cursorMoveLine.png"),0,0);
-    key    = trk.getKey();
+    key         = trk.getKey();
 
     // reset any focus the track might have.
     trk.setMouseFocusByPoint(NOPOINT, CGisItemTrk::eFocusMouseMove);
@@ -43,7 +43,7 @@ CMouseEditTrk::CMouseEditTrk(CGisItemTrk &trk, CGisDraw * gis, CCanvas * parent)
         trk.gainUserFocus(false);
     }
 
-    canvas->reportStatus(key, tr("<b>Edit Track Points</b><br/>Select a track point for more options.<br/>"));
+    canvas->reportStatus(key.item, tr("<b>Edit Track Points</b><br/>Select a track point for more options.<br/>"));
     /*
         trigger complete update of GIS components to make sure all changes to
         the originating object are reflected on the canvas
@@ -58,7 +58,7 @@ CMouseEditTrk::~CMouseEditTrk()
 
 void CMouseEditTrk::mousePressEvent(QMouseEvent * e)
 {
-    canvas->reportStatus(key, "");
+    canvas->reportStatus(key.item, "");
     IMouseEditLine::mousePressEvent(e);
 }
 
@@ -69,20 +69,20 @@ IGisLine * CMouseEditTrk::getGisLine()
 
 void CMouseEditTrk::slotAbort()
 {
-    canvas->reportStatus(key,"");
+    canvas->reportStatus(key.item,"");
     IMouseEditLine::slotAbort();
 }
 
 void CMouseEditTrk::slotCopyToOrig()
 {
-    canvas->reportStatus(key,"");
+    canvas->reportStatus(key.item,"");
     IMouseEditLine::slotCopyToOrig();
 }
 
 
 void CMouseEditTrk::slotCopyToNew()
 {
-    canvas->reportStatus(key,"");
+    canvas->reportStatus(key.item,"");
 
     if(coords1.size() < 2)
     {
diff --git a/src/mouse/CMouseEditTrk.h b/src/mouse/CMouseEditTrk.h
index 48f6eee..7331121 100644
--- a/src/mouse/CMouseEditTrk.h
+++ b/src/mouse/CMouseEditTrk.h
@@ -20,6 +20,7 @@
 #define CMOUSEEDITTRK_H
 
 #include "mouse/IMouseEditLine.h"
+#include "gis/IGisItem.h"
 
 class CGisItemTrk;
 
@@ -43,7 +44,7 @@ class CMouseEditTrk : public IMouseEditLine
         IGisLine * getGisLine();
 
     private:
-        QString     key;
+        IGisItem::key_t key;
 };
 
 #endif //CMOUSEEDITTRK_H
diff --git a/src/mouse/CMouseMoveWpt.cpp b/src/mouse/CMouseMoveWpt.cpp
index e6cae37..22b93b6 100644
--- a/src/mouse/CMouseMoveWpt.cpp
+++ b/src/mouse/CMouseMoveWpt.cpp
@@ -31,10 +31,10 @@
 CMouseMoveWpt::CMouseMoveWpt(CGisItemWpt &wpt, CGisDraw * gis, CCanvas *parent)
     : IMouse(gis, parent)
 {
-    cursor  = QCursor(QPixmap(":/cursors/cursorMoveWpt.png"),0,0);
-    key     = wpt.getKey();
-    icon    = getWptIconByName(wpt.getIconName(), focus);
-    origPos = wpt.getPosition() * DEG_TO_RAD;
+    cursor      = QCursor(QPixmap(":/cursors/cursorMoveWpt.png"),0,0);
+    key         = wpt.getKey();
+    icon        = getWptIconByName(wpt.getIconName(), focus);
+    origPos     = wpt.getPosition() * DEG_TO_RAD;
 }
 
 CMouseMoveWpt::~CMouseMoveWpt()
diff --git a/src/mouse/CMouseMoveWpt.h b/src/mouse/CMouseMoveWpt.h
index 2c2a1da..041f3f2 100644
--- a/src/mouse/CMouseMoveWpt.h
+++ b/src/mouse/CMouseMoveWpt.h
@@ -20,6 +20,7 @@
 #define CMOUSEMOVEWPT_H
 
 #include "mouse/IMouse.h"
+#include "gis/IGisItem.h"
 
 #include <QPixmap>
 
@@ -43,7 +44,7 @@ class CMouseMoveWpt : public IMouse
         virtual void slotPanCanvas();
 
     private:
-        QString key;
+        IGisItem::key_t key;
         QPointF origPos;
         QPointF newPos;
         QPointF focus;
diff --git a/src/mouse/CMouseNormal.cpp b/src/mouse/CMouseNormal.cpp
index c701435..908c51a 100644
--- a/src/mouse/CMouseNormal.cpp
+++ b/src/mouse/CMouseNormal.cpp
@@ -25,7 +25,7 @@
 #include "gis/rte/CGisItemRte.h"
 #include "gis/CGisWidget.h"
 #include "gis/CGisDraw.h"
-#include "gis/IGisProject.h"
+#include "gis/prj/IGisProject.h"
 #include "GeoMath.h"
 
 #include <QtWidgets>
@@ -98,10 +98,10 @@ void CMouseNormal::mouseMoveEvent(QMouseEvent * e)
             case eStateHooverSingle:
             case eStateHooverMultiple:
             {
-                const QString& key = CGisItemTrk::getKeyUserFocus();
-                if(!key.isEmpty())
+                const IGisItem::key_t& key = CGisItemTrk::getKeyUserFocus();
+                if(!key.item.isEmpty())
                 {
-                    CGisItemTrk * trk = dynamic_cast<CGisItemTrk*>(CGisWidget::self().getItemByKey(CGisItemTrk::getKeyUserFocus()));
+                    CGisItemTrk * trk = dynamic_cast<CGisItemTrk*>(CGisWidget::self().getItemByKey(key));
                     if(trk != 0)
                     {
                         trk->setMouseFocusByPoint(point, CGisItemTrk::eFocusMouseMove);
@@ -158,10 +158,9 @@ void CMouseNormal::mouseReleaseEvent(QMouseEvent *e)
                     const CScrOptUnclutter::item_t * scrOpt = screenUnclutter->selectItem(point);
                     if(scrOpt != 0)
                     {
-                        QString key = scrOpt->key;
                         screenUnclutter->clear();
 
-                        IGisItem * item = CGisWidget::self().getItemByKey(key);
+                        IGisItem * item = CGisWidget::self().getItemByKey(scrOpt->key);
                         if(item)
                         {
                             item->treeWidget()->collapseAll();
diff --git a/src/mouse/CMouseRangeTrk.cpp b/src/mouse/CMouseRangeTrk.cpp
index 9e9c5d6..a80afd5 100644
--- a/src/mouse/CMouseRangeTrk.cpp
+++ b/src/mouse/CMouseRangeTrk.cpp
@@ -31,8 +31,8 @@ CMouseRangeTrk::CMouseRangeTrk(CGisItemTrk &trk, CGisDraw *gis, CCanvas *parent)
     , state(eStateIdle)
     , anchor(NOPOINTF)
 {
-    cursor  = QCursor(QPixmap("://cursors/cursorSelectRange.png"),0,0);
-    key = trk.getKey();
+    cursor      = QCursor(QPixmap("://cursors/cursorSelectRange.png"),0,0);
+    key         = trk.getKey();
 
     // reset user focus if the track has it
     trk.setMouseFocusByPoint(NOPOINT, CGisItemTrk::eFocusMouseMove);
@@ -45,7 +45,7 @@ CMouseRangeTrk::CMouseRangeTrk(CGisItemTrk &trk, CGisDraw *gis, CCanvas *parent)
     // switch to full mode to show deleted (hidden) track points, too
     trk.setDrawMode(CGisItemTrk::eDrawRange);
 
-    canvas->reportStatus(key, tr("<b>Select Range</b><br/>Select first track point. And then a second one.<br/>"));
+    canvas->reportStatus(key.item, tr("<b>Select Range</b><br/>Select first track point. And then a second one.<br/>"));
     /*
         trigger complete update of GIS components to make sure all changes to
         the originating object are reflected on the canvas
@@ -55,7 +55,7 @@ CMouseRangeTrk::CMouseRangeTrk(CGisItemTrk &trk, CGisDraw *gis, CCanvas *parent)
 
 CMouseRangeTrk::~CMouseRangeTrk()
 {
-    canvas->reportStatus(key, "");
+    canvas->reportStatus(key.item, "");
 
     CGisItemTrk * trk = dynamic_cast<CGisItemTrk*>(CGisWidget::self().getItemByKey(key));
     if(trk)
@@ -112,7 +112,7 @@ void CMouseRangeTrk::draw(QPainter& p,  bool needsRedraw, const QRect &rect)
 
 void CMouseRangeTrk::mousePressEvent(QMouseEvent * e)
 {
-    canvas->reportStatus(key, "");
+    canvas->reportStatus(key.item, "");
     point  = e->pos();
     if(e->button() == Qt::RightButton)
     {
diff --git a/src/mouse/CMouseRangeTrk.h b/src/mouse/CMouseRangeTrk.h
index dcd0a16..095f0ea 100644
--- a/src/mouse/CMouseRangeTrk.h
+++ b/src/mouse/CMouseRangeTrk.h
@@ -20,6 +20,7 @@
 #define CMOUSERANGETRK_H
 
 #include "mouse/IMouse.h"
+#include "gis/IGisItem.h"
 #include <QPointer>
 
 class CGisItemTrk;
@@ -46,7 +47,7 @@ class CMouseRangeTrk : public IMouse
         void slotCopy();
 
     private:
-        QString key;
+        IGisItem::key_t key;
 
         enum state_e
         {
diff --git a/src/mouse/CScrOptUnclutter.cpp b/src/mouse/CScrOptUnclutter.cpp
index 7028f65..47286d1 100644
--- a/src/mouse/CScrOptUnclutter.cpp
+++ b/src/mouse/CScrOptUnclutter.cpp
@@ -143,22 +143,23 @@ void CScrOptUnclutter::addItem(IGisItem * gisItem)
 {
     items << item_t();
     item_t& item    = items.last();
-    item.name       = gisItem->getName();
+    item.name       = gisItem->getNameEx();
     item.key        = gisItem->getKey();
     item.icon       = gisItem->getIcon();
     item.area       = item.icon.rect();
     item.active     = item.area.adjusted(-10,-10,10,10);
 }
 
-QString CScrOptUnclutter::getItemKey(int index)
+IGisItem::key_t CScrOptUnclutter::getItemKey(int index)
 {
     if(index < items.size())
     {
         return items[index].key;
     }
-    return QString::Null();
+    return IGisItem::key_t();
 }
 
+
 const CScrOptUnclutter::item_t * CScrOptUnclutter::selectItem(const QPoint& point)
 {
     foreach(const item_t& item, items)
diff --git a/src/mouse/CScrOptUnclutter.h b/src/mouse/CScrOptUnclutter.h
index a95d671..286fd88 100644
--- a/src/mouse/CScrOptUnclutter.h
+++ b/src/mouse/CScrOptUnclutter.h
@@ -20,8 +20,7 @@
 #define CSCROPTUNCLUTTER_H
 
 #include "mouse/IScrOpt.h"
-
-class IGisItem;
+#include "gis/IGisItem.h"
 
 
 class CScrOptUnclutter : public IScrOpt
@@ -33,7 +32,7 @@ class CScrOptUnclutter : public IScrOpt
         struct item_t
         {
             QString name;
-            QString key;
+            IGisItem::key_t key;
             QPixmap icon;
             QRect   area;
             QRect   text;
@@ -44,7 +43,7 @@ class CScrOptUnclutter : public IScrOpt
         virtual int  size(){return items.size();}
 
         void addItem(IGisItem * gisItem);
-        QString getItemKey(int index = 0);
+        IGisItem::key_t getItemKey(int index = 0);
         const item_t *selectItem(const QPoint& point);
 
         void draw(QPainter& p);
diff --git a/src/units/CUnitImperial.cpp b/src/units/CUnitImperial.cpp
index b9061f9..0a4f6e7 100644
--- a/src/units/CUnitImperial.cpp
+++ b/src/units/CUnitImperial.cpp
@@ -77,6 +77,21 @@ void CUnitImperial::meter2distance(qreal meter, QString& val, QString& unit)
     }
 }
 
+void CUnitImperial::meter2area(qreal meter, QString& val, QString& unit)
+{
+    if(meter == NOFLOAT)
+    {
+        val  = "-";
+        unit = "";
+    }
+    else
+    {
+        val.sprintf("%1.2f", meter / (1/0.6213699E-3 * 1/0.6213699E-3));
+        unit = "ml²";
+    }
+}
+
+
 
 qreal CUnitImperial::elevation2meter(const QString& val)
 {
diff --git a/src/units/CUnitImperial.h b/src/units/CUnitImperial.h
index 2d5fd93..839cfa7 100644
--- a/src/units/CUnitImperial.h
+++ b/src/units/CUnitImperial.h
@@ -30,6 +30,7 @@ class CUnitImperial : public IUnit
 
         void meter2elevation(qreal meter, QString& val, QString& unit);
         void meter2distance(qreal meter, QString& val, QString& unit);
+        void meter2area(qreal meter, QString& val, QString& unit);
         qreal elevation2meter(const QString& val);
 };
 #endif                           //CUNITIMPERIAL_H
diff --git a/src/units/CUnitMetric.cpp b/src/units/CUnitMetric.cpp
index 906fdac..02f4586 100644
--- a/src/units/CUnitMetric.cpp
+++ b/src/units/CUnitMetric.cpp
@@ -99,6 +99,20 @@ void CUnitMetric::meter2speed(qreal meter, QString& val, QString& unit)
     unit = speedunit;
 }
 
+void CUnitMetric::meter2area(qreal meter, QString& val, QString& unit)
+{
+    if(meter == NOFLOAT)
+    {
+        val  = "-";
+        unit = "";
+    }
+    else
+    {
+        val.sprintf("%1.2f", meter / 1000000);
+        unit = "km²";
+    }
+
+}
 
 qreal CUnitMetric::elevation2meter(const QString& val)
 {
diff --git a/src/units/CUnitMetric.h b/src/units/CUnitMetric.h
index 5d96a9a..13e284b 100644
--- a/src/units/CUnitMetric.h
+++ b/src/units/CUnitMetric.h
@@ -31,6 +31,7 @@ class CUnitMetric : public IUnit
         void meter2elevation(qreal meter, QString& val, QString& unit);
         void meter2distance(qreal meter, QString& val, QString& unit);
         void meter2speed(qreal meter, QString& val, QString& unit);
+        void meter2area(qreal meter, QString& val, QString& unit);
         qreal elevation2meter(const QString& val);
 };
 #endif                           //CUNITMETRIC_H
diff --git a/src/units/CUnitNautic.cpp b/src/units/CUnitNautic.cpp
index a47fecd..bb57a08 100644
--- a/src/units/CUnitNautic.cpp
+++ b/src/units/CUnitNautic.cpp
@@ -76,6 +76,21 @@ void CUnitNautic::meter2speed(qreal meter, QString& val, QString& unit)
     }
 }
 
+void CUnitNautic::meter2area(qreal meter, QString& val, QString& unit)
+{
+    if(meter == NOFLOAT)
+    {
+        val  = "-";
+        unit = "";
+    }
+    else
+    {
+        val.sprintf("%1.2f", meter / (1852 * 1852));
+        unit = "nm²";
+    }
+
+}
+
 
 qreal CUnitNautic::elevation2meter(const QString& val)
 {
diff --git a/src/units/CUnitNautic.h b/src/units/CUnitNautic.h
index 4312a8b..432105f 100644
--- a/src/units/CUnitNautic.h
+++ b/src/units/CUnitNautic.h
@@ -32,6 +32,7 @@ class CUnitNautic : public IUnit
         void meter2elevation(qreal meter, QString& val, QString& unit);
         void meter2distance(qreal meter, QString& val, QString& unit);
         void meter2speed(qreal meter, QString& val, QString& unit);
+        void meter2area(qreal meter, QString& val, QString& unit);
         qreal elevation2meter(const QString& val);
 };
 #endif                           //CUNITNAUTIC_H
diff --git a/src/units/IUnit.h b/src/units/IUnit.h
index 246a254..50f937b 100644
--- a/src/units/IUnit.h
+++ b/src/units/IUnit.h
@@ -42,9 +42,11 @@ class IUnit : public QObject
         virtual void meter2distance(qreal meter, QString& val, QString& unit) = 0;
         /// convert meter per second to a speed value string and unit label
         virtual void meter2speed(qreal meter, QString& val, QString& unit);
+        virtual void meter2area(qreal meter, QString& val, QString& unit) = 0;
         virtual void seconds2time(quint32 ttime, QString& val, QString& unit);
         virtual qreal elevation2meter(const QString& val) = 0;
 
+
         enum type_e {eTypeMetric, eTypeImperial, eTypeNautic};
         static void setUnitType(type_e t, QObject *parent);
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/qmapshack.git



More information about the Pkg-grass-devel mailing list