Bug Summary

File:app/dragdrop/itemdragdrop.cpp
Warning:line 269, column 47
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name itemdragdrop.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/gilles/devel/8.x/build.scan/core/app -fcoverage-compilation-dir=/home/gilles/devel/8.x/build.scan/core/app -resource-dir /usr/lib/llvm-19/lib/clang/19 -D CMS_NO_REGISTER_KEYWORD=1 -D HAVE_FFMPEG_VERSION5 -D KF_DEPRECATED_WARNINGS_SINCE=0x70000 -D KF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x61100 -D LIBPGF_DISABLE_OPENMP -D MAGICKCORE_HDRI_ENABLE=0 -D MAGICKCORE_QUANTUM_DEPTH=16 -D QT_DEPRECATED_WARNINGS -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_FROM_BYTEARRAY -D QT_NO_CAST_TO_ASCII -D QT_NO_FOREACH -D QT_NO_KEYWORDS -D QT_NO_NARROWING_CONVERSIONS_IN_CONNECT -D QT_NO_URL_CAST_FROM_STRING -D QT_STRICT_ITERATORS -D QT_USE_QSTRINGBUILDER -D TRANSLATION_DOMAIN="digikam" -D USE_JASPER -D USE_JPEG -D USE_JPEG8 -D _GNU_SOURCE -D _LARGEFILE64_SOURCE -D digikamgui_EXPORTS -I /home/gilles/devel/8.x/build.scan/core/app -I /home/gilles/devel/8.x/core/app -I /home/gilles/devel/8.x/build.scan/core/app/gui_digikam_obj_autogen/include -I /home/gilles/devel/8.x/core/libs/video/player/qtmm -I /home/gilles/devel/8.x/core/app/main -I /home/gilles/devel/8.x/core/app/date -I /home/gilles/devel/8.x/core/app/filters -I /home/gilles/devel/8.x/core/app/dragdrop -I /home/gilles/devel/8.x/core/app/views/stack -I /home/gilles/devel/8.x/core/app/views/utils -I /home/gilles/devel/8.x/core/app/views/sidebar -I /home/gilles/devel/8.x/core/app/views/tableview -I /home/gilles/devel/8.x/core/app/items/utils -I /home/gilles/devel/8.x/core/app/items/thumbbar -I /home/gilles/devel/8.x/core/app/items/delegate -I /home/gilles/devel/8.x/core/app/items/views -I /home/gilles/devel/8.x/core/app/items/overlays -I /home/gilles/devel/8.x/core/app/views/preview -I /home/gilles/devel/8.x/core/libs/aitoolspipeline -I /home/gilles/devel/8.x/core/libs/album/engine -I /home/gilles/devel/8.x/core/libs/album/manager -I /home/gilles/devel/8.x/core/libs/album/treeview -I /home/gilles/devel/8.x/core/libs/album/widgets -I /home/gilles/devel/8.x/core/libs/autorotator -I /home/gilles/devel/8.x/core/libs/database/collection -I /home/gilles/devel/8.x/core/libs/database/coredb -I /home/gilles/devel/8.x/core/libs/database/dbjobs -I /home/gilles/devel/8.x/core/libs/database/engine -I /home/gilles/devel/8.x/core/libs/database/haar -I /home/gilles/devel/8.x/core/libs/database/history -I /home/gilles/devel/8.x/core/libs/database/item/containers -I /home/gilles/devel/8.x/core/libs/database/item/lister -I /home/gilles/devel/8.x/core/libs/database/item/query -I /home/gilles/devel/8.x/core/libs/database/item/scanner -I /home/gilles/devel/8.x/core/libs/database/models -I /home/gilles/devel/8.x/core/libs/database/server -I /home/gilles/devel/8.x/core/libs/database/similaritydb -I /home/gilles/devel/8.x/core/libs/database/tags -I /home/gilles/devel/8.x/core/libs/database/thumbsdb -I /home/gilles/devel/8.x/core/libs/database/utils/ifaces -I /home/gilles/devel/8.x/core/libs/database/utils/scan -I /home/gilles/devel/8.x/core/libs/database/utils/widgets -I /home/gilles/devel/8.x/core/libs/dialogs -I /home/gilles/devel/8.x/core/libs/dimg/color -I /home/gilles/devel/8.x/core/libs/dimg -I /home/gilles/devel/8.x/core/libs/dimg/filters/auto -I /home/gilles/devel/8.x/core/libs/dimg/filters/bcg -I /home/gilles/devel/8.x/core/libs/dimg/filters/bw -I /home/gilles/devel/8.x/core/libs/dimg/filters/cb -I /home/gilles/devel/8.x/core/libs/dimg/filters/curves -I /home/gilles/devel/8.x/core/libs/dimg/filters/decorate -I /home/gilles/devel/8.x/core/libs/dimg/filters -I /home/gilles/devel/8.x/core/libs/dimg/filters/film -I /home/gilles/devel/8.x/core/libs/dimg/filters/fx -I /home/gilles/devel/8.x/core/libs/dimg/filters/greycstoration/cimg -I /home/gilles/devel/8.x/core/libs/dimg/filters/greycstoration -I /home/gilles/devel/8.x/core/libs/dimg/filters/hotpixels -I /home/gilles/devel/8.x/core/libs/dimg/filters/hsl -I /home/gilles/devel/8.x/core/libs/dimg/filters/icc -I /home/gilles/devel/8.x/core/libs/dimg/filters/lc -I /home/gilles/devel/8.x/core/libs/dimg/filters/lens -I /home/gilles/devel/8.x/core/libs/dimg/filters/levels -I /home/gilles/devel/8.x/core/libs/dimg/filters/nr -I /home/gilles/devel/8.x/core/libs/dimg/filters/raw -I /home/gilles/devel/8.x/core/libs/dimg/filters/redeye -I /home/gilles/devel/8.x/core/libs/dimg/filters/sharp -I /home/gilles/devel/8.x/core/libs/dimg/filters/transform -I /home/gilles/devel/8.x/core/libs/dimg/filters/wb -I /home/gilles/devel/8.x/core/libs/dimg/history -I /home/gilles/devel/8.x/core/libs/dimg/loaders -I /home/gilles/devel/8.x/core/libs/dngwriter -I /home/gilles/devel/8.x/core/libs/dnnmodelmanager -I /home/gilles/devel/8.x/core/libs/dplugins/core -I /home/gilles/devel/8.x/core/libs/dplugins/iface -I /home/gilles/devel/8.x/core/libs/dplugins/setup -I /home/gilles/devel/8.x/core/libs/dplugins/webservices -I /home/gilles/devel/8.x/core/libs/dplugins/widgets -I /home/gilles/devel/8.x/core/libs/dragdrop -I /home/gilles/devel/8.x/core/libs/dtrash -I /home/gilles/devel/8.x/core/libs/facesengine/common -I /home/gilles/devel/8.x/core/libs/facesengine/detection -I /home/gilles/devel/8.x/core/libs/facesengine/detection/opencv-dnn -I /home/gilles/devel/8.x/core/libs/facesengine/facedb -I /home/gilles/devel/8.x/core/libs/facesengine/recognition -I /home/gilles/devel/8.x/core/libs/facesengine/recognition/opencv-dnn -I /home/gilles/devel/8.x/core/libs/facesengine/widgets -I /home/gilles/devel/8.x/core/libs/fileactionmanager -I /home/gilles/devel/8.x/core/libs/filters -I /home/gilles/devel/8.x/core/libs/imgqsort/detectors -I /home/gilles/devel/8.x/core/libs/imgqsort -I /home/gilles/devel/8.x/core/libs/iojobs -I /home/gilles/devel/8.x/core/libs/jpegutils -I /home/gilles/devel/8.x/core/libs/metadataengine/containers -I /home/gilles/devel/8.x/core/libs/metadataengine/dmetadata -I /home/gilles/devel/8.x/core/libs/metadataengine/engine -I /home/gilles/devel/8.x/core/libs/metadataengine/exiftool -I /home/gilles/devel/8.x/core/libs/metadataengine/focuspoint -I /home/gilles/devel/8.x/core/libs/mlfoundation -I /home/gilles/devel/8.x/core/libs/models -I /home/gilles/devel/8.x/core/libs/networkmanager -I /home/gilles/devel/8.x/core/libs/notificationmanager -I /home/gilles/devel/8.x/core/libs/onlineversion -I /home/gilles/devel/8.x/core/libs/pgfutils -I /home/gilles/devel/8.x/core/libs/progressmanager -I /home/gilles/devel/8.x/core/libs/properties/captions -I /home/gilles/devel/8.x/core/libs/properties/geolocation -I /home/gilles/devel/8.x/core/libs/properties/history -I /home/gilles/devel/8.x/core/libs/properties/import -I /home/gilles/devel/8.x/core/libs/properties -I /home/gilles/devel/8.x/core/libs/qtopencvimg -I /home/gilles/devel/8.x/core/libs/rawengine -I /home/gilles/devel/8.x/core/libs/settings -I /home/gilles/devel/8.x/core/libs/tags/autoassignment -I /home/gilles/devel/8.x/core/libs/tags/autoassignment/classifiers -I /home/gilles/devel/8.x/core/libs/tags/autoassignment/classifiers/minmax -I /home/gilles/devel/8.x/core/libs/tags/autoassignment/classifiers/multiclassyolo -I /home/gilles/devel/8.x/core/libs/tags/autoassignment/classifiers/softmax -I /home/gilles/devel/8.x/core/libs/tags/autoassignment/pipelines -I /home/gilles/devel/8.x/core/libs/tags/autoassignment/pipelines/object -I /home/gilles/devel/8.x/core/libs/tags/engine -I /home/gilles/devel/8.x/core/libs/tags/manager/models -I /home/gilles/devel/8.x/core/libs/tags/manager -I /home/gilles/devel/8.x/core/libs/tags/widgets -I /home/gilles/devel/8.x/core/libs/template -I /home/gilles/devel/8.x/core/libs/threadimageio/engine -I /home/gilles/devel/8.x/core/libs/threadimageio/fileio -I /home/gilles/devel/8.x/core/libs/threadimageio/preview -I /home/gilles/devel/8.x/core/libs/threadimageio/thumb -I /home/gilles/devel/8.x/core/libs/threadimageio/video -I /home/gilles/devel/8.x/core/libs/threads -I /home/gilles/devel/8.x/core/libs/timeadjust -I /home/gilles/devel/8.x/core/libs/transitionmngr -I /home/gilles/devel/8.x/core/libs/versionmanager -I /home/gilles/devel/8.x/core/libs/video -I /home/gilles/devel/8.x/core/libs/video/manager -I /home/gilles/devel/8.x/core/libs/video/osd -I /home/gilles/devel/8.x/core/libs/video/player -I /home/gilles/devel/8.x/core/libs/widgets/colors -I /home/gilles/devel/8.x/core/libs/widgets/combo -I /home/gilles/devel/8.x/core/libs/widgets/files -I /home/gilles/devel/8.x/core/libs/widgets/fonts -I /home/gilles/devel/8.x/core/libs/widgets/graphicsview -I /home/gilles/devel/8.x/core/libs/widgets/history -I /home/gilles/devel/8.x/core/libs/widgets/iccprofiles -I /home/gilles/devel/8.x/core/libs/widgets/itemview -I /home/gilles/devel/8.x/core/libs/widgets/layout -I /home/gilles/devel/8.x/core/libs/widgets/mainview -I /home/gilles/devel/8.x/core/libs/widgets/metadata/config -I /home/gilles/devel/8.x/core/libs/widgets/metadata/exiftool -I /home/gilles/devel/8.x/core/libs/widgets/metadata/exiv2 -I /home/gilles/devel/8.x/core/libs/widgets/metadata/labels -I /home/gilles/devel/8.x/core/libs/widgets/metadata/utils -I /home/gilles/devel/8.x/core/libs/widgets/range -I /home/gilles/devel/8.x/core/libs/widgets/text -I /home/gilles/devel/8.x/core/libs/jpegutils/libjpeg/84 -I /home/gilles/devel/8.x/core/app/utils -I /home/gilles/devel/8.x/build.scan/core/app/utils -I /home/gilles/devel/8.x/core/utilities/advancedrename -I /home/gilles/devel/8.x/core/utilities/advancedrename/common -I /home/gilles/devel/8.x/core/utilities/advancedrename/parser -I /home/gilles/devel/8.x/core/utilities/advancedrename/parser/modifiers -I /home/gilles/devel/8.x/core/utilities/advancedrename/parser/options -I /home/gilles/devel/8.x/core/utilities/advancedrename/parser/options/database -I /home/gilles/devel/8.x/core/utilities/advancedrename/parser/options/database/keys -I /home/gilles/devel/8.x/core/utilities/extrasupport/addressbook -I /home/gilles/devel/8.x/core/utilities/extrasupport/filesindexer -I /home/gilles/devel/8.x/core/utilities/facemanagement/backgroundprocesses -I /home/gilles/devel/8.x/core/utilities/facemanagement/bench -I /home/gilles/devel/8.x/core/utilities/facemanagement/database -I /home/gilles/devel/8.x/core/utilities/facemanagement/dialogs -I /home/gilles/devel/8.x/core/utilities/facemanagement/items -I /home/gilles/devel/8.x/core/utilities/facemanagement/pipelines/detectrecognize -I /home/gilles/devel/8.x/core/utilities/facemanagement/pipelines/edit -I /home/gilles/devel/8.x/core/utilities/facemanagement/pipelines -I /home/gilles/devel/8.x/core/utilities/facemanagement/pipelines/recognize -I /home/gilles/devel/8.x/core/utilities/facemanagement/pipelines/reset -I /home/gilles/devel/8.x/core/utilities/facemanagement/pipelines/retrain -I /home/gilles/devel/8.x/core/utilities/facemanagement/widgets -I /home/gilles/devel/8.x/core/utilities/firstrun -I /home/gilles/devel/8.x/core/utilities/focuspointmanagement -I /home/gilles/devel/8.x/core/utilities/fuzzysearch -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/astro -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/blendings -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/core -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/data -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/graphicsitem -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/handlers/dgml -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/handlers/kml -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/parser -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/scene -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/writer -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/writers/dgml -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/geodata/writers/kml -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/graphicsview -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/layers -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/models -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/osm -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/atmosphere -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/compass -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/crosshairs -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/graticule -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/mapscale -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/measure -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/navigation -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/overviewmap -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/render/progress -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/cache -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/gpsbabel -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/gpx -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/gpx/handlers -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/json -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/kml -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/nominatim-reversegeocoding -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm/o5mreader -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm/translators -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm/writers -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/pn2 -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/plugins/runner/pnt -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/projections -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/runners -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/settings -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/storage -I /home/gilles/devel/8.x/core/utilities/geolocation/engine/tile -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/backends -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/bookmark -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/core -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/correlator -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/dragdrop -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/items -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/lookup -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/reversegeocoding -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/tiles -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/tracks -I /home/gilles/devel/8.x/core/utilities/geolocation/geoiface/widgets -I /home/gilles/devel/8.x/core/utilities/geolocation/geomapwrapper -I /home/gilles/devel/8.x/core/utilities/geolocation/mapsearches -I /home/gilles/devel/8.x/core/utilities/imageeditor/core -I /home/gilles/devel/8.x/core/utilities/imageeditor/dialogs -I /home/gilles/devel/8.x/core/utilities/imageeditor/editor -I /home/gilles/devel/8.x/core/utilities/imageeditor/main -I /home/gilles/devel/8.x/core/utilities/imageeditor/widgets -I /home/gilles/devel/8.x/core/utilities/import/backend -I /home/gilles/devel/8.x/core/utilities/import/dialogs -I /home/gilles/devel/8.x/core/utilities/import/items -I /home/gilles/devel/8.x/core/utilities/import/main -I /home/gilles/devel/8.x/core/utilities/import/models -I /home/gilles/devel/8.x/core/utilities/import/views -I /home/gilles/devel/8.x/core/utilities/import/widgets -I /home/gilles/devel/8.x/core/utilities/lighttable -I /home/gilles/devel/8.x/core/utilities/maintenance/main -I /home/gilles/devel/8.x/core/utilities/maintenance/manager -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/dbcleaner -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/dbscan -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/duplicates -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/facesmanagement -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/fingerprints -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/imgqsort -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/metaremover -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/metasync -I /home/gilles/devel/8.x/core/utilities/maintenance/tools/thumbs -I /home/gilles/devel/8.x/core/utilities/maintenance/utils -I /home/gilles/devel/8.x/core/utilities/queuemanager/dplugins -I /home/gilles/devel/8.x/core/utilities/queuemanager/main -I /home/gilles/devel/8.x/core/utilities/queuemanager/manager -I /home/gilles/devel/8.x/core/utilities/queuemanager/views -I /home/gilles/devel/8.x/core/utilities/searchwindow -I /home/gilles/devel/8.x/core/utilities/setup/album -I /home/gilles/devel/8.x/core/utilities/setup/camera -I /home/gilles/devel/8.x/core/utilities/setup/collections -I /home/gilles/devel/8.x/core/utilities/setup/downloader -I /home/gilles/devel/8.x/core/utilities/setup/editor -I /home/gilles/devel/8.x/core/utilities/setup/metadata -I /home/gilles/devel/8.x/core/utilities/setup/misc -I /home/gilles/devel/8.x/core/utilities/setup -I /opt/qt6/include/opencv4 -I /usr/include/ImageMagick-6 -I /usr/include/x86_64-linux-gnu/ImageMagick-6 -I /opt/qt6/include/QtMultimedia -I /opt/qt6/include -I /opt/qt6/include/QtCore -I /opt/qt6/mkspecs/linux-g++ -I /opt/qt6/include/QtGui -I /opt/qt6/include/QtNetwork -I /opt/qt6/include/QtMultimediaWidgets -I /opt/qt6/include/QtWidgets -I /opt/qt6/include/QtPrintSupport -I /opt/qt6/include/QtXml -I /opt/qt6/include/QtSql -I /opt/qt6/include/KF6/KI18n -I /opt/qt6/include/KF6/Solid -I /opt/qt6/include/KF6/KWindowSystem -I /opt/qt6/include/KF6/KXmlGui -I /opt/qt6/include/KF6/KConfig -I /opt/qt6/include/KF6/KConfigCore -I /opt/qt6/include/KF6/KConfigWidgets -I /opt/qt6/include/KF6/KWidgetsAddons -I /opt/qt6/include/KF6/KConfigGui -I /opt/qt6/include/KF6/KColorScheme -I /opt/qt6/include/KF6/KGuiAddons -I /opt/qt6/include/QtDBus -I /opt/qt6/include/KF6/KService -I /opt/qt6/include/KF6/KCoreAddons -I /opt/qt6/include/KF6/KIconThemes -I /opt/qt6/include/QtWebEngineWidgets -I /opt/qt6/include/QtWebEngineCore -I /opt/qt6/include/QtQuick -I /opt/qt6/include/QtQml -I /opt/qt6/include/QtQmlIntegration -I /opt/qt6/include/QtQmlMeta -I /opt/qt6/include/QtQmlModels -I /opt/qt6/include/QtQmlWorkerScript -I /opt/qt6/include/QtOpenGL -I /opt/qt6/include/QtWebChannel -I /opt/qt6/include/KF6/KIOWidgets -I /opt/qt6/include/KF6/KIOGui -I /opt/qt6/include/KF6/KIOCore -I /opt/qt6/include/KF6/KIO -I /opt/qt6/include/KF6/KJobWidgets -I /opt/qt6/include/KF6/KCompletion -I /usr/include/gphoto2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-long-long -Wno-deprecated-copy -std=c++20 -fdeprecated-macro -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -fno-operator-names -fopenmp -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/gilles/devel/8.x/project/reports/report.scan/2025-09-05-111736-844906-1 -x c++ /home/gilles/devel/8.x/core/app/dragdrop/itemdragdrop.cpp
1/* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2009-04-16
7 * Description : Qt Model for Items - drag and drop handling
8 *
9 * SPDX-FileCopyrightText: 2002-2005 by Renchi Raju <renchi dot raju at gmail dot com>
10 * SPDX-FileCopyrightText: 2020-2025 by Maik Qualmann <metzpinguin at gmail dot com>
11 * SPDX-FileCopyrightText: 2002-2025 by Gilles Caulier <caulier dot gilles at gmail dot com>
12 * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
13 * SPDX-FileCopyrightText: 2009 by Andi Clemens <andi dot clemens at gmail dot com>
14 * SPDX-FileCopyrightText: 2013 by Michael G. Hansen <mike at mghansen dot de>
15 *
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 *
18 * ============================================================ */
19
20#include "itemdragdrop.h"
21
22// Qt includes
23
24#include <QDropEvent>
25#include <QMenu>
26#include <QIcon>
27#include <QApplication>
28
29// KDE includes
30
31#include <klocalizedstring.h>
32
33// Local includes
34
35#include "digikam_debug.h"
36#include "albummanager.h"
37#include "importui.h"
38#include "importiconview.h"
39#include "itemthumbnailbar.h"
40#include "ddragobjects.h"
41#include "dio.h"
42#include "itemcategorizedview.h"
43#include "iteminfolist.h"
44#include "tableview_treeview.h"
45#include "digikamitemview.h"
46#include "facetags.h"
47
48namespace Digikam
49{
50
51enum DropAction
52{
53 NoAction,
54 CopyAction,
55 MoveAction,
56 GroupAction,
57 SortAction,
58 GroupAndMoveAction,
59 AssignTagAction
60};
61
62static QAction* addGroupAction(QMenu* const menu)
63{
64 return menu->addAction(QIcon::fromTheme(QLatin1String("go-bottom")),
65 i18nc("@action:inmenu Group images with this item",i18ndc("digikam", "@action:inmenu Group images with this item"
, "Group here")
66 "Group here")i18ndc("digikam", "@action:inmenu Group images with this item"
, "Group here")
);
67}
68
69static QAction* addSortAction(QMenu* const menu)
70{
71 return menu->addAction(QIcon::fromTheme(QLatin1String("insert-image")),
72 i18nc("@action:inmenu Insert dragged images before this item",i18ndc("digikam", "@action:inmenu Insert dragged images before this item"
, "Insert Items here")
73 "Insert Items here")i18ndc("digikam", "@action:inmenu Insert dragged images before this item"
, "Insert Items here")
);
74}
75
76static QAction* addGroupAndMoveAction(QMenu* const menu)
77{
78 return menu->addAction(QIcon::fromTheme(QLatin1String("go-bottom")),
79 i18nc("@action:inmenu Group images with this item and move them to its album",i18ndc("digikam", "@action:inmenu Group images with this item and move them to its album"
, "Group here and move to album")
80 "Group here and move to album")i18ndc("digikam", "@action:inmenu Group images with this item and move them to its album"
, "Group here and move to album")
);
81}
82
83static QAction* addCancelAction(QMenu* const menu)
84{
85 return menu->addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("C&ancel")i18nd("digikam", "C&ancel"));
86}
87
88static DropAction copyOrMove(const QDropEvent* const e,
89 QWidget* const view,
90 bool allowMove = true,
91 bool askForGrouping = false)
92{
93
94#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
95
96 if (e->modifiers() & Qt::ControlModifier)
97
98#else
99
100 if (e->keyboardModifiers() & Qt::ControlModifier)
101
102#endif
103
104 {
105 return CopyAction;
106 }
107
108#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
109
110 else if (e->modifiers() & Qt::ShiftModifier)
111
112#else
113
114 else if (e->keyboardModifiers() & Qt::ShiftModifier)
115
116#endif
117
118 {
119 return MoveAction;
120 }
121
122 if (!allowMove && !askForGrouping)
123 {
124 switch (e->proposedAction())
125 {
126 case Qt::CopyAction:
127 {
128 return CopyAction;
129 }
130
131 case Qt::MoveAction:
132 {
133 return MoveAction;
134 }
135
136 default:
137 {
138 return NoAction;
139 }
140 }
141 }
142
143 QMenu popMenu(view);
144
145 QAction* moveAction = nullptr;
146
147 if (allowMove)
148 {
149 moveAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("go-jump")), i18n("&Move Here")i18nd("digikam", "&Move Here"));
150 }
151
152 QAction* const copyAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("edit-copy")), i18n("&Copy Here")i18nd("digikam", "&Copy Here"));
153 popMenu.addSeparator();
154
155 QAction* groupAction = nullptr;
156 QAction* groupAndMoveAction = nullptr;
157
158 if (askForGrouping)
159 {
160 groupAction = addGroupAction(&popMenu);
161 groupAndMoveAction = addGroupAndMoveAction(&popMenu);
162 popMenu.addSeparator();
163 }
164
165 addCancelAction(&popMenu);
166
167 popMenu.setMouseTracking(true);
168 qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->restoreOverrideCursor();
169
170#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
171
172 QAction* const choice = popMenu.exec(view->mapToGlobal(e->position().toPoint()));
173
174#else
175
176 QAction* const choice = popMenu.exec(view->mapToGlobal(e->pos()));
177
178#endif
179
180 if (moveAction && (choice == moveAction))
181 {
182 return MoveAction;
183 }
184 else if (choice == copyAction)
185 {
186 return CopyAction;
187 }
188 else if (groupAction && (choice == groupAction))
189 {
190 return GroupAction;
191 }
192 else if (groupAndMoveAction && (choice == groupAndMoveAction))
193 {
194 return GroupAndMoveAction;
195 }
196
197 return NoAction;
198}
199
200static DropAction tagAction(const QDropEvent* const e, QWidget* const view, bool askForGrouping)
201{
202 QMenu popMenu(view);
203 QAction* const tagAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("tag")),
204 i18n("Assign Tag to Dropped Items")i18nd("digikam", "Assign Tag to Dropped Items"));
205 QAction* groupAction = nullptr;
206
207 if (askForGrouping)
208 {
209 popMenu.addSeparator();
210 groupAction = addGroupAction(&popMenu);
211 }
212
213 popMenu.addSeparator();
214 addCancelAction(&popMenu);
215
216 popMenu.setMouseTracking(true);
217 qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->restoreOverrideCursor();
218
219#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
220
221 QAction* const choice = popMenu.exec(view->mapToGlobal(e->position().toPoint()));
222
223#else
224
225 QAction* const choice = popMenu.exec(view->mapToGlobal(e->pos()));
226
227#endif
228
229 if (groupAction && (choice == groupAction))
230 {
231 return GroupAction;
232 }
233 else if (tagAction && (choice == tagAction))
234 {
235 return AssignTagAction;
236 }
237
238 return NoAction;
239}
240
241static DropAction s_groupAction(const QDropEvent* const e, QWidget* const view)
242{
243 ItemCategorizedView* const imgView = dynamic_cast<ItemCategorizedView*>(view);
244 int sortOrder = ApplicationSettings::instance()->getImageSortOrder();
245
246 QMenu popMenu(view);
247 QAction* sortAction = nullptr;
248
249 if (imgView
30.1
'imgView' is null
&&
250 (
251 (sortOrder == ItemSortSettings::SortByManualOrderAndName) ||
252 (sortOrder == ItemSortSettings::SortByManualOrderAndDate)
253 )
254 )
255 {
256 sortAction = addSortAction(&popMenu);
257 popMenu.addSeparator();
258 }
259
260 QAction* const groupAction = addGroupAction(&popMenu);
261 popMenu.addSeparator();
262 addCancelAction(&popMenu);
263
264 popMenu.setMouseTracking(true);
265 qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->restoreOverrideCursor();
266
267#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
268
269 QAction* const choice = popMenu.exec(view->mapToGlobal(e->position().toPoint()));
31
Called C++ object pointer is null
270
271#else
272
273 QAction* const choice = popMenu.exec(view->mapToGlobal(e->pos()));
274
275#endif
276
277 if (groupAction && (choice == groupAction))
278 {
279 return GroupAction;
280 }
281
282 if (sortAction && (choice == sortAction))
283 {
284 return SortAction;
285 }
286
287 return NoAction;
288}
289
290// -------------------------------------------------------------------------------------
291
292ItemDragDropHandler::ItemDragDropHandler(ItemModel* const model)
293 : AbstractItemDragDropHandler(model)
294{
295}
296
297ItemModel* ItemDragDropHandler::model() const
298{
299 return static_cast<ItemModel*>(m_model);
300}
301
302ItemAlbumModel* ItemDragDropHandler::albumModel() const
303{
304 return qobject_cast<ItemAlbumModel*>(model());
305}
306
307void ItemDragDropHandler::setReadOnlyDrop(bool readOnly)
308{
309 m_readOnly = readOnly;
310}
311
312bool ItemDragDropHandler::dropEvent(QAbstractItemView* abstractview, const QDropEvent* e, const QModelIndex& droppedOn)
313{
314 Album* album = nullptr;
315
316 // Note that the drop event does not have to be in an ItemCategorizedView.
317 // It can also be a TableViewTreeView.
318
319 ItemCategorizedView* const view = qobject_cast<ItemCategorizedView*>(abstractview);
1
'view' initialized here
320
321 if (view)
2
Assuming 'view' is null
3
Taking false branch
322 {
323
324#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
325
326 album = view->albumAt(e->position().toPoint());
327
328#else
329
330 album = view->albumAt(e->pos());
331
332#endif
333
334 }
335 else
336 {
337 TableViewTreeView* const tableViewTreeView = qobject_cast<TableViewTreeView*>(abstractview);
338
339 if (tableViewTreeView)
4
Assuming 'tableViewTreeView' is non-null
5
Taking true branch
340 {
341
342#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
343
344 album = tableViewTreeView->albumAt(e->position().toPoint());
345
346#else
347
348 album = tableViewTreeView->albumAt(e->pos());
349
350#endif
351
352 }
353 }
354
355 // unless we are readonly anyway, we always want an album
356
357 if (!m_readOnly && (!album || album->isRoot()))
6
Assuming field 'm_readOnly' is false
7
Assuming 'album' is non-null
8
Assuming the condition is false
9
Taking false branch
358 {
359 return false;
360 }
361
362 PAlbum* palbum = nullptr;
363 TAlbum* talbum = nullptr;
364
365 if (album
9.1
'album' is non-null
)
10
Taking true branch
366 {
367 Album* currentAlbum = nullptr;
368
369 if (albumModel() && !(albumModel()->currentAlbums().isEmpty()))
11
Assuming the condition is false
12
Taking false branch
370 {
371 currentAlbum = albumModel()->currentAlbums().first();
372 }
373
374 if (album->type() == Album::PHYSICAL)
13
Assuming the condition is false
375 {
376 palbum = static_cast<PAlbum*>(album);
377 }
378 else if (currentAlbum
13.1
'currentAlbum' is null
&& (currentAlbum->type() == Album::PHYSICAL))
379 {
380 palbum = static_cast<PAlbum*>(currentAlbum);
381 }
382
383 if (album->type() == Album::TAG)
14
Assuming the condition is false
384 {
385 talbum = static_cast<TAlbum*>(album);
386 }
387 else if (currentAlbum
14.1
'currentAlbum' is null
&& (currentAlbum->type() == Album::TAG))
388 {
389 talbum = static_cast<TAlbum*>(currentAlbum);
390 }
391 }
392
393 if (DItemDrag::canDecode(e->mimeData()))
15
Assuming the condition is true
16
Taking true branch
394 {
395 // Drag & drop inside of digiKam
396
397 QList<QUrl> urls;
398 QList<int> albumIDs;
399 QList<qlonglong> imageIDs;
400
401 if (!DItemDrag::decode(e->mimeData(), urls, albumIDs, imageIDs))
17
Assuming the condition is false
402 {
403 return false;
404 }
405
406 if (urls.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
18
Assuming the condition is false
19
Assuming the condition is false
20
Assuming the condition is false
21
Taking false branch
407 {
408 return false;
409 }
410
411 DropAction action = NoAction;
412
413 ItemInfo droppedOnInfo;
414
415 if (droppedOn.isValid())
22
Taking true branch
416 {
417 ItemThumbnailBar* const thumbBar = qobject_cast<ItemThumbnailBar*>(abstractview);
418
419 if (thumbBar)
23
Assuming 'thumbBar' is null
24
Taking false branch
420 {
421 droppedOnInfo = model()->imageInfo(thumbBar->itemFilterModel()->mapToSourceItemModel(droppedOn));
422 }
423 else
424 {
425 droppedOnInfo = model()->imageInfo(droppedOn);
426 }
427 }
428
429 if (m_readOnly
24.1
Field 'm_readOnly' is false
)
25
Taking false branch
430 {
431 Q_EMIT itemInfosDropped(ItemInfoList(imageIDs));
432
433 return true;
434 }
435 else if (palbum
25.1
'palbum' is null
)
26
Taking false branch
436 {
437 // Check if items dropped come from outside current album.
438
439 QList<ItemInfo> extImages, intImages;
440
441 for (QList<qlonglong>::const_iterator it = imageIDs.constBegin() ;
442 it != imageIDs.constEnd() ; ++it)
443 {
444 ItemInfo info(*it);
445
446 if (info.albumId() != album->id())
447 {
448 extImages << info;
449 }
450 else
451 {
452 intImages << info;
453 }
454 }
455
456 bool onlyExternal = (intImages.isEmpty() && !extImages.isEmpty());
457 bool onlyInternal = (!intImages.isEmpty() && extImages.isEmpty());
458 bool mixed = (!intImages.isEmpty() && !extImages.isEmpty());
459
460 // Check for drop of image on itself
461
462 if (
463 (intImages.size() == 1) &&
464 (intImages.first() == droppedOnInfo)
465 )
466 {
467 return false;
468 }
469
470 if (
471 onlyInternal &&
472 droppedOn.isValid() &&
473
474#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
475
476 (e->modifiers() == Qt::NoModifier)
477
478#else
479
480 (e->keyboardModifiers() == Qt::NoModifier)
481
482#endif
483 )
484
485 {
486 action = s_groupAction(e, view);
487 }
488 else
489 {
490 // Determine action. Show Menu only if there are any album-external items.
491 // Ask for grouping if dropped-on is valid (gives LinkAction)
492
493 action = copyOrMove(e, view, mixed || onlyExternal, !droppedOnInfo.isNull());
494 }
495
496 if (onlyExternal)
497 {
498 // Only external items: copy or move as requested
499
500 if (action == MoveAction)
501 {
502 DIO::move(extImages, palbum);
503 return true;
504 }
505 else if (action == CopyAction)
506 {
507 DIO::copy(extImages, palbum);
508 return true;
509 }
510 }
511 else if (onlyInternal)
512 {
513 // Only items from the current album:
514 // Move is a no-op. Do not show menu to ask for copy or move.
515 // If the user indicates a copy operation (holding Ctrl), copy.
516
517 if (action == CopyAction)
518 {
519 DIO::copy(intImages, palbum);
520 return true;
521 }
522 else if (action == MoveAction)
523 {
524 return false;
525 }
526 }
527 else if (mixed)
528 {
529 // Mixed items.
530 // For move operations, ignore items from current album.
531 // If user requests copy, copy.
532
533 if (action == MoveAction)
534 {
535 DIO::move(extImages, palbum);
536 return true;
537 }
538 else if (action == CopyAction)
539 {
540 DIO::copy(extImages + intImages, palbum);
541 return true;
542 }
543 }
544 }
545 else if (talbum
26.1
'talbum' is null
)
27
Taking false branch
546 {
547 if (talbum->hasProperty(TagPropertyName::person()))
548 {
549 return false;
550 }
551
552 action = tagAction(e, view, droppedOn.isValid());
553
554 if (action == AssignTagAction)
555 {
556 Q_EMIT assignTags(ItemInfoList(imageIDs), QList<int>() << talbum->id());
557
558 return true;
559 }
560 }
561 else
562 {
563 if (droppedOn.isValid())
28
Taking true branch
564 {
565 // Ask if the user wants to group
566
567 action = s_groupAction(e, view);
29
Passing null pointer value via 2nd parameter 'view'
30
Calling 's_groupAction'
568 }
569 }
570
571 if (action == GroupAction)
572 {
573 if (droppedOnInfo.isNull())
574 {
575 return false;
576 }
577
578 Q_EMIT addToGroup(droppedOnInfo, ItemInfoList(imageIDs));
579
580 return true;
581 }
582
583 if (action == SortAction)
584 {
585 if (droppedOnInfo.isNull())
586 {
587 return false;
588 }
589
590 Q_EMIT dragDropSort(droppedOnInfo, ItemInfoList(imageIDs));
591
592 return true;
593 }
594
595 if (action == GroupAndMoveAction)
596 {
597 if (droppedOnInfo.isNull())
598 {
599 return false;
600 }
601
602 Q_EMIT addToGroup(droppedOnInfo, ItemInfoList(imageIDs));
603
604 DIO::move(ItemInfoList(imageIDs), palbum);
605
606 return true;
607 }
608
609 return false;
610 }
611 else if (e->mimeData()->hasUrls())
612 {
613 if (!palbum && !m_readOnly)
614 {
615 return false;
616 }
617
618 // Drag & drop outside of digiKam
619
620 QList<QUrl> srcURLs = e->mimeData()->urls();
621
622 if (m_readOnly)
623 {
624 Q_EMIT urlsDropped(srcURLs);
625
626 return true;
627 }
628
629 DropAction action = copyOrMove(e, view);
630
631 if (action == MoveAction)
632 {
633 DIO::move(srcURLs, palbum);
634 }
635 else if (action == CopyAction)
636 {
637 DIO::copy(srcURLs, palbum);
638 }
639
640 return true;
641 }
642 else if (DTagListDrag::canDecode(e->mimeData()))
643 {
644 QList<int> tagIDs;
645 bool isDecoded = DTagListDrag::decode(e->mimeData(), tagIDs);
646
647 if (!isDecoded)
648 {
649 qCDebug(DIGIKAM_GENERAL_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_GENERAL_LOG)()); qt_category; qt_category.control =
false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/app/dragdrop/itemdragdrop.cpp"
), 649, static_cast<const char *>(__PRETTY_FUNCTION__),
qt_category.name()).debug()
<< "Error: Decoding failed!";
650 return false;
651 }
652
653 if (!view)
654 {
655 qCDebug(DIGIKAM_GENERAL_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_GENERAL_LOG)()); qt_category; qt_category.control =
false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/app/dragdrop/itemdragdrop.cpp"
), 655, static_cast<const char *>(__PRETTY_FUNCTION__),
qt_category.name()).debug()
<< "Error: View is null!";
656 return false;
657 }
658
659 // Face tags
660
661 if (talbum && talbum->hasProperty(TagPropertyName::person()))
662 {
663 if (
664 (tagIDs.first() == FaceTags::unconfirmedPersonTagId()) ||
665 (tagIDs.first() == FaceTags::unknownPersonTagId()) ||
666 !FaceTags::isPerson(tagIDs.first())
667 )
668 {
669 return false;
670 }
671
672 DigikamItemView* const dview = qobject_cast<DigikamItemView*>(abstractview);
673
674 if ((dview == nullptr) || !droppedOn.isValid())
675 {
676 return false;
677 }
678
679 QMenu popFaceTagMenu(dview);
680
681 QAction* assignFace = nullptr;
682 QAction* assignFaces = nullptr;
683
684 if (dview->selectionModel()->selectedIndexes().size() > 1)
685 {
686 assignFaces = popFaceTagMenu.addAction(QIcon::fromTheme(QLatin1String("tag")), i18n("Change Face Tags")i18nd("digikam", "Change Face Tags"));
687 }
688 else
689 {
690 assignFace = popFaceTagMenu.addAction(QIcon::fromTheme(QLatin1String("tag")), i18n("Change Face Tag")i18nd("digikam", "Change Face Tag"));
691 }
692
693 popFaceTagMenu.addSeparator();
694 popFaceTagMenu.addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("&Cancel")i18nd("digikam", "&Cancel"));
695 popFaceTagMenu.setMouseTracking(true);
696 qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->restoreOverrideCursor();
697
698#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
699
700 QAction* const res = popFaceTagMenu.exec(dview->mapToGlobal(e->position().toPoint()));
701
702#else
703
704 QAction* const res = popFaceTagMenu.exec(dview->mapToGlobal(e->pos()));
705
706#endif
707
708 if (res)
709 {
710 if (res == assignFace)
711 {
712 dview->confirmFaces({droppedOn}, tagIDs.first());
713 }
714 else if (res == assignFaces)
715 {
716 dview->confirmFaces(dview->selectionModel()->selectedIndexes(), tagIDs.first());
717 }
718 }
719
720 return true;
721 }
722
723 // Standard tags
724
725 QMenu popMenu(view);
726
727 QList<ItemInfo> selectedInfos = view->selectedItemInfosCurrentFirst();
728 QAction* assignToSelectedAction = nullptr;
729
730 if (selectedInfos.count() > 1)
731 {
732 assignToSelectedAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("tag")),
733 i18n("Assign Tags to &Selected Items")i18nd("digikam", "Assign Tags to &Selected Items"));
734 }
735
736 QAction* assignToThisAction = nullptr;
737
738 if (droppedOn.isValid())
739 {
740 assignToThisAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("tag")),
741 i18n("Assign Tags to &This Item")i18nd("digikam", "Assign Tags to &This Item"));
742 }
743
744 QAction* const assignToAllAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("tag")),
745 i18n("Assign Tags to &All Items")i18nd("digikam", "Assign Tags to &All Items"));
746
747 popMenu.addSeparator();
748 popMenu.addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("&Cancel")i18nd("digikam", "&Cancel"));
749
750 popMenu.setMouseTracking(true);
751 qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->restoreOverrideCursor();
752
753#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
754
755 QAction* const choice = popMenu.exec(view->mapToGlobal(e->position().toPoint()));
756
757#else
758
759 QAction* const choice = popMenu.exec(view->mapToGlobal(e->pos()));
760
761#endif
762
763 if (choice)
764 {
765 if (choice == assignToSelectedAction) // Selected Items
766 {
767 Q_EMIT assignTags(selectedInfos, tagIDs);
768 }
769 else if (choice == assignToAllAction) // All Items
770 {
771 Q_EMIT assignTags(view->allItemInfos(), tagIDs);
772 }
773 else if (choice == assignToThisAction) // Dropped item only.
774 {
775 QModelIndex dropIndex = droppedOn;
776 ItemThumbnailBar* const thumbBar = qobject_cast<ItemThumbnailBar*>(abstractview);
777
778 if (thumbBar)
779 {
780 dropIndex = thumbBar->itemFilterModel()->mapToSourceItemModel(droppedOn);
781 }
782
783 Q_EMIT assignTags(QList<ItemInfo>() << model()->imageInfo(dropIndex), tagIDs);
784 }
785 }
786
787 return true;
788 }
789 else if (DCameraItemListDrag::canDecode(e->mimeData()))
790 {
791 if (!palbum)
792 {
793 return false;
794 }
795
796 ImportIconView* const iconView = dynamic_cast<ImportIconView*>(e->source());
797
798 if (!iconView)
799 {
800 return false;
801 }
802
803 QMenu popMenu(iconView);
804 popMenu.addSection(QIcon::fromTheme(QLatin1String("digikam")), i18n("Importing")i18nd("digikam", "Importing"));
805 QAction* const downAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("get-hot-new-stuff")),
806 i18n("Download From Camera")i18nd("digikam", "Download From Camera"));
807 QAction* const downDelAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("get-hot-new-stuff")),
808 i18n("Download && Delete From Camera")i18nd("digikam", "Download && Delete From Camera"));
809 popMenu.addSeparator();
810 popMenu.addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("C&ancel")i18nd("digikam", "C&ancel"));
811 popMenu.setMouseTracking(true);
812 qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->restoreOverrideCursor();
813
814#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
815
816 QAction* const choice = popMenu.exec(iconView->mapToGlobal(e->position().toPoint()));
817
818#else
819
820 QAction* const choice = popMenu.exec(iconView->mapToGlobal(e->pos()));
821
822#endif
823
824 if (choice)
825 {
826 if (choice == downAction)
827 {
828 ImportUI::instance()->slotDownload(true, false, palbum);
829 }
830 else if (choice == downDelAction)
831 {
832 ImportUI::instance()->slotDownload(true, true, palbum);
833 }
834 }
835
836 return true;
837 }
838
839 return false;
840}
841
842Qt::DropAction ItemDragDropHandler::accepts(const QDropEvent* e, const QModelIndex& /*dropIndex*/)
843{
844 if (albumModel() && albumModel()->currentAlbums().isEmpty())
845 {
846 return Qt::IgnoreAction;
847 }
848
849 if (DItemDrag::canDecode(e->mimeData()) || e->mimeData()->hasUrls())
850 {
851
852#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
853
854 if (e->modifiers() & Qt::ControlModifier)
855
856#else
857
858 if (e->keyboardModifiers() & Qt::ControlModifier)
859
860#endif
861
862 {
863 return Qt::CopyAction;
864 }
865
866#if (QT_VERSION((6<<16)|(9<<8)|(2)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0)))
867
868 else if (e->modifiers() & Qt::ShiftModifier)
869
870#else
871
872 else if (e->keyboardModifiers() & Qt::ShiftModifier)
873
874#endif
875
876 {
877 return Qt::MoveAction;
878 }
879
880 return Qt::MoveAction;
881 }
882
883 if (
884 DTagListDrag::canDecode(e->mimeData()) ||
885 DCameraItemListDrag::canDecode(e->mimeData()) ||
886 DCameraDragObject::canDecode(e->mimeData())
887 )
888 {
889 return Qt::MoveAction;
890 }
891
892 return Qt::IgnoreAction;
893}
894
895QStringList ItemDragDropHandler::mimeTypes() const
896{
897 QStringList mimeTypes;
898
899 mimeTypes << DItemDrag::mimeTypes()
900 << DTagListDrag::mimeTypes()
901 << DCameraItemListDrag::mimeTypes()
902 << DCameraDragObject::mimeTypes()
903 << QLatin1String("text/uri-list");
904
905 return mimeTypes;
906}
907
908QMimeData* ItemDragDropHandler::createMimeData(const QList<QModelIndex>& indexes)
909{
910 QList<ItemInfo> infos = model()->imageInfos(indexes);
911
912 QList<QUrl> urls;
913 QList<int> albumIDs;
914 QList<qlonglong> imageIDs;
915
916 for (const ItemInfo& info : std::as_const(infos))
917 {
918 urls.append(info.fileUrl());
919 albumIDs.append(info.albumId());
920 imageIDs.append(info.id());
921 }
922
923 if (urls.isEmpty())
924 {
925 return nullptr;
926 }
927
928 return new DItemDrag(urls, albumIDs, imageIDs);
929}
930
931} // namespace Digikam
932
933#include "moc_itemdragdrop.cpp"