diff --git a/AnnotationDialog/Dialog.cpp b/AnnotationDialog/Dialog.cpp
index bb88fc5c..26908c1d 100644
--- a/AnnotationDialog/Dialog.cpp
+++ b/AnnotationDialog/Dialog.cpp
@@ -1,1731 +1,1731 @@
/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "Dialog.h"
#include "DateEdit.h"
#include "DescriptionEdit.h"
#include "ImagePreviewWidget.h"
#include "ListSelect.h"
#include "Logging.h"
#include "ResizableFrame.h"
#include "ShortCutManager.h"
#include "ShowSelectionOnlyManager.h"
#include "enums.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-#ifdef HAVE_KGEOMAP
+#ifdef HAVE_MARBLE
#include
"),
i18n("Feature has not been configured"));
return nullptr;
}
}
// vi:expandtab:tabstop=4 shiftwidth=4:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d8519a8..5caf65fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,551 +1,551 @@
cmake_minimum_required(VERSION 3.2.0)
project(kphotoalbum VERSION 5.5)
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif()
# provide drop-down menu for build-type in cmake-gui:
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ";Debug;Release;RelWithDebInfo;MinSizeRel")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
find_package(ECM REQUIRED NO_MODULE)
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH} )
include(KDEInstallDirs)
include(KDECompilerSettings)
include(KDECMakeSettings)
include(FeatureSummary)
# enable exceptions:
kde_enable_exceptions()
add_definitions(
-DQT_NO_CAST_FROM_ASCII
-DQT_NO_CAST_TO_ASCII
-DQT_NO_URL_CAST_FROM_STRING
-DQT_NO_CAST_FROM_BYTEARRAY
-DQT_DEPRECATED_WARNINGS
-DQT_STRICT_ITERATORS
)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_REQUIRED TRUE)
########### dependencies ###############
find_package(Qt5 5.9 REQUIRED COMPONENTS Sql Xml Widgets Network)
find_package(Phonon4Qt5 REQUIRED)
find_package(KF5 5.44 REQUIRED COMPONENTS Archive Completion Config CoreAddons DocTools I18n IconThemes JobWidgets KIO TextWidgets XmlGui WidgetsAddons)
find_package(JPEG REQUIRED)
if(JPEG_FOUND)
include_directories(${JPEG_INCLUDE_DIR})
endif()
### 2018-12-30 jzarl
# When Exiv2 0.26 can be deprecated, FindExiv2.cmake should be removed
# and only find_package(exiv2) should be used
find_package(exiv2 CONFIG QUIET)
if(exiv2_FOUND)
# search againg with REQUIRED, so that the feature summary correctly shows exiv as required dependency
find_package(exiv2 CONFIG REQUIRED)
set(EXIV2_LIBRARIES exiv2lib)
else()
find_package(Exiv2 REQUIRED)
endif()
find_package(KF5Kipi 5.1.0)
set_package_properties(KF5Kipi
PROPERTIES
TYPE RECOMMENDED
PURPOSE "Enables integration of KDE image plugin interface (shared functionality between KPhotoAlbum and other apps like gwenview or digikam)"
)
set(HASKIPI ${KF5Kipi_FOUND})
find_package(KF5Purpose)
set_package_properties(KF5Purpose
PROPERTIES
TYPE RECOMMENDED
PURPOSE "Enables integration with KDE Purpose plugins, which provide image sharing and similar functionality."
)
find_package(KF5KDcraw)
set_package_properties(KF5KDcraw
PROPERTIES
TYPE OPTIONAL
PURPOSE "Enables RAW image support"
)
set(HAVE_KDCRAW ${KF5KDcraw_FOUND} )
-#find_package(KF5KGeoMap)
-#set_package_properties(KF5KGeoMap
-# PROPERTIES
-# TYPE OPTIONAL
-# PURPOSE "Enables support for geographic map location using embedded GPS information."
-# )
-#set(HAVE_KGEOMAP ${KF5KGeoMap_FOUND})
+find_package(Marble)
+set_package_properties(Marble
+ PROPERTIES
+ TYPE OPTIONAL
+ PURPOSE "Enables support for geographic map location using embedded GPS information."
+ )
+set(HAVE_MARBLE ${Marble_FOUND})
add_custom_target(
UpdateVersion ALL
COMMAND ${CMAKE_COMMAND}
-DBASE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DPROJECT_NAME=KPA -DPROJECT_VERSION="${PROJECT_VERSION}"
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/UpdateVersion.cmake"
COMMENT "Updating version header."
BYPRODUCTS "${CMAKE_CURRENT_SOURCE_DIR}/version.h"
)
# For config-kpa-*.h
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(libdatebar_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/DateBar/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/DateBar/DateBarWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DateBar/ViewHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DateBar/MouseHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DateBar/MouseHandler.cpp
)
set(libSettings_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Settings/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/Settings/SettingsData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/SettingsDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/ViewerSizeConfig.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/CategoryItem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/CategoryPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/TagGroupsPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/GeneralPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/FileVersionDetectionPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/ThumbnailsPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/ViewerPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/DatabaseBackendPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/UntaggedGroupBox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/CategoriesGroupsWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/BirthdayPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/DateTableWidgetItem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/Logging.cpp
)
set(libxmldb_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/Database.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/XMLCategoryCollection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/XMLCategory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/XMLImageDateCollection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/NumberedBackup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/FileReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/FileWriter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/ElementWriter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/XmlReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/CompressFileInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/XMLDB/Logging.cpp
)
set(libThumbnailView_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/FilterWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailRequest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailToolTip.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/GridResizeInteraction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/GridResizeSlider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/SelectionInteraction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/MouseTrackingInteraction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/CellGeometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailFacade.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/KeyboardEventHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailDND.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/Delegate.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/SelectionMaintainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/VideoThumbnailCycler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/MouseInteraction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/ThumbnailFactory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ThumbnailView/enums.cpp
)
set(libPlugins_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/Logging.cpp
)
if(KF5Kipi_FOUND)
set(libPlugins_SRCS ${libPlugins_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/Interface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/ImageCollection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/ImageInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/CategoryImageCollection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/ImageCollectionSelector.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/PluginsPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/UploadWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/UploadImageCollection.cpp
)
endif()
if(KF5Purpose_FOUND)
set(libPlugins_SRCS ${libPlugins_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PurposeMenu.cpp
)
endif()
set(libViewer_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/ViewerWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/ImageDisplay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/ViewHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/SpeedDisplay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/InfoBox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/CategoryImageConfig.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/AbstractDisplay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/VideoDisplay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/TextDisplay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/InfoBoxResizer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/VisibleOptionsMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/VideoShooter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/TaggedArea.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Viewer/Logging.cpp
)
set(libCategoryListView_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/CategoryListView/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/CategoryListView/DragableTreeWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CategoryListView/CheckDropItem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CategoryListView/DragItemInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CategoryListView/Logging.cpp
)
set(libHTMLGenerator_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/HTMLDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/Generator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/Setup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/ImageSizeCheckBox.h
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/HTMLGenerator/ImageSizeCheckBox.cpp
)
set(libUtilities_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/AlgorithmHelper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ShowBusyCursor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/List.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/UniqFilenameMapper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/FileUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/BooleanGuard.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/Process.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/DeleteFiles.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ToolTip.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/JpeglibWithFix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/StringSet.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/FastJpeg.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/DemoUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/DescriptionUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/FileNameUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/VideoUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ImageUtil.cpp
)
set(libMainWindow_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DeleteDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/RunDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/FeatureDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/InvalidDateFinder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/AutoStackImages.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/TokenEditor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/WelcomeDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/Window.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/SplashScreen.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/ExternalPopup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/CategoryImagePopup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/SearchBar.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/ImageCounter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DirtyIndicator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/StatisticsDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/BreadcrumbViewer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/StatusBar.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/UpdateVideoThumbnail.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DuplicateMerger/DuplicateMerger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DuplicateMerger/DuplicateMatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/DuplicateMerger/MergeToolTip.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/CopyPopup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/Options.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow/Logging.cpp
)
set(libImageManager_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ImageLoaderThread.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/AsyncLoader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ImageRequest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ImageClientInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ImageDecoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/RawImageDecoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/RequestQueue.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ThumbnailCache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ImageEvent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ThumbnailBuilder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/PreloadRequest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/CancelEvent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/VideoImageRescaleRequest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/VideoThumbnails.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/VideoLengthExtractor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/ExtractOneVideoFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/CacheFileInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImageManager/enums.cpp
)
set(libDB_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/DB/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/Category.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/CategoryCollection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ExactCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageDate.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/MD5Map.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/MemberMap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageInfoList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageDB.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/FileInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/NegationCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/NewImageFinder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageScout.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/NoTagCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/GroupCounter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/CategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageSearchInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/CategoryItem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ContainerCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ValueCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/OrCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/AndCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/FastDir.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/OptimizedFileList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/FileName.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/FileNameList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/CategoryPtr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ExifMode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageDateCollection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/ImageInfoPtr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/MD5.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/MediaCount.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/RawId.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/SimpleCategoryMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DB/UIDelegate.cpp
)
set(libImportExport_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/Export.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/Import.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/ImportMatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/XMLHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/MiniViewer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/ImportHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/ImageRow.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/ImportDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/ImportSettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/KimFileReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/MD5CheckPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ImportExport/Logging.cpp
)
set(libAnnotationDialog_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/Dialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ListSelect.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ImagePreview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ImagePreviewWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/DateEdit.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/CompletableLineEdit.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ListViewItemHider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ShowSelectionOnlyManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ShortCutManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/ResizableFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/DescriptionEdit.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/AreaTagSelectDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/AnnotationDialog/enums.cpp
)
set(libBrowser_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Browser/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/Browser/BrowserWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/BrowserPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/OverviewPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/CategoryPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/ImageViewPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/TreeFilter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/Breadcrumb.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/BreadcrumbList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/AbstractCategoryModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/FlatCategoryModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/TreeCategoryModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/CenteringIconView.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/enums.cpp
)
set(libExif_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Exif/documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/Exif/Database.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/InfoDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/SearchDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/SearchInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/TreeView.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/Info.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/RangeWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/DatabaseElement.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/ReReadDialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/Grid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exif/SearchDialogSettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Settings/ExifPage.cpp
)
set(libBackgroundTaskManager_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/JobInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/JobManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/StatusIndicator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/JobViewer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/JobModel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/JobInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/CompletedJobInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/Priority.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/PriorityQueue.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundTaskManager/Logging.cpp
)
set(libBackgroundJobs_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundJobs/SearchForVideosWithoutLengthInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundJobs/ReadVideoLengthJob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundJobs/SearchForVideosWithoutVideoThumbnailsJob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundJobs/HandleVideoThumbnailRequestJob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/BackgroundJobs/ExtractOneThumbnailJob.cpp
)
set(libRemoteControl_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/RemoteCommand.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/RemoteConnection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/Server.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/RemoteInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/SearchInfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/RemoteImageRequest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/ImageNameStore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/ConnectionIndicator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RemoteControl/Logging.cpp
)
set(libMap_SRCS)
-#if(KF5KGeoMap_FOUND)
+if(Marble_FOUND)
set(libMap_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/Browser/GeoPositionPage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Browser/PositionBrowserWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Map/MapView.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Map/Logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Map/GeoCoordinates.cpp
)
-#endif()
+endif()
add_subdirectory(images)
add_subdirectory(icons)
add_subdirectory(demo)
add_subdirectory(themes)
add_subdirectory(scripts)
add_subdirectory(doc)
########### next target ###############
set(kphotoalbum_SRCS
main.cpp
${libdatebar_SRCS}
${libSettings_SRCS}
${libsurvey_SRCS}
${libxmldb_SRCS}
${libThumbnailView_SRCS}
${libPlugins_SRCS}
${libViewer_SRCS}
${libCategoryListView_SRCS}
${libHTMLGenerator_SRCS}
${libMainWindow_SRCS}
${libImageManager_SRCS}
${libDB_SRCS}
${libImportExport_SRCS}
${libAnnotationDialog_SRCS}
${libExif_SRCS}
${libBrowser_SRCS}
${libBackgroundTaskManager_SRCS}
${libBackgroundJobs_SRCS}
${libRemoteControl_SRCS}
${libMap_SRCS}
${libUtilities_SRCS}
# add doxygen headers so that they get visibiltiy in IDEs:
${CMAKE_CURRENT_SOURCE_DIR}/documentation/coding-standards.h
${CMAKE_CURRENT_SOURCE_DIR}/documentation/mainpage.h
${CMAKE_CURRENT_SOURCE_DIR}/documentation/phrase-book.h
${CMAKE_CURRENT_SOURCE_DIR}/documentation/videothumbnails.h
)
add_executable(kphotoalbum ${kphotoalbum_SRCS})
add_dependencies(kphotoalbum UpdateVersion)
# External components
target_link_libraries(kphotoalbum
${JPEG_LIBRARY}
${EXIV2_LIBRARIES}
KF5::Archive
KF5::Completion
KF5::ConfigCore
KF5::ConfigGui
KF5::CoreAddons
KF5::I18n
KF5::IconThemes
KF5::JobWidgets
KF5::KIOCore
KF5::KIOWidgets
KF5::TextWidgets
KF5::XmlGui
KF5::WidgetsAddons
Phonon::phonon4qt5
Qt5::Network
Qt5::Sql
)
if(KF5Kipi_FOUND)
target_link_libraries(kphotoalbum KF5::Kipi)
endif()
if(KF5Purpose_FOUND)
target_link_libraries(kphotoalbum KF5::Purpose KF5::PurposeWidgets)
endif()
if(KF5KDcraw_FOUND)
target_link_libraries(kphotoalbum KF5::KDcraw)
endif()
-#if(KF5KGeoMap_FOUND)
-# target_link_libraries(kphotoalbum KF5::KGeoMap )
-#endif()
+if(Marble_FOUND)
+ target_link_libraries(kphotoalbum Marble)
+endif()
install(TARGETS kphotoalbum ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
########### install files ###############
install(PROGRAMS org.kde.kphotoalbum.desktop org.kde.kphotoalbum-import.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES kphotoalbumrc DESTINATION ${KDE_INSTALL_CONFDIR})
install(FILES tips default-setup DESTINATION ${KDE_INSTALL_DATADIR}/kphotoalbum)
install(FILES kphotoalbumui.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/kphotoalbum)
install(FILES org.kde.kphotoalbum.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
configure_file(config-kpa-kdcraw.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kpa-kdcraw.h)
configure_file(config-kpa-kipi.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kpa-kipi.h)
-#configure_file(config-kpa-kgeomap.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kpa-kgeomap.h)
+configure_file(config-kpa-marble.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kpa-marble.h)
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
# vi:expandtab:tabstop=4 shiftwidth=4:
diff --git a/DB/ImageInfo.cpp b/DB/ImageInfo.cpp
index d737b4fa..a92ec960 100644
--- a/DB/ImageInfo.cpp
+++ b/DB/ImageInfo.cpp
@@ -1,799 +1,799 @@
/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "ImageInfo.h"
#include "CategoryCollection.h"
#include "FileInfo.h"
#include "ImageDB.h"
#include "Logging.h"
#include "MemberMap.h"
#include
#include
#include
#include
#include
#include
#include
#include
using namespace DB;
ImageInfo::ImageInfo()
: m_null(true)
, m_rating(-1)
, m_stackId(0)
, m_stackOrder(0)
, m_videoLength(-1)
, m_isMatched(false)
, m_matchGeneration(-1)
, m_locked(false)
, m_dirty(false)
{
}
ImageInfo::ImageInfo(const DB::FileName &fileName, MediaType type, bool readExifInfo,
bool storeExifInfo)
: m_imageOnDisk(YesOnDisk)
, m_null(false)
, m_size(-1, -1)
, m_type(type)
, m_rating(-1)
, m_stackId(0)
, m_stackOrder(0)
, m_videoLength(-1)
, m_isMatched(false)
, m_matchGeneration(-1)
, m_locked(false)
{
QFileInfo fi(fileName.absolute());
m_label = fi.completeBaseName();
m_angle = 0;
setFileName(fileName);
// Read Exif information
if (readExifInfo) {
ExifMode mode = EXIFMODE_INIT;
if (!storeExifInfo)
mode &= ~EXIFMODE_DATABASE_UPDATE;
readExif(fileName, mode);
}
m_dirty = false;
}
ImageInfo::ImageInfo(const ImageInfo &other)
{
*this = other;
}
void ImageInfo::setIsMatched(bool isMatched)
{
m_isMatched = isMatched;
}
bool ImageInfo::isMatched() const
{
return m_isMatched;
}
void ImageInfo::setMatchGeneration(int matchGeneration)
{
m_matchGeneration = matchGeneration;
}
int ImageInfo::matchGeneration() const
{
return m_matchGeneration;
}
void ImageInfo::setLabel(const QString &desc)
{
if (desc != m_label)
m_dirty = true;
m_label = desc;
}
QString ImageInfo::label() const
{
return m_label;
}
void ImageInfo::setDescription(const QString &desc)
{
if (desc != m_description)
m_dirty = true;
m_description = desc.trimmed();
}
QString ImageInfo::description() const
{
return m_description;
}
void ImageInfo::setCategoryInfo(const QString &key, const StringSet &value)
{
// Don't check if really changed, because it's too slow.
m_dirty = true;
m_categoryInfomation[key] = value;
}
bool ImageInfo::hasCategoryInfo(const QString &key, const QString &value) const
{
return m_categoryInfomation[key].contains(value);
}
bool DB::ImageInfo::hasCategoryInfo(const QString &key, const StringSet &values) const
{
return values.intersects(m_categoryInfomation[key]);
}
StringSet ImageInfo::itemsOfCategory(const QString &key) const
{
return m_categoryInfomation[key];
}
void ImageInfo::renameItem(const QString &category, const QString &oldValue, const QString &newValue)
{
if (m_taggedAreas.contains(category)) {
if (m_taggedAreas[category].contains(oldValue)) {
m_taggedAreas[category][newValue] = m_taggedAreas[category][oldValue];
m_taggedAreas[category].remove(oldValue);
}
}
StringSet &set = m_categoryInfomation[category];
StringSet::iterator it = set.find(oldValue);
if (it != set.end()) {
m_dirty = true;
set.erase(it);
set.insert(newValue);
}
}
DB::FileName ImageInfo::fileName() const
{
return m_fileName;
}
void ImageInfo::setFileName(const DB::FileName &fileName)
{
if (fileName != m_fileName)
m_dirty = true;
m_fileName = fileName;
m_imageOnDisk = Unchecked;
DB::CategoryPtr folderCategory = DB::ImageDB::instance()->categoryCollection()->categoryForSpecial(DB::Category::FolderCategory);
if (folderCategory) {
DB::MemberMap &map = DB::ImageDB::instance()->memberMap();
createFolderCategoryItem(folderCategory, map);
//ImageDB::instance()->setMemberMap( map );
}
}
void ImageInfo::rotate(int degrees, RotationMode mode)
{
// ensure positive degrees:
degrees += 360;
degrees = degrees % 360;
if (degrees == 0)
return;
m_dirty = true;
m_angle = (m_angle + degrees) % 360;
if (degrees == 90 || degrees == 270) {
m_size.transpose();
}
// the AnnotationDialog manages this by itself and sets RotateImageInfoOnly:
if (mode == RotateImageInfoAndAreas) {
for (auto &areasOfCategory : m_taggedAreas) {
for (auto &area : areasOfCategory) {
QRect rotatedArea;
// parameter order for QRect::setCoords:
// setCoords( left, top, right, bottom )
// keep in mind that _size is already transposed
switch (degrees) {
case 90:
rotatedArea.setCoords(
m_size.width() - area.bottom(),
area.left(),
m_size.width() - area.top(),
area.right());
break;
case 180:
rotatedArea.setCoords(
m_size.width() - area.right(),
m_size.height() - area.bottom(),
m_size.width() - area.left(),
m_size.height() - area.top());
break;
case 270:
rotatedArea.setCoords(
area.top(),
m_size.height() - area.right(),
area.bottom(),
m_size.height() - area.left());
break;
default:
// degrees==0; "odd" values won't happen.
rotatedArea = area;
break;
}
// update _taggedAreas[category][tag]:
area = rotatedArea;
}
}
}
}
int ImageInfo::angle() const
{
return m_angle;
}
void ImageInfo::setAngle(int angle)
{
if (angle != m_angle)
m_dirty = true;
m_angle = angle;
}
short ImageInfo::rating() const
{
return m_rating;
}
void ImageInfo::setRating(short rating)
{
Q_ASSERT((rating >= 0 && rating <= 10) || rating == -1);
if (rating > 10)
rating = 10;
if (rating < -1)
rating = -1;
if (m_rating != rating)
m_dirty = true;
m_rating = rating;
}
DB::StackID ImageInfo::stackId() const
{
return m_stackId;
}
void ImageInfo::setStackId(const DB::StackID stackId)
{
if (stackId != m_stackId)
m_dirty = true;
m_stackId = stackId;
}
unsigned int ImageInfo::stackOrder() const
{
return m_stackOrder;
}
void ImageInfo::setStackOrder(const unsigned int stackOrder)
{
if (stackOrder != m_stackOrder)
m_dirty = true;
m_stackOrder = stackOrder;
}
void ImageInfo::setVideoLength(int length)
{
if (m_videoLength != length)
m_dirty = true;
m_videoLength = length;
}
int ImageInfo::videoLength() const
{
return m_videoLength;
}
void ImageInfo::setDate(const ImageDate &date)
{
if (date != m_date)
m_dirty = true;
m_date = date;
}
ImageDate &ImageInfo::date()
{
return m_date;
}
ImageDate ImageInfo::date() const
{
return m_date;
}
bool ImageInfo::operator!=(const ImageInfo &other) const
{
return !(*this == other);
}
bool ImageInfo::operator==(const ImageInfo &other) const
{
bool changed = (m_fileName != other.m_fileName || m_label != other.m_label || (!m_description.isEmpty() && !other.m_description.isEmpty() && m_description != other.m_description) || // one might be isNull.
m_date != other.m_date || m_angle != other.m_angle || m_rating != other.m_rating || (m_stackId != other.m_stackId || !((m_stackId == 0) ? true : (m_stackOrder == other.m_stackOrder))));
if (!changed) {
QStringList keys = DB::ImageDB::instance()->categoryCollection()->categoryNames();
for (QStringList::ConstIterator it = keys.constBegin(); it != keys.constEnd(); ++it)
changed |= m_categoryInfomation[*it] != other.m_categoryInfomation[*it];
}
return !changed;
}
void ImageInfo::renameCategory(const QString &oldName, const QString &newName)
{
m_dirty = true;
m_categoryInfomation[newName] = m_categoryInfomation[oldName];
m_categoryInfomation.remove(oldName);
m_taggedAreas[newName] = m_taggedAreas[oldName];
m_taggedAreas.remove(oldName);
}
void ImageInfo::setMD5Sum(const MD5 &sum, bool storeEXIF)
{
if (sum != m_md5sum) {
// if we make a QObject derived class out of imageinfo, we might invalidate thumbnails from here
// file changed -> reload/invalidate metadata:
ExifMode mode = EXIFMODE_ORIENTATION | EXIFMODE_DATABASE_UPDATE;
// fuzzy dates are usually set for a reason
if (!m_date.isFuzzy())
mode |= EXIFMODE_DATE;
// FIXME (ZaJ): the "right" thing to do would be to update the description
// - if it is currently empty (done.)
// - if it has been set from the exif info and not been changed (TODO)
if (m_description.isEmpty())
mode |= EXIFMODE_DESCRIPTION;
if (!storeEXIF)
mode &= ~EXIFMODE_DATABASE_UPDATE;
readExif(fileName(), mode);
// FIXME (ZaJ): it *should* make sense to set the ImageDB::md5Map() from here, but I want
// to make sure I fully understand everything first...
// this could also be done as signal md5Changed(old,new)
// image size is invalidated by the thumbnail builder, if needed
m_dirty = true;
}
m_md5sum = sum;
}
void ImageInfo::setLocked(bool locked)
{
m_locked = locked;
}
bool ImageInfo::isLocked() const
{
return m_locked;
}
void ImageInfo::readExif(const DB::FileName &fullPath, DB::ExifMode mode)
{
DB::FileInfo exifInfo = DB::FileInfo::read(fullPath, mode);
// Date
if (updateDateInformation(mode)) {
const ImageDate newDate(exifInfo.dateTime());
setDate(newDate);
}
// Orientation
if ((mode & EXIFMODE_ORIENTATION) && Settings::SettingsData::instance()->useEXIFRotate()) {
setAngle(exifInfo.angle());
}
// Description
if ((mode & EXIFMODE_DESCRIPTION) && Settings::SettingsData::instance()->useEXIFComments()) {
bool doSetDescription = true;
QString desc = exifInfo.description();
if (Settings::SettingsData::instance()->stripEXIFComments()) {
for (const auto &ignoredComment : Settings::SettingsData::instance()->EXIFCommentsToStrip()) {
if (desc == ignoredComment) {
doSetDescription = false;
break;
}
}
}
if (doSetDescription) {
setDescription(desc);
}
}
// Database update
if (mode & EXIFMODE_DATABASE_UPDATE) {
Exif::Database::instance()->add(exifInfo);
-#ifdef HAVE_KGEOMAP
+#ifdef HAVE_MARBLE
// GPS coords might have changed...
m_coordsIsSet = false;
#endif
}
}
QStringList ImageInfo::availableCategories() const
{
return m_categoryInfomation.keys();
}
QSize ImageInfo::size() const
{
return m_size;
}
void ImageInfo::setSize(const QSize &size)
{
if (size != m_size)
m_dirty = true;
m_size = size;
}
bool ImageInfo::imageOnDisk(const DB::FileName &fileName)
{
return fileName.exists();
}
ImageInfo::ImageInfo(const DB::FileName &fileName,
const QString &label,
const QString &description,
const ImageDate &date,
int angle,
const MD5 &md5sum,
const QSize &size,
MediaType type,
short rating,
unsigned int stackId,
unsigned int stackOrder)
{
m_fileName = fileName;
m_label = label;
m_description = description;
m_date = date;
m_angle = angle;
m_md5sum = md5sum;
m_size = size;
m_imageOnDisk = Unchecked;
m_locked = false;
m_null = false;
m_type = type;
m_dirty = true;
if (rating > 10)
rating = 10;
if (rating < -1)
rating = -1;
m_rating = rating;
m_stackId = stackId;
m_stackOrder = stackOrder;
m_videoLength = -1;
}
// Note: we need this operator because the base class QSharedData hides
// its copy operator to make exclude the reference counting from being
// copied.
ImageInfo &ImageInfo::operator=(const ImageInfo &other)
{
m_fileName = other.m_fileName;
m_label = other.m_label;
m_description = other.m_description;
m_date = other.m_date;
m_categoryInfomation = other.m_categoryInfomation;
m_taggedAreas = other.m_taggedAreas;
m_angle = other.m_angle;
m_imageOnDisk = other.m_imageOnDisk;
m_md5sum = other.m_md5sum;
m_null = other.m_null;
m_size = other.m_size;
m_type = other.m_type;
m_rating = other.m_rating;
m_stackId = other.m_stackId;
m_stackOrder = other.m_stackOrder;
m_videoLength = other.m_videoLength;
m_isMatched = other.m_isMatched;
m_matchGeneration = other.m_matchGeneration;
#ifdef HAVE_KGEOMAP
m_coordinates = other.m_coordinates;
m_coordsIsSet = other.m_coordsIsSet;
#endif
m_locked = other.m_locked;
m_dirty = other.m_dirty;
return *this;
}
MediaType DB::ImageInfo::mediaType() const
{
return m_type;
}
bool ImageInfo::isVideo() const
{
return m_type == Video;
}
void DB::ImageInfo::createFolderCategoryItem(DB::CategoryPtr folderCategory, DB::MemberMap &memberMap)
{
QString folderName = Utilities::relativeFolderName(m_fileName.relative());
if (folderName.isEmpty())
return;
if (!memberMap.contains(folderCategory->name(), folderName)) {
QStringList directories = folderName.split(QString::fromLatin1("/"));
QString curPath;
for (QStringList::ConstIterator directoryIt = directories.constBegin(); directoryIt != directories.constEnd(); ++directoryIt) {
if (curPath.isEmpty())
curPath = *directoryIt;
else {
QString oldPath = curPath;
curPath = curPath + QString::fromLatin1("/") + *directoryIt;
memberMap.addMemberToGroup(folderCategory->name(), oldPath, curPath);
}
}
folderCategory->addItem(folderName);
}
m_categoryInfomation.insert(folderCategory->name(), StringSet() << folderName);
}
void DB::ImageInfo::copyExtraData(const DB::ImageInfo &from, bool copyAngle)
{
m_categoryInfomation = from.m_categoryInfomation;
m_description = from.m_description;
// Hmm... what should the date be? orig or modified?
// _date = from._date;
if (copyAngle)
m_angle = from.m_angle;
m_rating = from.m_rating;
}
void DB::ImageInfo::removeExtraData()
{
m_categoryInfomation.clear();
m_description.clear();
m_rating = -1;
}
void ImageInfo::merge(const ImageInfo &other)
{
// Merge date
if (other.date() != m_date) {
// a fuzzy date has been set by the user and therefore "wins" over an exact date.
// two fuzzy dates can be merged
// two exact dates should ideally be cross-checked with Exif information in the file.
// Nevertheless, we merge them into a fuzzy date to avoid the complexity of checking the file.
if (other.date().isFuzzy()) {
if (m_date.isFuzzy())
m_date.extendTo(other.date());
else
m_date = other.date();
} else if (!m_date.isFuzzy()) {
m_date.extendTo(other.date());
}
// else: keep m_date
}
// Merge description
if (!other.description().isEmpty()) {
if (m_description.isEmpty())
m_description = other.description();
else if (m_description != other.description())
m_description += QString::fromUtf8("\n-----------\n") + other.m_description;
}
// Clear untagged tag if only one of the images was untagged
const QString untaggedCategory = Settings::SettingsData::instance()->untaggedCategory();
const QString untaggedTag = Settings::SettingsData::instance()->untaggedTag();
const bool isCompleted = !m_categoryInfomation[untaggedCategory].contains(untaggedTag) || !other.m_categoryInfomation[untaggedCategory].contains(untaggedTag);
// Merge tags
QSet keys = QSet::fromList(m_categoryInfomation.keys());
keys.unite(QSet::fromList(other.m_categoryInfomation.keys()));
for (const QString &key : keys) {
m_categoryInfomation[key].unite(other.m_categoryInfomation[key]);
}
// Clear untagged tag if only one of the images was untagged
if (isCompleted)
m_categoryInfomation[untaggedCategory].remove(untaggedTag);
// merge stacks:
if (isStacked() || other.isStacked()) {
DB::FileNameList stackImages;
if (!isStacked())
stackImages.append(fileName());
else
stackImages.append(DB::ImageDB::instance()->getStackFor(fileName()));
stackImages.append(DB::ImageDB::instance()->getStackFor(other.fileName()));
DB::ImageDB::instance()->unstack(stackImages);
if (!DB::ImageDB::instance()->stack(stackImages))
qCWarning(DBLog, "Could not merge stacks!");
}
}
void DB::ImageInfo::addCategoryInfo(const QString &category, const StringSet &values)
{
for (StringSet::const_iterator valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt) {
if (!m_categoryInfomation[category].contains(*valueIt)) {
m_dirty = true;
m_categoryInfomation[category].insert(*valueIt);
}
}
}
void DB::ImageInfo::clearAllCategoryInfo()
{
m_categoryInfomation.clear();
m_taggedAreas.clear();
}
void DB::ImageInfo::removeCategoryInfo(const QString &category, const StringSet &values)
{
for (StringSet::const_iterator valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt) {
if (m_categoryInfomation[category].contains(*valueIt)) {
m_dirty = true;
m_categoryInfomation[category].remove(*valueIt);
m_taggedAreas[category].remove(*valueIt);
}
}
}
void DB::ImageInfo::addCategoryInfo(const QString &category, const QString &value, const QRect &area)
{
if (!m_categoryInfomation[category].contains(value)) {
m_dirty = true;
m_categoryInfomation[category].insert(value);
if (area.isValid()) {
m_taggedAreas[category][value] = area;
}
}
}
void DB::ImageInfo::removeCategoryInfo(const QString &category, const QString &value)
{
if (m_categoryInfomation[category].contains(value)) {
m_dirty = true;
m_categoryInfomation[category].remove(value);
m_taggedAreas[category].remove(value);
}
}
void DB::ImageInfo::setPositionedTags(const QString &category, const QMap &positionedTags)
{
m_dirty = true;
m_taggedAreas[category] = positionedTags;
}
bool DB::ImageInfo::updateDateInformation(int mode) const
{
if ((mode & EXIFMODE_DATE) == 0)
return false;
if ((mode & EXIFMODE_FORCE) != 0)
return true;
return true;
}
QMap> DB::ImageInfo::taggedAreas() const
{
return m_taggedAreas;
}
QRect DB::ImageInfo::areaForTag(QString category, QString tag) const
{
// QMap::value returns a default constructed value if the key is not found:
return m_taggedAreas.value(category).value(tag);
}
-#ifdef HAVE_KGEOMAP
+#ifdef HAVE_MARBLE
Map::GeoCoordinates DB::ImageInfo::coordinates() const
{
if (m_coordsIsSet) {
return m_coordinates;
}
static const int EXIF_GPS_VERSIONID = 0;
static const int EXIF_GPS_LATREF = 1;
static const int EXIF_GPS_LAT = 2;
static const int EXIF_GPS_LONREF = 3;
static const int EXIF_GPS_LON = 4;
static const int EXIF_GPS_ALTREF = 5;
static const int EXIF_GPS_ALT = 6;
static const QString S = QString::fromUtf8("S");
static const QString W = QString::fromUtf8("W");
static QList fields;
if (fields.isEmpty()) {
// the order here matters! we use the named int constants afterwards to refer to them:
fields.append(new Exif::IntExifElement("Exif.GPSInfo.GPSVersionID")); // actually a byte value
fields.append(new Exif::StringExifElement("Exif.GPSInfo.GPSLatitudeRef"));
fields.append(new Exif::RationalExifElement("Exif.GPSInfo.GPSLatitude"));
fields.append(new Exif::StringExifElement("Exif.GPSInfo.GPSLongitudeRef"));
fields.append(new Exif::RationalExifElement("Exif.GPSInfo.GPSLongitude"));
fields.append(new Exif::IntExifElement("Exif.GPSInfo.GPSAltitudeRef")); // actually a byte value
fields.append(new Exif::RationalExifElement("Exif.GPSInfo.GPSAltitude"));
}
// read field values from database:
bool foundIt = Exif::Database::instance()->readFields(m_fileName, fields);
// if the Database query result doesn't contain exif GPS info (-> upgraded exifdb from DBVersion < 2), it is null
// if the result is int 0, then there's no exif gps information in the image
// otherwise we can proceed to parse the information
if (foundIt && fields[EXIF_GPS_VERSIONID]->value().isNull()) {
// update exif DB and repeat the search:
Exif::Database::instance()->remove(fileName());
Exif::Database::instance()->add(fileName());
Exif::Database::instance()->readFields(m_fileName, fields);
Q_ASSERT(!fields[EXIF_GPS_VERSIONID]->value().isNull());
}
Map::GeoCoordinates coords;
// gps info set?
// don't use the versionid field here, because some cameras use 0 as its value
if (foundIt && fields[EXIF_GPS_LAT]->value().toInt() != -1.0
&& fields[EXIF_GPS_LON]->value().toInt() != -1.0) {
// lat/lon/alt reference determines sign of float:
double latr = (fields[EXIF_GPS_LATREF]->value().toString() == S) ? -1.0 : 1.0;
double lat = fields[EXIF_GPS_LAT]->value().toFloat();
double lonr = (fields[EXIF_GPS_LONREF]->value().toString() == W) ? -1.0 : 1.0;
double lon = fields[EXIF_GPS_LON]->value().toFloat();
double altr = (fields[EXIF_GPS_ALTREF]->value().toInt() == 1) ? -1.0 : 1.0;
double alt = fields[EXIF_GPS_ALT]->value().toFloat();
if (lat != -1.0 && lon != -1.0) {
coords.setLatLon(latr * lat, lonr * lon);
if (alt != 0.0f) {
coords.setAlt(altr * alt);
}
}
}
m_coordinates = coords;
m_coordsIsSet = true;
return m_coordinates;
}
#endif
// vi:expandtab:tabstop=4 shiftwidth=4:
diff --git a/DB/ImageInfo.h b/DB/ImageInfo.h
index 3b69fb02..368caa95 100644
--- a/DB/ImageInfo.h
+++ b/DB/ImageInfo.h
@@ -1,247 +1,248 @@
/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef IMAGEINFO_H
#define IMAGEINFO_H
-#include "config-kpa-kgeomap.h"
+#include "config-kpa-marble.h"
#include "CategoryPtr.h"
#include "ExifMode.h"
#include "FileName.h"
#include "ImageDate.h"
+#include "Utilities/StringSet.h"
#include "MD5.h"
-#ifdef HAVE_KGEOMAP
+#ifdef HAVE_MARBLE
#include