summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libs/3rdparty/3rdparty.pro6
-rw-r--r--src/libs/3rdparty/7zip/7zip.pri (renamed from src/libs/7zip/7zip.pri)0
-rw-r--r--src/libs/3rdparty/7zip/7zip.pro (renamed from src/libs/7zip/7zip.pro)2
-rw-r--r--src/libs/3rdparty/7zip/COPYING15
-rw-r--r--src/libs/3rdparty/7zip/installer_framework_changes.txt (renamed from src/libs/7zip/installer_framework_changes.txt)0
-rw-r--r--src/libs/3rdparty/7zip/qt_attribution.json13
-rw-r--r--src/libs/3rdparty/7zip/unix/C/7zCrc.c (renamed from src/libs/7zip/unix/C/7zCrc.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/7zCrc.h (renamed from src/libs/7zip/unix/C/7zCrc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/7zCrcOpt.c (renamed from src/libs/7zip/unix/C/7zCrcOpt.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/7zStream.c (renamed from src/libs/7zip/unix/C/7zStream.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/7zTypes.h (renamed from src/libs/7zip/unix/C/7zTypes.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/7zVersion.h (renamed from src/libs/7zip/unix/C/7zVersion.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Alloc.c (renamed from src/libs/7zip/unix/C/Alloc.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Alloc.h (renamed from src/libs/7zip/unix/C/Alloc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Bra.c (renamed from src/libs/7zip/unix/C/Bra.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Bra.h (renamed from src/libs/7zip/unix/C/Bra.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Bra86.c (renamed from src/libs/7zip/unix/C/Bra86.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/BraIA64.c (renamed from src/libs/7zip/unix/C/BraIA64.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/C.pri (renamed from src/libs/7zip/unix/C/C.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Compiler.h (renamed from src/libs/7zip/unix/C/Compiler.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/CpuArch.h (renamed from src/libs/7zip/unix/C/CpuArch.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Delta.c (renamed from src/libs/7zip/unix/C/Delta.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Delta.h (renamed from src/libs/7zip/unix/C/Delta.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzFind.c (renamed from src/libs/7zip/unix/C/LzFind.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzFind.h (renamed from src/libs/7zip/unix/C/LzFind.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzFindMt.c (renamed from src/libs/7zip/unix/C/LzFindMt.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzFindMt.h (renamed from src/libs/7zip/unix/C/LzFindMt.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzHash.h (renamed from src/libs/7zip/unix/C/LzHash.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Lzma2Dec.c (renamed from src/libs/7zip/unix/C/Lzma2Dec.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Lzma2Dec.h (renamed from src/libs/7zip/unix/C/Lzma2Dec.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Lzma2Enc.c (renamed from src/libs/7zip/unix/C/Lzma2Enc.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Lzma2Enc.h (renamed from src/libs/7zip/unix/C/Lzma2Enc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzmaDec.c (renamed from src/libs/7zip/unix/C/LzmaDec.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzmaDec.h (renamed from src/libs/7zip/unix/C/LzmaDec.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzmaEnc.c (renamed from src/libs/7zip/unix/C/LzmaEnc.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/LzmaEnc.h (renamed from src/libs/7zip/unix/C/LzmaEnc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/MtCoder.c (renamed from src/libs/7zip/unix/C/MtCoder.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/MtCoder.h (renamed from src/libs/7zip/unix/C/MtCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Precomp.h (renamed from src/libs/7zip/unix/C/Precomp.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/RotateDefs.h (renamed from src/libs/7zip/unix/C/RotateDefs.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Sha256.c (renamed from src/libs/7zip/unix/C/Sha256.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Sha256.h (renamed from src/libs/7zip/unix/C/Sha256.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Threads.c (renamed from src/libs/7zip/unix/C/Threads.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Threads.h (renamed from src/libs/7zip/unix/C/Threads.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Xz.c (renamed from src/libs/7zip/unix/C/Xz.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/Xz.h (renamed from src/libs/7zip/unix/C/Xz.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzCrc64.c (renamed from src/libs/7zip/unix/C/XzCrc64.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzCrc64.h (renamed from src/libs/7zip/unix/C/XzCrc64.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzCrc64Opt.c (renamed from src/libs/7zip/unix/C/XzCrc64Opt.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzDec.c (renamed from src/libs/7zip/unix/C/XzDec.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzEnc.c (renamed from src/libs/7zip/unix/C/XzEnc.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzEnc.h (renamed from src/libs/7zip/unix/C/XzEnc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/C/XzIn.c (renamed from src/libs/7zip/unix/C/XzIn.c)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/7zip.pri (renamed from src/libs/7zip/unix/CPP/7zip/7zip.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7z.pri (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zIn.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zItem.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zOut.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zProperties.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Archive.pri (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/Common.pri (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/IArchive.h (renamed from src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/XzHandler.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CWrappers.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CWrappers.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/Common.pri (renamed from src/libs/7zip/unix/CPP/7zip/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CreateCoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CreateCoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FileStreams.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FileStreams.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilterCoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilterCoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InBuffer.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InBuffer.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LimitedStreams.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LockedStream.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/LockedStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LockedStream.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/LockedStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodId.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/MethodId.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodProps.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodProps.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/OutBuffer.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/OutBuffer.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/ProgressUtils.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/PropId.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/RegisterArc.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/RegisterCodec.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamBinder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamBinder.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamObjects.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamObjects.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamUtils.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamUtils.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/UniqBlocks.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/VirtThread.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Common/VirtThread.h (renamed from src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Register.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Register.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjCoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BcjCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjCoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BcjCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjRegister.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BcjRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchCoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BranchCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchCoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BranchCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchMisc.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchRegister.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/BranchRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/ByteSwap.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/ByteSwap.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Compress.pri (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyCoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyRegister.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/CopyRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Register.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Register.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaRegister.cpp (renamed from src/libs/7zip/unix/CPP/7zip/Compress/LzmaRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/RangeCoder.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h (renamed from src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/Guid.txt (renamed from src/libs/7zip/unix/CPP/7zip/Guid.txt)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/ICoder.h (renamed from src/libs/7zip/unix/CPP/7zip/ICoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/IDecl.h (renamed from src/libs/7zip/unix/CPP/7zip/IDecl.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/IPassword.h (renamed from src/libs/7zip/unix/CPP/7zip/IPassword.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/IProgress.h (renamed from src/libs/7zip/unix/CPP/7zip/IProgress.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/IStream.h (renamed from src/libs/7zip/unix/CPP/7zip/IStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/PropID.h (renamed from src/libs/7zip/unix/CPP/7zip/PropID.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Common.pri (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DefaultName.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DirItem.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Extract.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Extract.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/HashCalc.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Property.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SetProperties.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SortUtils.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/TempFiles.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Update.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Update.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/Console.pri (renamed from src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp (renamed from src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h (renamed from src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/ComTry.h (renamed from src/libs/7zip/unix/CPP/Common/ComTry.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/CommandLineParser.cpp (renamed from src/libs/7zip/unix/CPP/Common/CommandLineParser.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/CommandLineParser.h (renamed from src/libs/7zip/unix/CPP/Common/CommandLineParser.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/Common.h (renamed from src/libs/7zip/unix/CPP/Common/Common.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/Common.pri (renamed from src/libs/7zip/unix/CPP/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/Defs.h (renamed from src/libs/7zip/unix/CPP/Common/Defs.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/IntToString.cpp (renamed from src/libs/7zip/unix/CPP/Common/IntToString.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/IntToString.h (renamed from src/libs/7zip/unix/CPP/Common/IntToString.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/ListFileUtils.cpp (renamed from src/libs/7zip/unix/CPP/Common/ListFileUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/ListFileUtils.h (renamed from src/libs/7zip/unix/CPP/Common/ListFileUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyBuffer.h (renamed from src/libs/7zip/unix/CPP/Common/MyBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyCom.h (renamed from src/libs/7zip/unix/CPP/Common/MyCom.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyException.h (renamed from src/libs/7zip/unix/CPP/Common/MyException.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyGuidDef.h (renamed from src/libs/7zip/unix/CPP/Common/MyGuidDef.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyInitGuid.h (renamed from src/libs/7zip/unix/CPP/Common/MyInitGuid.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyString.cpp (renamed from src/libs/7zip/unix/CPP/Common/MyString.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyString.h (renamed from src/libs/7zip/unix/CPP/Common/MyString.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyTypes.h (renamed from src/libs/7zip/unix/CPP/Common/MyTypes.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyUnknown.h (renamed from src/libs/7zip/unix/CPP/Common/MyUnknown.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyVector.h (renamed from src/libs/7zip/unix/CPP/Common/MyVector.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyWindows.cpp (renamed from src/libs/7zip/unix/CPP/Common/MyWindows.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/MyWindows.h (renamed from src/libs/7zip/unix/CPP/Common/MyWindows.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/NewHandler.cpp (renamed from src/libs/7zip/unix/CPP/Common/NewHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/NewHandler.h (renamed from src/libs/7zip/unix/CPP/Common/NewHandler.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/StdOutStream.cpp (renamed from src/libs/7zip/unix/CPP/Common/StdOutStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/StdOutStream.h (renamed from src/libs/7zip/unix/CPP/Common/StdOutStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/StringConvert.cpp (renamed from src/libs/7zip/unix/CPP/Common/StringConvert.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/StringConvert.h (renamed from src/libs/7zip/unix/CPP/Common/StringConvert.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/StringToInt.cpp (renamed from src/libs/7zip/unix/CPP/Common/StringToInt.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/StringToInt.h (renamed from src/libs/7zip/unix/CPP/Common/StringToInt.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/UTFConvert.cpp (renamed from src/libs/7zip/unix/CPP/Common/UTFConvert.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/UTFConvert.h (renamed from src/libs/7zip/unix/CPP/Common/UTFConvert.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/Wildcard.cpp (renamed from src/libs/7zip/unix/CPP/Common/Wildcard.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Common/Wildcard.h (renamed from src/libs/7zip/unix/CPP/Common/Wildcard.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/DLL.cpp (renamed from src/libs/7zip/unix/CPP/Windows/DLL.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/DLL.h (renamed from src/libs/7zip/unix/CPP/Windows/DLL.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/Defs.h (renamed from src/libs/7zip/unix/CPP/Windows/Defs.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileDir.cpp (renamed from src/libs/7zip/unix/CPP/Windows/FileDir.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileDir.h (renamed from src/libs/7zip/unix/CPP/Windows/FileDir.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileFind.cpp (renamed from src/libs/7zip/unix/CPP/Windows/FileFind.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileFind.h (renamed from src/libs/7zip/unix/CPP/Windows/FileFind.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileIO.cpp (renamed from src/libs/7zip/unix/CPP/Windows/FileIO.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileIO.h (renamed from src/libs/7zip/unix/CPP/Windows/FileIO.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileName.cpp (renamed from src/libs/7zip/unix/CPP/Windows/FileName.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/FileName.h (renamed from src/libs/7zip/unix/CPP/Windows/FileName.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariant.cpp (renamed from src/libs/7zip/unix/CPP/Windows/PropVariant.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariant.h (renamed from src/libs/7zip/unix/CPP/Windows/PropVariant.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariantConv.cpp (renamed from src/libs/7zip/unix/CPP/Windows/PropVariantConv.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariantConv.h (renamed from src/libs/7zip/unix/CPP/Windows/PropVariantConv.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization.cpp (renamed from src/libs/7zip/unix/CPP/Windows/Synchronization.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization.h (renamed from src/libs/7zip/unix/CPP/Windows/Synchronization.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization2.h (renamed from src/libs/7zip/unix/CPP/Windows/Synchronization2.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/System.cpp (renamed from src/libs/7zip/unix/CPP/Windows/System.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/System.h (renamed from src/libs/7zip/unix/CPP/Windows/System.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/Thread.h (renamed from src/libs/7zip/unix/CPP/Windows/Thread.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/TimeUtils.cpp (renamed from src/libs/7zip/unix/CPP/Windows/TimeUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/TimeUtils.h (renamed from src/libs/7zip/unix/CPP/Windows/TimeUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/Windows/Windows.pri (renamed from src/libs/7zip/unix/CPP/Windows/Windows.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/include_windows/basetyps.h (renamed from src/libs/7zip/unix/CPP/include_windows/basetyps.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/include_windows/include_windows.pri (renamed from src/libs/7zip/unix/CPP/include_windows/include_windows.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/include_windows/tchar.h (renamed from src/libs/7zip/unix/CPP/include_windows/tchar.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/include_windows/windows.h (renamed from src/libs/7zip/unix/CPP/include_windows/windows.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/StdAfx.h (renamed from src/libs/7zip/unix/CPP/myWindows/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/config.h (renamed from src/libs/7zip/unix/CPP/myWindows/config.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/initguid.h (renamed from src/libs/7zip/unix/CPP/myWindows/initguid.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp (renamed from src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp)32
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/myDateAndTime.cpp (renamed from src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/myPrivate.h (renamed from src/libs/7zip/unix/CPP/myWindows/myPrivate.h)0
-rw-r--r--src/libs/3rdparty/7zip/unix/CPP/myWindows/myWindows.pri (renamed from src/libs/7zip/unix/CPP/myWindows/myWindows.pri)0
-rw-r--r--src/libs/3rdparty/7zip/unix/unix.pri (renamed from src/libs/7zip/unix/unix.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/7zCrc.c (renamed from src/libs/7zip/win/C/7zCrc.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/7zCrc.h (renamed from src/libs/7zip/win/C/7zCrc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/7zCrcOpt.c (renamed from src/libs/7zip/win/C/7zCrcOpt.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/7zStream.c (renamed from src/libs/7zip/win/C/7zStream.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/7zTypes.h (renamed from src/libs/7zip/win/C/7zTypes.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/7zVersion.h (renamed from src/libs/7zip/win/C/7zVersion.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Alloc.c (renamed from src/libs/7zip/win/C/Alloc.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Alloc.h (renamed from src/libs/7zip/win/C/Alloc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Bra.c (renamed from src/libs/7zip/win/C/Bra.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Bra.h (renamed from src/libs/7zip/win/C/Bra.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Bra86.c (renamed from src/libs/7zip/win/C/Bra86.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/BraIA64.c (renamed from src/libs/7zip/win/C/BraIA64.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/C.pri (renamed from src/libs/7zip/win/C/C.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Compiler.h (renamed from src/libs/7zip/win/C/Compiler.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/CpuArch.c (renamed from src/libs/7zip/win/C/CpuArch.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/CpuArch.h (renamed from src/libs/7zip/win/C/CpuArch.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Delta.c (renamed from src/libs/7zip/win/C/Delta.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Delta.h (renamed from src/libs/7zip/win/C/Delta.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzFind.c (renamed from src/libs/7zip/win/C/LzFind.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzFind.h (renamed from src/libs/7zip/win/C/LzFind.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzFindMt.c (renamed from src/libs/7zip/win/C/LzFindMt.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzFindMt.h (renamed from src/libs/7zip/win/C/LzFindMt.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzHash.h (renamed from src/libs/7zip/win/C/LzHash.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Lzma2Dec.c (renamed from src/libs/7zip/win/C/Lzma2Dec.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Lzma2Dec.h (renamed from src/libs/7zip/win/C/Lzma2Dec.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Lzma2Enc.c (renamed from src/libs/7zip/win/C/Lzma2Enc.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Lzma2Enc.h (renamed from src/libs/7zip/win/C/Lzma2Enc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzmaDec.c (renamed from src/libs/7zip/win/C/LzmaDec.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzmaDec.h (renamed from src/libs/7zip/win/C/LzmaDec.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzmaEnc.c (renamed from src/libs/7zip/win/C/LzmaEnc.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/LzmaEnc.h (renamed from src/libs/7zip/win/C/LzmaEnc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/MtCoder.c (renamed from src/libs/7zip/win/C/MtCoder.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/MtCoder.h (renamed from src/libs/7zip/win/C/MtCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Precomp.h (renamed from src/libs/7zip/win/C/Precomp.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/RotateDefs.h (renamed from src/libs/7zip/win/C/RotateDefs.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Sha256.c (renamed from src/libs/7zip/win/C/Sha256.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Sha256.h (renamed from src/libs/7zip/win/C/Sha256.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Threads.c (renamed from src/libs/7zip/win/C/Threads.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Threads.h (renamed from src/libs/7zip/win/C/Threads.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Xz.c (renamed from src/libs/7zip/win/C/Xz.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/Xz.h (renamed from src/libs/7zip/win/C/Xz.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzCrc64.c (renamed from src/libs/7zip/win/C/XzCrc64.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzCrc64.h (renamed from src/libs/7zip/win/C/XzCrc64.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzCrc64Opt.c (renamed from src/libs/7zip/win/C/XzCrc64Opt.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzDec.c (renamed from src/libs/7zip/win/C/XzDec.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzEnc.c (renamed from src/libs/7zip/win/C/XzEnc.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzEnc.h (renamed from src/libs/7zip/win/C/XzEnc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/C/XzIn.c (renamed from src/libs/7zip/win/C/XzIn.c)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/7zip.pri (renamed from src/libs/7zip/win/CPP/7zip/7zip.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7z.pri (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zDecode.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zEncode.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandler.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHeader.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zIn.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zItem.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zItem.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zOut.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zProperties.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Archive.pri (renamed from src/libs/7zip/win/CPP/7zip/Archive/Archive.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/Common.pri (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/MultiStream.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/IArchive.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/IArchive.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/SplitHandler.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/SplitHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Archive/XzHandler.cpp (renamed from src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/CWrappers.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/CWrappers.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/CWrappers.h (renamed from src/libs/7zip/win/CPP/7zip/Common/CWrappers.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/Common.pri (renamed from src/libs/7zip/win/CPP/7zip/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/CreateCoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/CreateCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/CreateCoder.h (renamed from src/libs/7zip/win/CPP/7zip/Common/CreateCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilePathAutoRename.h (renamed from src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/FileStreams.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/FileStreams.h (renamed from src/libs/7zip/win/CPP/7zip/Common/FileStreams.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilterCoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/FilterCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilterCoder.h (renamed from src/libs/7zip/win/CPP/7zip/Common/FilterCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/InBuffer.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/InBuffer.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/InBuffer.h (renamed from src/libs/7zip/win/CPP/7zip/Common/InBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/InOutTempBuffer.h (renamed from src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/LimitedStreams.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/LimitedStreams.h (renamed from src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/LockedStream.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/LockedStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/LockedStream.h (renamed from src/libs/7zip/win/CPP/7zip/Common/LockedStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodId.h (renamed from src/libs/7zip/win/CPP/7zip/Common/MethodId.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodProps.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/MethodProps.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodProps.h (renamed from src/libs/7zip/win/CPP/7zip/Common/MethodProps.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/OutBuffer.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/OutBuffer.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/OutBuffer.h (renamed from src/libs/7zip/win/CPP/7zip/Common/OutBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/ProgressUtils.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/ProgressUtils.h (renamed from src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/PropId.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/PropId.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/RegisterArc.h (renamed from src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/RegisterCodec.h (renamed from src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/Common/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamBinder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamBinder.h (renamed from src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamObjects.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/StreamObjects.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamObjects.h (renamed from src/libs/7zip/win/CPP/7zip/Common/StreamObjects.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamUtils.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/StreamUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamUtils.h (renamed from src/libs/7zip/win/CPP/7zip/Common/StreamUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/UniqBlocks.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/UniqBlocks.h (renamed from src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/VirtThread.cpp (renamed from src/libs/7zip/win/CPP/7zip/Common/VirtThread.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Common/VirtThread.h (renamed from src/libs/7zip/win/CPP/7zip/Common/VirtThread.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Coder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Register.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/Bcj2Register.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjCoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/BcjCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjCoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/BcjCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjRegister.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/BcjRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchCoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/BranchCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchCoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/BranchCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchMisc.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchMisc.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchRegister.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/BranchRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/ByteSwap.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/ByteSwap.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Compress.pri (renamed from src/libs/7zip/win/CPP/7zip/Compress/Compress.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyCoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyCoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyRegister.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/CopyRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Decoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Register.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/Lzma2Register.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaDecoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaEncoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaRegister.cpp (renamed from src/libs/7zip/win/CPP/7zip/Compress/LzmaRegister.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/RangeCoder.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/RangeCoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/RangeCoderBit.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/RangeCoderBit.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Compress/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/Guid.txt (renamed from src/libs/7zip/win/CPP/7zip/Guid.txt)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/ICoder.h (renamed from src/libs/7zip/win/CPP/7zip/ICoder.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/IDecl.h (renamed from src/libs/7zip/win/CPP/7zip/IDecl.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/IPassword.h (renamed from src/libs/7zip/win/CPP/7zip/IPassword.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/IProgress.h (renamed from src/libs/7zip/win/CPP/7zip/IProgress.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/IStream.h (renamed from src/libs/7zip/win/CPP/7zip/IStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/PropID.h (renamed from src/libs/7zip/win/CPP/7zip/PropID.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Common.pri (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DefaultName.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DirItem.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/DirItem.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Extract.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Extract.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/Extract.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractMode.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ExtractMode.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/HashCalc.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/OpenArchive.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Property.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/Property.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SetProperties.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SortUtils.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/TempFiles.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Update.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/Update.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Update.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/Update.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateAction.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdatePair.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/Console.pri (renamed from src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp (renamed from src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/StdAfx.h (renamed from src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/ComTry.h (renamed from src/libs/7zip/win/CPP/Common/ComTry.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/CommandLineParser.cpp (renamed from src/libs/7zip/win/CPP/Common/CommandLineParser.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/CommandLineParser.h (renamed from src/libs/7zip/win/CPP/Common/CommandLineParser.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/Common.h (renamed from src/libs/7zip/win/CPP/Common/Common.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/Common.pri (renamed from src/libs/7zip/win/CPP/Common/Common.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/Defs.h (renamed from src/libs/7zip/win/CPP/Common/Defs.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/IntToString.cpp (renamed from src/libs/7zip/win/CPP/Common/IntToString.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/IntToString.h (renamed from src/libs/7zip/win/CPP/Common/IntToString.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/ListFileUtils.cpp (renamed from src/libs/7zip/win/CPP/Common/ListFileUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/ListFileUtils.h (renamed from src/libs/7zip/win/CPP/Common/ListFileUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyBuffer.h (renamed from src/libs/7zip/win/CPP/Common/MyBuffer.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyCom.h (renamed from src/libs/7zip/win/CPP/Common/MyCom.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyException.h (renamed from src/libs/7zip/win/CPP/Common/MyException.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyGuidDef.h (renamed from src/libs/7zip/win/CPP/Common/MyGuidDef.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyInitGuid.h (renamed from src/libs/7zip/win/CPP/Common/MyInitGuid.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyString.cpp (renamed from src/libs/7zip/win/CPP/Common/MyString.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyString.h (renamed from src/libs/7zip/win/CPP/Common/MyString.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyTypes.h (renamed from src/libs/7zip/win/CPP/Common/MyTypes.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyUnknown.h (renamed from src/libs/7zip/win/CPP/Common/MyUnknown.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyVector.h (renamed from src/libs/7zip/win/CPP/Common/MyVector.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyWindows.cpp (renamed from src/libs/7zip/win/CPP/Common/MyWindows.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/MyWindows.h (renamed from src/libs/7zip/win/CPP/Common/MyWindows.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/NewHandler.cpp (renamed from src/libs/7zip/win/CPP/Common/NewHandler.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/NewHandler.h (renamed from src/libs/7zip/win/CPP/Common/NewHandler.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StdAfx.h (renamed from src/libs/7zip/win/CPP/Common/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StdOutStream.cpp (renamed from src/libs/7zip/win/CPP/Common/StdOutStream.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StdOutStream.h (renamed from src/libs/7zip/win/CPP/Common/StdOutStream.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StringConvert.cpp (renamed from src/libs/7zip/win/CPP/Common/StringConvert.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StringConvert.h (renamed from src/libs/7zip/win/CPP/Common/StringConvert.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StringToInt.cpp (renamed from src/libs/7zip/win/CPP/Common/StringToInt.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/StringToInt.h (renamed from src/libs/7zip/win/CPP/Common/StringToInt.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/UTFConvert.cpp (renamed from src/libs/7zip/win/CPP/Common/UTFConvert.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/UTFConvert.h (renamed from src/libs/7zip/win/CPP/Common/UTFConvert.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/Wildcard.cpp (renamed from src/libs/7zip/win/CPP/Common/Wildcard.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Common/Wildcard.h (renamed from src/libs/7zip/win/CPP/Common/Wildcard.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/DLL.cpp (renamed from src/libs/7zip/win/CPP/Windows/DLL.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/DLL.h (renamed from src/libs/7zip/win/CPP/Windows/DLL.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/Defs.h (renamed from src/libs/7zip/win/CPP/Windows/Defs.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileDir.cpp (renamed from src/libs/7zip/win/CPP/Windows/FileDir.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileDir.h (renamed from src/libs/7zip/win/CPP/Windows/FileDir.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileFind.cpp (renamed from src/libs/7zip/win/CPP/Windows/FileFind.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileFind.h (renamed from src/libs/7zip/win/CPP/Windows/FileFind.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileIO.cpp (renamed from src/libs/7zip/win/CPP/Windows/FileIO.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileIO.h (renamed from src/libs/7zip/win/CPP/Windows/FileIO.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileLink.cpp (renamed from src/libs/7zip/win/CPP/Windows/FileLink.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileMapping.h (renamed from src/libs/7zip/win/CPP/Windows/FileMapping.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileName.cpp (renamed from src/libs/7zip/win/CPP/Windows/FileName.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/FileName.h (renamed from src/libs/7zip/win/CPP/Windows/FileName.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/Handle.h (renamed from src/libs/7zip/win/CPP/Windows/Handle.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/PropVariant.cpp (renamed from src/libs/7zip/win/CPP/Windows/PropVariant.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/PropVariant.h (renamed from src/libs/7zip/win/CPP/Windows/PropVariant.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/PropVariantConv.cpp (renamed from src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/PropVariantConv.h (renamed from src/libs/7zip/win/CPP/Windows/PropVariantConv.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/SecurityUtils.cpp (renamed from src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/SecurityUtils.h (renamed from src/libs/7zip/win/CPP/Windows/SecurityUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/StdAfx.h (renamed from src/libs/7zip/win/CPP/Windows/StdAfx.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/Synchronization.cpp (renamed from src/libs/7zip/win/CPP/Windows/Synchronization.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/Synchronization.h (renamed from src/libs/7zip/win/CPP/Windows/Synchronization.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/System.cpp (renamed from src/libs/7zip/win/CPP/Windows/System.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/System.h (renamed from src/libs/7zip/win/CPP/Windows/System.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/Thread.h (renamed from src/libs/7zip/win/CPP/Windows/Thread.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/TimeUtils.cpp (renamed from src/libs/7zip/win/CPP/Windows/TimeUtils.cpp)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/TimeUtils.h (renamed from src/libs/7zip/win/CPP/Windows/TimeUtils.h)0
-rw-r--r--src/libs/3rdparty/7zip/win/CPP/Windows/Windows.pri (renamed from src/libs/7zip/win/CPP/Windows/Windows.pri)0
-rw-r--r--src/libs/3rdparty/7zip/win/win.pri (renamed from src/libs/7zip/win/win.pri)0
-rw-r--r--src/libs/3rdparty/libarchive/archive.h14
-rw-r--r--src/libs/3rdparty/libarchive/archive_blake2.h4
-rw-r--r--src/libs/3rdparty/libarchive/archive_blake2_impl.h2
-rw-r--r--src/libs/3rdparty/libarchive/archive_blake2s_ref.c2
-rw-r--r--src/libs/3rdparty/libarchive/archive_blake2sp_ref.c2
-rw-r--r--src/libs/3rdparty/libarchive/archive_cryptor.c8
-rw-r--r--src/libs/3rdparty/libarchive/archive_digest.c94
-rw-r--r--src/libs/3rdparty/libarchive/archive_digest_private.h10
-rw-r--r--src/libs/3rdparty/libarchive/archive_disk_acl_freebsd.c20
-rw-r--r--src/libs/3rdparty/libarchive/archive_disk_acl_linux.c23
-rw-r--r--src/libs/3rdparty/libarchive/archive_disk_acl_sunos.c13
-rw-r--r--src/libs/3rdparty/libarchive/archive_entry.c14
-rw-r--r--src/libs/3rdparty/libarchive/archive_entry.h6
-rw-r--r--src/libs/3rdparty/libarchive/archive_getdate.c121
-rw-r--r--src/libs/3rdparty/libarchive/archive_hmac.c34
-rw-r--r--src/libs/3rdparty/libarchive/archive_hmac_private.h9
-rw-r--r--src/libs/3rdparty/libarchive/archive_openssl_evp_private.h3
-rw-r--r--src/libs/3rdparty/libarchive/archive_pack_dev.c3
-rw-r--r--src/libs/3rdparty/libarchive/archive_pathmatch.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_platform.h33
-rw-r--r--src/libs/3rdparty/libarchive/archive_private.h12
-rw-r--r--src/libs/3rdparty/libarchive/archive_random.c43
-rw-r--r--src/libs/3rdparty/libarchive/archive_read.c150
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_append_filter.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_data_into_fd.c7
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_disk_entry_from_file.c8
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_disk_posix.c136
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_disk_windows.c136
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_open_file.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_private.h53
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_set_options.c32
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_bzip2.c40
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_compress.c43
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_grzip.c23
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_gzip.c35
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_lrzip.c24
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c44
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c31
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_program.c63
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_rpm.c34
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_uu.c34
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c77
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_filter_zstd.c43
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c251
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_cab.c15
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_cpio.c24
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c17
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_lha.c29
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c160
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_rar.c897
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c259
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_tar.c42
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_warc.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_xar.c12
-rw-r--r--src/libs/3rdparty/libarchive/archive_read_support_format_zip.c319
-rw-r--r--src/libs/3rdparty/libarchive/archive_string.c12
-rw-r--r--src/libs/3rdparty/libarchive/archive_util.c57
-rw-r--r--src/libs/3rdparty/libarchive/archive_windows.c35
-rw-r--r--src/libs/3rdparty/libarchive/archive_write.c98
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_add_filter_bzip2.c6
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_add_filter_compress.c2
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_add_filter_lz4.c8
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_add_filter_xz.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_add_filter_zstd.c251
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_disk_posix.c267
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_disk_windows.c149
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_private.h1
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_7zip.c17
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_by_name.c4
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_cpio.c493
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_cpio_binary.c610
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_cpio_odc.c500
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_iso9660.c34
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_pax.c39
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_warc.c25
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_xar.c14
-rw-r--r--src/libs/3rdparty/libarchive/archive_write_set_format_zip.c33
-rw-r--r--src/libs/3rdparty/libarchive/config/mac/config.h10
-rw-r--r--src/libs/3rdparty/libarchive/config_freebsd.h16
-rw-r--r--src/libs/3rdparty/libarchive/filter_fork_posix.c2
-rw-r--r--src/libs/3rdparty/libarchive/filter_fork_windows.c48
-rw-r--r--src/libs/3rdparty/libarchive/libarchive.pro6
-rw-r--r--src/libs/3rdparty/libarchive/qt_attribution.json2
-rw-r--r--src/libs/3rdparty/libarchive/xxhash.c10
-rw-r--r--src/libs/7zip/patches/0001-Adjust-7z-and-p7z.patch517
-rw-r--r--src/libs/ifwtools/binarycreator.cpp173
-rw-r--r--src/libs/ifwtools/binarycreator.h6
-rw-r--r--src/libs/ifwtools/rcc/rcc.cpp26
-rw-r--r--src/libs/ifwtools/repositorygen.cpp197
-rw-r--r--src/libs/ifwtools/repositorygen.h3
-rw-r--r--src/libs/installer/abstractarchive.h7
-rw-r--r--src/libs/installer/abstracttask.h8
-rw-r--r--src/libs/installer/archivefactory.cpp16
-rw-r--r--src/libs/installer/aspectratiolabel.cpp51
-rw-r--r--src/libs/installer/aspectratiolabel.h17
-rw-r--r--src/libs/installer/binaryformat.cpp11
-rw-r--r--src/libs/installer/binaryformat.h18
-rw-r--r--src/libs/installer/binaryformatengine.cpp25
-rw-r--r--src/libs/installer/binaryformatengine.h31
-rw-r--r--src/libs/installer/calculatorbase.cpp76
-rw-r--r--src/libs/installer/calculatorbase.h85
-rw-r--r--src/libs/installer/commandlineparser.cpp90
-rw-r--r--src/libs/installer/commandlineparser.h16
-rw-r--r--src/libs/installer/component.cpp452
-rw-r--r--src/libs/installer/component.h31
-rw-r--r--src/libs/installer/component_p.cpp12
-rw-r--r--src/libs/installer/component_p.h8
-rw-r--r--src/libs/installer/componentalias.cpp649
-rw-r--r--src/libs/installer/componentalias.h160
-rw-r--r--src/libs/installer/componentmodel.cpp95
-rw-r--r--src/libs/installer/componentmodel.h30
-rw-r--r--src/libs/installer/componentselectionpage_p.cpp389
-rw-r--r--src/libs/installer/componentselectionpage_p.h34
-rw-r--r--src/libs/installer/componentsortfilterproxymodel.cpp2
-rw-r--r--src/libs/installer/componentsortfilterproxymodel.h4
-rw-r--r--src/libs/installer/concurrentoperationrunner.cpp279
-rw-r--r--src/libs/installer/concurrentoperationrunner.h88
-rw-r--r--src/libs/installer/constants.h90
-rw-r--r--src/libs/installer/consumeoutputoperation.cpp30
-rw-r--r--src/libs/installer/consumeoutputoperation.h10
-rw-r--r--src/libs/installer/copydirectoryoperation.cpp2
-rw-r--r--src/libs/installer/copydirectoryoperation.h10
-rw-r--r--src/libs/installer/copyfiletask.cpp4
-rw-r--r--src/libs/installer/copyfiletask.h4
-rw-r--r--src/libs/installer/createdesktopentryoperation.cpp16
-rw-r--r--src/libs/installer/createdesktopentryoperation.h10
-rw-r--r--src/libs/installer/createlinkoperation.cpp2
-rw-r--r--src/libs/installer/createlinkoperation.h10
-rw-r--r--src/libs/installer/createlocalrepositoryoperation.cpp16
-rw-r--r--src/libs/installer/createlocalrepositoryoperation.h10
-rw-r--r--src/libs/installer/createshortcutoperation.cpp4
-rw-r--r--src/libs/installer/createshortcutoperation.h10
-rw-r--r--src/libs/installer/customcombobox.cpp54
-rw-r--r--src/libs/installer/customcombobox.h48
-rw-r--r--src/libs/installer/directoryguard.cpp4
-rw-r--r--src/libs/installer/downloadarchivesjob.cpp77
-rw-r--r--src/libs/installer/downloadarchivesjob.h22
-rw-r--r--src/libs/installer/downloadfiletask.cpp26
-rw-r--r--src/libs/installer/downloadfiletask.h8
-rw-r--r--src/libs/installer/downloadfiletask_p.h2
-rw-r--r--src/libs/installer/elevatedexecuteoperation.cpp66
-rw-r--r--src/libs/installer/elevatedexecuteoperation.h10
-rw-r--r--src/libs/installer/environmentvariablesoperation.cpp21
-rw-r--r--src/libs/installer/environmentvariablesoperation.h10
-rw-r--r--src/libs/installer/errors.h14
-rw-r--r--src/libs/installer/extractarchiveoperation.cpp146
-rw-r--r--src/libs/installer/extractarchiveoperation.h24
-rw-r--r--src/libs/installer/extractarchiveoperation_p.h120
-rw-r--r--src/libs/installer/fakestopprocessforupdateoperation.cpp8
-rw-r--r--src/libs/installer/fakestopprocessforupdateoperation.h10
-rw-r--r--src/libs/installer/fileguard.cpp120
-rw-r--r--src/libs/installer/fileguard.h66
-rw-r--r--src/libs/installer/fileutils.cpp138
-rw-r--r--src/libs/installer/fileutils.h18
-rw-r--r--src/libs/installer/fileutils_mac.mm75
-rw-r--r--src/libs/installer/genericdatacache.cpp695
-rw-r--r--src/libs/installer/genericdatacache.h122
-rw-r--r--src/libs/installer/globals.cpp71
-rw-r--r--src/libs/installer/globals.h19
-rw-r--r--src/libs/installer/globalsettingsoperation.cpp6
-rw-r--r--src/libs/installer/globalsettingsoperation.h10
-rw-r--r--src/libs/installer/graph.h2
-rw-r--r--src/libs/installer/init.cpp5
-rw-r--r--src/libs/installer/installer.pro59
-rw-r--r--src/libs/installer/installer_global.h8
-rw-r--r--src/libs/installer/installercalculator.cpp274
-rw-r--r--src/libs/installer/installercalculator.h59
-rw-r--r--src/libs/installer/installiconsoperation.cpp6
-rw-r--r--src/libs/installer/installiconsoperation.h10
-rw-r--r--src/libs/installer/lib7z_create.h7
-rw-r--r--src/libs/installer/lib7z_extract.h23
-rw-r--r--src/libs/installer/lib7z_facade.cpp11
-rw-r--r--src/libs/installer/lib7z_guid.h23
-rw-r--r--src/libs/installer/lib7z_list.h23
-rw-r--r--src/libs/installer/lib7zarchive.h24
-rw-r--r--src/libs/installer/libarchivearchive.cpp458
-rw-r--r--src/libs/installer/libarchivearchive.h21
-rw-r--r--src/libs/installer/libarchivewrapper.cpp3
-rw-r--r--src/libs/installer/libarchivewrapper.h27
-rw-r--r--src/libs/installer/libarchivewrapper_p.cpp19
-rw-r--r--src/libs/installer/libarchivewrapper_p.h1
-rw-r--r--src/libs/installer/licenseoperation.cpp17
-rw-r--r--src/libs/installer/licenseoperation.h10
-rw-r--r--src/libs/installer/linereplaceoperation.h10
-rw-r--r--src/libs/installer/link.cpp2
-rw-r--r--src/libs/installer/loggingutils.cpp188
-rw-r--r--src/libs/installer/loggingutils.h19
-rw-r--r--src/libs/installer/messageboxhandler.cpp5
-rw-r--r--src/libs/installer/metadata.cpp410
-rw-r--r--src/libs/installer/metadata.h81
-rw-r--r--src/libs/installer/metadatacache.cpp67
-rw-r--r--src/libs/installer/metadatacache.h46
-rw-r--r--src/libs/installer/metadatajob.cpp677
-rw-r--r--src/libs/installer/metadatajob.h65
-rw-r--r--src/libs/installer/metadatajob_p.h146
-rw-r--r--src/libs/installer/minimumprogressoperation.h10
-rw-r--r--src/libs/installer/observer.cpp6
-rw-r--r--src/libs/installer/observer.h10
-rw-r--r--src/libs/installer/operationtracer.cpp151
-rw-r--r--src/libs/installer/operationtracer.h68
-rw-r--r--src/libs/installer/packagemanagercore.cpp1717
-rw-r--r--src/libs/installer/packagemanagercore.h120
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp1203
-rw-r--r--src/libs/installer/packagemanagercore_p.h87
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp30
-rw-r--r--src/libs/installer/packagemanagercoredata.h5
-rw-r--r--src/libs/installer/packagemanagergui.cpp421
-rw-r--r--src/libs/installer/packagemanagergui.h81
-rw-r--r--src/libs/installer/packagemanagerproxyfactory.h6
-rw-r--r--src/libs/installer/packagesource.cpp27
-rw-r--r--src/libs/installer/packagesource.h29
-rw-r--r--src/libs/installer/performinstallationform.cpp65
-rw-r--r--src/libs/installer/performinstallationform.h18
-rw-r--r--src/libs/installer/permissionsettings.cpp2
-rw-r--r--src/libs/installer/permissionsettings.h11
-rw-r--r--src/libs/installer/productkeycheck.cpp29
-rw-r--r--src/libs/installer/productkeycheck.h9
-rw-r--r--src/libs/installer/progresscoordinator.cpp55
-rw-r--r--src/libs/installer/progresscoordinator.h10
-rw-r--r--src/libs/installer/protocol.h7
-rw-r--r--src/libs/installer/qinstallerglobal.cpp33
-rw-r--r--src/libs/installer/qinstallerglobal.h10
-rw-r--r--src/libs/installer/qprocesswrapper.cpp86
-rw-r--r--src/libs/installer/qprocesswrapper.h9
-rw-r--r--src/libs/installer/qsettingswrapper.cpp110
-rw-r--r--src/libs/installer/qsettingswrapper.h54
-rw-r--r--src/libs/installer/qtpatch.cpp6
-rw-r--r--src/libs/installer/registerfiletypeoperation.cpp8
-rw-r--r--src/libs/installer/registerfiletypeoperation.h10
-rw-r--r--src/libs/installer/remoteclient_p.h5
-rw-r--r--src/libs/installer/remotefileengine.cpp36
-rw-r--r--src/libs/installer/remotefileengine.h82
-rw-r--r--src/libs/installer/remoteobject.cpp21
-rw-r--r--src/libs/installer/remoteobject.h110
-rw-r--r--src/libs/installer/remoteserver_p.h4
-rw-r--r--src/libs/installer/remoteserverconnection.cpp304
-rw-r--r--src/libs/installer/remoteserverconnection.h41
-rw-r--r--src/libs/installer/remoteserverconnection_p.h2
-rw-r--r--src/libs/installer/replaceoperation.h10
-rw-r--r--src/libs/installer/repository.cpp64
-rw-r--r--src/libs/installer/repository.h14
-rw-r--r--src/libs/installer/repositorycategory.cpp14
-rw-r--r--src/libs/installer/repositorycategory.h9
-rw-r--r--src/libs/installer/resources/installer.qrc1
-rw-r--r--src/libs/installer/resources/qt/etc/qt.conf0
-rw-r--r--src/libs/installer/runextensions.h378
-rw-r--r--src/libs/installer/scriptengine.cpp109
-rw-r--r--src/libs/installer/scriptengine.h8
-rw-r--r--src/libs/installer/scriptengine_p.h41
-rw-r--r--src/libs/installer/selfrestartoperation.h10
-rw-r--r--src/libs/installer/settings.cpp192
-rw-r--r--src/libs/installer/settings.h22
-rw-r--r--src/libs/installer/settingsoperation.cpp33
-rw-r--r--src/libs/installer/settingsoperation.h10
-rw-r--r--src/libs/installer/simplemovefileoperation.cpp2
-rw-r--r--src/libs/installer/simplemovefileoperation.h10
-rw-r--r--src/libs/installer/sysinfo_win.cpp10
-rw-r--r--src/libs/installer/systeminfo.cpp30
-rw-r--r--src/libs/installer/systeminfo.h5
-rw-r--r--src/libs/installer/testrepository.h6
-rw-r--r--src/libs/installer/uninstallercalculator.cpp203
-rw-r--r--src/libs/installer/uninstallercalculator.h32
-rw-r--r--src/libs/installer/unziptask.h4
-rw-r--r--src/libs/installer/utils.cpp104
-rw-r--r--src/libs/installer/utils.h9
-rw-r--r--src/libs/kdtools/filedownloader.cpp88
-rw-r--r--src/libs/kdtools/filedownloader.h4
-rw-r--r--src/libs/kdtools/filedownloader_p.h69
-rw-r--r--src/libs/kdtools/genericfactory.cpp26
-rw-r--r--src/libs/kdtools/genericfactory.h21
-rw-r--r--src/libs/kdtools/kdsysinfo_win.cpp14
-rw-r--r--src/libs/kdtools/localpackagehub.cpp36
-rw-r--r--src/libs/kdtools/localpackagehub.h12
-rw-r--r--src/libs/kdtools/lockfile_win.cpp2
-rw-r--r--src/libs/kdtools/sysinfo.cpp2
-rw-r--r--src/libs/kdtools/sysinfo_x11.cpp12
-rw-r--r--src/libs/kdtools/updatefinder.cpp410
-rw-r--r--src/libs/kdtools/updatefinder.h90
-rw-r--r--src/libs/kdtools/updateoperation.cpp179
-rw-r--r--src/libs/kdtools/updateoperation.h19
-rw-r--r--src/libs/kdtools/updateoperations.cpp65
-rw-r--r--src/libs/kdtools/updateoperations.h63
-rw-r--r--src/libs/kdtools/updatesinfo.cpp256
-rw-r--r--src/libs/kdtools/updatesinfo_p.h6
-rw-r--r--src/libs/kdtools/updatesinfodata_p.h14
-rw-r--r--src/libs/libs.pro6
-rw-r--r--src/sdk/aboutapplicationdialog.cpp100
-rw-r--r--src/sdk/aboutapplicationdialog.h48
-rw-r--r--src/sdk/commandlineinterface.cpp55
-rw-r--r--src/sdk/commandlineinterface.h1
-rw-r--r--src/sdk/installerbase.cpp22
-rw-r--r--src/sdk/main.cpp87
-rw-r--r--src/sdk/sdk.pro19
-rw-r--r--src/sdk/sdkapp.h118
-rw-r--r--src/sdk/settingsdialog.cpp38
-rw-r--r--src/sdk/settingsdialog.h6
-rw-r--r--src/sdk/settingsdialog.ui96
-rw-r--r--src/sdk/tabcontroller.cpp70
-rw-r--r--src/sdk/tabcontroller.h4
-rw-r--r--src/sdk/translations/ifw_ar.ts641
-rw-r--r--src/sdk/translations/ifw_ca.ts677
-rw-r--r--src/sdk/translations/ifw_da.ts691
-rw-r--r--src/sdk/translations/ifw_de.ts673
-rw-r--r--src/sdk/translations/ifw_es.ts647
-rw-r--r--src/sdk/translations/ifw_fr.ts673
-rw-r--r--src/sdk/translations/ifw_hr.ts692
-rw-r--r--src/sdk/translations/ifw_hu.ts3081
-rw-r--r--src/sdk/translations/ifw_it.ts699
-rw-r--r--src/sdk/translations/ifw_ja.ts668
-rw-r--r--src/sdk/translations/ifw_ko.ts770
-rw-r--r--src/sdk/translations/ifw_pl.ts774
-rw-r--r--src/sdk/translations/ifw_pt.ts658
-rw-r--r--src/sdk/translations/ifw_pt_BR.ts652
-rw-r--r--src/sdk/translations/ifw_ru.ts626
-rw-r--r--src/sdk/translations/ifw_zh_CN.ts713
905 files changed, 27557 insertions, 9275 deletions
diff --git a/src/libs/3rdparty/3rdparty.pro b/src/libs/3rdparty/3rdparty.pro
index f22bf261b..e69183197 100644
--- a/src/libs/3rdparty/3rdparty.pro
+++ b/src/libs/3rdparty/3rdparty.pro
@@ -1,4 +1,10 @@
TEMPLATE = subdirs
+
+include(../../../installerfw.pri)
+
CONFIG(libarchive) {
SUBDIRS += libarchive
}
+CONFIG(lzmasdk) {
+ SUBDIRS += 7zip
+}
diff --git a/src/libs/7zip/7zip.pri b/src/libs/3rdparty/7zip/7zip.pri
index 26c052fc7..26c052fc7 100644
--- a/src/libs/7zip/7zip.pri
+++ b/src/libs/3rdparty/7zip/7zip.pri
diff --git a/src/libs/7zip/7zip.pro b/src/libs/3rdparty/7zip/7zip.pro
index 17e64df8f..0c8ff3e1b 100644
--- a/src/libs/7zip/7zip.pro
+++ b/src/libs/3rdparty/7zip/7zip.pro
@@ -1,7 +1,7 @@
QT = core
TARGET = 7z
TEMPLATE = lib
-include(../../../installerfw.pri)
+include(../../../../installerfw.pri)
INCLUDEPATH += . ..
CONFIG += staticlib
DESTDIR = $$IFW_LIB_PATH
diff --git a/src/libs/3rdparty/7zip/COPYING b/src/libs/3rdparty/7zip/COPYING
new file mode 100644
index 000000000..2b197ecf1
--- /dev/null
+++ b/src/libs/3rdparty/7zip/COPYING
@@ -0,0 +1,15 @@
+LICENSE
+-------
+
+LZMA SDK is written and placed in the public domain by Igor Pavlov.
+
+Some code in LZMA SDK is based on public domain code from another developers:
+ 1) PPMd var.H (2001): Dmitry Shkarin
+ 2) SHA-256: Wei Dai (Crypto++ library)
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute the
+original LZMA SDK code, either in source code form or as a compiled binary, for
+any purpose, commercial or non-commercial, and by any means.
+
+LZMA SDK code is compatible with open source licenses, for example, you can
+include it to GNU GPL or GNU LGPL code.
diff --git a/src/libs/7zip/installer_framework_changes.txt b/src/libs/3rdparty/7zip/installer_framework_changes.txt
index 6b5839208..6b5839208 100644
--- a/src/libs/7zip/installer_framework_changes.txt
+++ b/src/libs/3rdparty/7zip/installer_framework_changes.txt
diff --git a/src/libs/3rdparty/7zip/qt_attribution.json b/src/libs/3rdparty/7zip/qt_attribution.json
new file mode 100644
index 000000000..1028b2bd4
--- /dev/null
+++ b/src/libs/3rdparty/7zip/qt_attribution.json
@@ -0,0 +1,13 @@
+{
+ "Id": "lzmasdk",
+ "Name": "LZMA SDK",
+ "QDocModule": "ifw",
+ "Description": "Tools to develop applications that use LZMA compression.",
+ "QtUsage": "Used for reading and writing 7z archives in Qt Installer Framework",
+ "Homepage": "https://www.7-zip.org/sdk.html",
+ "Version": "9.38.beta",
+ "License": "Public Domain",
+ "LicenseId": "public-domain",
+ "LicenseFile": "COPYING",
+ "Copyright": "Copyright (c) 2015 Igor Pavlov"
+}
diff --git a/src/libs/7zip/unix/C/7zCrc.c b/src/libs/3rdparty/7zip/unix/C/7zCrc.c
index ac33358f6..ac33358f6 100644
--- a/src/libs/7zip/unix/C/7zCrc.c
+++ b/src/libs/3rdparty/7zip/unix/C/7zCrc.c
diff --git a/src/libs/7zip/unix/C/7zCrc.h b/src/libs/3rdparty/7zip/unix/C/7zCrc.h
index 8fd579587..8fd579587 100644
--- a/src/libs/7zip/unix/C/7zCrc.h
+++ b/src/libs/3rdparty/7zip/unix/C/7zCrc.h
diff --git a/src/libs/7zip/unix/C/7zCrcOpt.c b/src/libs/3rdparty/7zip/unix/C/7zCrcOpt.c
index ce132b5d4..ce132b5d4 100644
--- a/src/libs/7zip/unix/C/7zCrcOpt.c
+++ b/src/libs/3rdparty/7zip/unix/C/7zCrcOpt.c
diff --git a/src/libs/7zip/unix/C/7zStream.c b/src/libs/3rdparty/7zip/unix/C/7zStream.c
index 88f9c42b1..88f9c42b1 100644
--- a/src/libs/7zip/unix/C/7zStream.c
+++ b/src/libs/3rdparty/7zip/unix/C/7zStream.c
diff --git a/src/libs/7zip/unix/C/7zTypes.h b/src/libs/3rdparty/7zip/unix/C/7zTypes.h
index 778413ef4..778413ef4 100644
--- a/src/libs/7zip/unix/C/7zTypes.h
+++ b/src/libs/3rdparty/7zip/unix/C/7zTypes.h
diff --git a/src/libs/7zip/unix/C/7zVersion.h b/src/libs/3rdparty/7zip/unix/C/7zVersion.h
index 518513534..518513534 100644
--- a/src/libs/7zip/unix/C/7zVersion.h
+++ b/src/libs/3rdparty/7zip/unix/C/7zVersion.h
diff --git a/src/libs/7zip/unix/C/Alloc.c b/src/libs/3rdparty/7zip/unix/C/Alloc.c
index 9c5fe00ca..9c5fe00ca 100644
--- a/src/libs/7zip/unix/C/Alloc.c
+++ b/src/libs/3rdparty/7zip/unix/C/Alloc.c
diff --git a/src/libs/7zip/unix/C/Alloc.h b/src/libs/3rdparty/7zip/unix/C/Alloc.h
index 7ef372e3a..7ef372e3a 100644
--- a/src/libs/7zip/unix/C/Alloc.h
+++ b/src/libs/3rdparty/7zip/unix/C/Alloc.h
diff --git a/src/libs/7zip/unix/C/Bra.c b/src/libs/3rdparty/7zip/unix/C/Bra.c
index 33f7a391c..33f7a391c 100644
--- a/src/libs/7zip/unix/C/Bra.c
+++ b/src/libs/3rdparty/7zip/unix/C/Bra.c
diff --git a/src/libs/7zip/unix/C/Bra.h b/src/libs/3rdparty/7zip/unix/C/Bra.h
index 184c291a7..184c291a7 100644
--- a/src/libs/7zip/unix/C/Bra.h
+++ b/src/libs/3rdparty/7zip/unix/C/Bra.h
diff --git a/src/libs/7zip/unix/C/Bra86.c b/src/libs/3rdparty/7zip/unix/C/Bra86.c
index 6db15e7ec..6db15e7ec 100644
--- a/src/libs/7zip/unix/C/Bra86.c
+++ b/src/libs/3rdparty/7zip/unix/C/Bra86.c
diff --git a/src/libs/7zip/unix/C/BraIA64.c b/src/libs/3rdparty/7zip/unix/C/BraIA64.c
index aa1a44e1e..aa1a44e1e 100644
--- a/src/libs/7zip/unix/C/BraIA64.c
+++ b/src/libs/3rdparty/7zip/unix/C/BraIA64.c
diff --git a/src/libs/7zip/unix/C/C.pri b/src/libs/3rdparty/7zip/unix/C/C.pri
index 6f0abb674..6f0abb674 100644
--- a/src/libs/7zip/unix/C/C.pri
+++ b/src/libs/3rdparty/7zip/unix/C/C.pri
diff --git a/src/libs/7zip/unix/C/Compiler.h b/src/libs/3rdparty/7zip/unix/C/Compiler.h
index 6e964897e..6e964897e 100644
--- a/src/libs/7zip/unix/C/Compiler.h
+++ b/src/libs/3rdparty/7zip/unix/C/Compiler.h
diff --git a/src/libs/7zip/unix/C/CpuArch.h b/src/libs/3rdparty/7zip/unix/C/CpuArch.h
index e3e5d8c99..e3e5d8c99 100644
--- a/src/libs/7zip/unix/C/CpuArch.h
+++ b/src/libs/3rdparty/7zip/unix/C/CpuArch.h
diff --git a/src/libs/7zip/unix/C/Delta.c b/src/libs/3rdparty/7zip/unix/C/Delta.c
index e3edd21ed..e3edd21ed 100644
--- a/src/libs/7zip/unix/C/Delta.c
+++ b/src/libs/3rdparty/7zip/unix/C/Delta.c
diff --git a/src/libs/7zip/unix/C/Delta.h b/src/libs/3rdparty/7zip/unix/C/Delta.h
index 2fa54ad67..2fa54ad67 100644
--- a/src/libs/7zip/unix/C/Delta.h
+++ b/src/libs/3rdparty/7zip/unix/C/Delta.h
diff --git a/src/libs/7zip/unix/C/LzFind.c b/src/libs/3rdparty/7zip/unix/C/LzFind.c
index 9a4d25b80..9a4d25b80 100644
--- a/src/libs/7zip/unix/C/LzFind.c
+++ b/src/libs/3rdparty/7zip/unix/C/LzFind.c
diff --git a/src/libs/7zip/unix/C/LzFind.h b/src/libs/3rdparty/7zip/unix/C/LzFind.h
index 706143d25..706143d25 100644
--- a/src/libs/7zip/unix/C/LzFind.h
+++ b/src/libs/3rdparty/7zip/unix/C/LzFind.h
diff --git a/src/libs/7zip/unix/C/LzFindMt.c b/src/libs/3rdparty/7zip/unix/C/LzFindMt.c
index 8be0adaaf..8be0adaaf 100644
--- a/src/libs/7zip/unix/C/LzFindMt.c
+++ b/src/libs/3rdparty/7zip/unix/C/LzFindMt.c
diff --git a/src/libs/7zip/unix/C/LzFindMt.h b/src/libs/3rdparty/7zip/unix/C/LzFindMt.h
index 65cc12783..65cc12783 100644
--- a/src/libs/7zip/unix/C/LzFindMt.h
+++ b/src/libs/3rdparty/7zip/unix/C/LzFindMt.h
diff --git a/src/libs/7zip/unix/C/LzHash.h b/src/libs/3rdparty/7zip/unix/C/LzHash.h
index f3e89966c..f3e89966c 100644
--- a/src/libs/7zip/unix/C/LzHash.h
+++ b/src/libs/3rdparty/7zip/unix/C/LzHash.h
diff --git a/src/libs/7zip/unix/C/Lzma2Dec.c b/src/libs/3rdparty/7zip/unix/C/Lzma2Dec.c
index e7dcc2725..e7dcc2725 100644
--- a/src/libs/7zip/unix/C/Lzma2Dec.c
+++ b/src/libs/3rdparty/7zip/unix/C/Lzma2Dec.c
diff --git a/src/libs/7zip/unix/C/Lzma2Dec.h b/src/libs/3rdparty/7zip/unix/C/Lzma2Dec.h
index 367daf6b3..367daf6b3 100644
--- a/src/libs/7zip/unix/C/Lzma2Dec.h
+++ b/src/libs/3rdparty/7zip/unix/C/Lzma2Dec.h
diff --git a/src/libs/7zip/unix/C/Lzma2Enc.c b/src/libs/3rdparty/7zip/unix/C/Lzma2Enc.c
index 5d67cc344..5d67cc344 100644
--- a/src/libs/7zip/unix/C/Lzma2Enc.c
+++ b/src/libs/3rdparty/7zip/unix/C/Lzma2Enc.c
diff --git a/src/libs/7zip/unix/C/Lzma2Enc.h b/src/libs/3rdparty/7zip/unix/C/Lzma2Enc.h
index f409f184c..f409f184c 100644
--- a/src/libs/7zip/unix/C/Lzma2Enc.h
+++ b/src/libs/3rdparty/7zip/unix/C/Lzma2Enc.h
diff --git a/src/libs/7zip/unix/C/LzmaDec.c b/src/libs/3rdparty/7zip/unix/C/LzmaDec.c
index b1a2ad150..b1a2ad150 100644
--- a/src/libs/7zip/unix/C/LzmaDec.c
+++ b/src/libs/3rdparty/7zip/unix/C/LzmaDec.c
diff --git a/src/libs/7zip/unix/C/LzmaDec.h b/src/libs/3rdparty/7zip/unix/C/LzmaDec.h
index 63efc351f..63efc351f 100644
--- a/src/libs/7zip/unix/C/LzmaDec.h
+++ b/src/libs/3rdparty/7zip/unix/C/LzmaDec.h
diff --git a/src/libs/7zip/unix/C/LzmaEnc.c b/src/libs/3rdparty/7zip/unix/C/LzmaEnc.c
index bf3cc2ddb..bf3cc2ddb 100644
--- a/src/libs/7zip/unix/C/LzmaEnc.c
+++ b/src/libs/3rdparty/7zip/unix/C/LzmaEnc.c
diff --git a/src/libs/7zip/unix/C/LzmaEnc.h b/src/libs/3rdparty/7zip/unix/C/LzmaEnc.h
index cffe220bb..cffe220bb 100644
--- a/src/libs/7zip/unix/C/LzmaEnc.h
+++ b/src/libs/3rdparty/7zip/unix/C/LzmaEnc.h
diff --git a/src/libs/7zip/unix/C/MtCoder.c b/src/libs/3rdparty/7zip/unix/C/MtCoder.c
index 3d4dd2d14..3d4dd2d14 100644
--- a/src/libs/7zip/unix/C/MtCoder.c
+++ b/src/libs/3rdparty/7zip/unix/C/MtCoder.c
diff --git a/src/libs/7zip/unix/C/MtCoder.h b/src/libs/3rdparty/7zip/unix/C/MtCoder.h
index e2cbdc3ab..e2cbdc3ab 100644
--- a/src/libs/7zip/unix/C/MtCoder.h
+++ b/src/libs/3rdparty/7zip/unix/C/MtCoder.h
diff --git a/src/libs/7zip/unix/C/Precomp.h b/src/libs/3rdparty/7zip/unix/C/Precomp.h
index e8ff8b40e..e8ff8b40e 100644
--- a/src/libs/7zip/unix/C/Precomp.h
+++ b/src/libs/3rdparty/7zip/unix/C/Precomp.h
diff --git a/src/libs/7zip/unix/C/RotateDefs.h b/src/libs/3rdparty/7zip/unix/C/RotateDefs.h
index 1b83e5ea1..1b83e5ea1 100644
--- a/src/libs/7zip/unix/C/RotateDefs.h
+++ b/src/libs/3rdparty/7zip/unix/C/RotateDefs.h
diff --git a/src/libs/7zip/unix/C/Sha256.c b/src/libs/3rdparty/7zip/unix/C/Sha256.c
index 10df0874f..10df0874f 100644
--- a/src/libs/7zip/unix/C/Sha256.c
+++ b/src/libs/3rdparty/7zip/unix/C/Sha256.c
diff --git a/src/libs/7zip/unix/C/Sha256.h b/src/libs/3rdparty/7zip/unix/C/Sha256.h
index 3f455dbc0..3f455dbc0 100644
--- a/src/libs/7zip/unix/C/Sha256.h
+++ b/src/libs/3rdparty/7zip/unix/C/Sha256.h
diff --git a/src/libs/7zip/unix/C/Threads.c b/src/libs/3rdparty/7zip/unix/C/Threads.c
index f3fdb24e1..f3fdb24e1 100644
--- a/src/libs/7zip/unix/C/Threads.c
+++ b/src/libs/3rdparty/7zip/unix/C/Threads.c
diff --git a/src/libs/7zip/unix/C/Threads.h b/src/libs/3rdparty/7zip/unix/C/Threads.h
index a285bc901..a285bc901 100644
--- a/src/libs/7zip/unix/C/Threads.h
+++ b/src/libs/3rdparty/7zip/unix/C/Threads.h
diff --git a/src/libs/7zip/unix/C/Xz.c b/src/libs/3rdparty/7zip/unix/C/Xz.c
index fbc732a8a..fbc732a8a 100644
--- a/src/libs/7zip/unix/C/Xz.c
+++ b/src/libs/3rdparty/7zip/unix/C/Xz.c
diff --git a/src/libs/7zip/unix/C/Xz.h b/src/libs/3rdparty/7zip/unix/C/Xz.h
index 9268d5bc6..9268d5bc6 100644
--- a/src/libs/7zip/unix/C/Xz.h
+++ b/src/libs/3rdparty/7zip/unix/C/Xz.h
diff --git a/src/libs/7zip/unix/C/XzCrc64.c b/src/libs/3rdparty/7zip/unix/C/XzCrc64.c
index 2c04c0af4..2c04c0af4 100644
--- a/src/libs/7zip/unix/C/XzCrc64.c
+++ b/src/libs/3rdparty/7zip/unix/C/XzCrc64.c
diff --git a/src/libs/7zip/unix/C/XzCrc64.h b/src/libs/3rdparty/7zip/unix/C/XzCrc64.h
index 08dbc330c..08dbc330c 100644
--- a/src/libs/7zip/unix/C/XzCrc64.h
+++ b/src/libs/3rdparty/7zip/unix/C/XzCrc64.h
diff --git a/src/libs/7zip/unix/C/XzCrc64Opt.c b/src/libs/3rdparty/7zip/unix/C/XzCrc64Opt.c
index dccae1c19..dccae1c19 100644
--- a/src/libs/7zip/unix/C/XzCrc64Opt.c
+++ b/src/libs/3rdparty/7zip/unix/C/XzCrc64Opt.c
diff --git a/src/libs/7zip/unix/C/XzDec.c b/src/libs/3rdparty/7zip/unix/C/XzDec.c
index 6eef587d3..6eef587d3 100644
--- a/src/libs/7zip/unix/C/XzDec.c
+++ b/src/libs/3rdparty/7zip/unix/C/XzDec.c
diff --git a/src/libs/7zip/unix/C/XzEnc.c b/src/libs/3rdparty/7zip/unix/C/XzEnc.c
index 56680fcd8..56680fcd8 100644
--- a/src/libs/7zip/unix/C/XzEnc.c
+++ b/src/libs/3rdparty/7zip/unix/C/XzEnc.c
diff --git a/src/libs/7zip/unix/C/XzEnc.h b/src/libs/3rdparty/7zip/unix/C/XzEnc.h
index c3c19eca0..c3c19eca0 100644
--- a/src/libs/7zip/unix/C/XzEnc.h
+++ b/src/libs/3rdparty/7zip/unix/C/XzEnc.h
diff --git a/src/libs/7zip/unix/C/XzIn.c b/src/libs/3rdparty/7zip/unix/C/XzIn.c
index ed9eac31a..ed9eac31a 100644
--- a/src/libs/7zip/unix/C/XzIn.c
+++ b/src/libs/3rdparty/7zip/unix/C/XzIn.c
diff --git a/src/libs/7zip/unix/CPP/7zip/7zip.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/7zip.pri
index a2b70a1f2..a2b70a1f2 100644
--- a/src/libs/7zip/unix/CPP/7zip/7zip.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/7zip.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7z.pri
index 60211faae..60211faae 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7z.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h
index 5cde97c38..5cde97c38 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp
index 973966bd3..973966bd3 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h
index 54e9d2b52..54e9d2b52 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp
index 5f1436fc7..5f1436fc7 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h
index 8e20bdb5f..8e20bdb5f 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp
index bb350455c..bb350455c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 3f420a513..3f420a513 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h
index 4ed4b2dd2..4ed4b2dd2 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
index 847f65bf2..847f65bf2 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h
index cc2d77343..cc2d77343 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp
index ed65dc20c..ed65dc20c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h
index 677a3e10a..677a3e10a 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 7de5b8140..7de5b8140 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp
index acff2fdd8..acff2fdd8 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h
index 61dad655d..61dad655d 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp
index 28ec5e083..28ec5e083 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zIn.h
index 98f61c81e..98f61c81e 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zIn.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zItem.h
index c112f83fd..c112f83fd 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zItem.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp
index e20858ea7..e20858ea7 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zOut.h
index 391ca9d02..391ca9d02 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zOut.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp
index a29f8abe9..a29f8abe9 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zProperties.h
index 661817954..661817954 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zProperties.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp
index 37ea29d30..37ea29d30 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp
index 8e45d9875..8e45d9875 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.h
index 2e26efd5c..2e26efd5c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp
index c745e32f0..c745e32f0 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h
index aee2d5ed3..aee2d5ed3 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Archive.pri
index fe77cb0d4..fe77cb0d4 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Archive.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Archive.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp
index e562fec58..e562fec58 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h
index 50e7077ae..50e7077ae 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
index 36b252600..36b252600 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h
index 2190cf867..2190cf867 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/CoderMixer2MT.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/Common.pri
index 5443ba297..5443ba297 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/Common.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp
index 7c4f54879..7c4f54879 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h
index b5a51fc07..b5a51fc07 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/DummyOutStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp
index 7b875fbd0..7b875fbd0 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h
index eba2a19e1..eba2a19e1 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/HandlerOut.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
index a2d688328..a2d688328 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.h
index 31b761e45..31b761e45 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/InStreamWithCRC.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp
index 7cd3037be..7cd3037be 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h
index d0dc76a41..d0dc76a41 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ItemNameUtils.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp
index 17f749058..17f749058 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/MultiStream.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h
index 93aff33bf..93aff33bf 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/MultiStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
index f955c2254..f955c2254 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h
index 09b899bbd..09b899bbd 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/OutStreamWithCRC.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h
index 1038a8c02..1038a8c02 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/Common/ParseProperties.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/IArchive.h
index 038e05ed2..038e05ed2 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/IArchive.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/IArchive.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp
index 279cdefb7..279cdefb7 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/LzmaHandler.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp
index db9f49aa0..db9f49aa0 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/SplitHandler.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/XzHandler.cpp
index 789f41a72..789f41a72 100644
--- a/src/libs/7zip/unix/CPP/7zip/Archive/XzHandler.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Archive/XzHandler.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CWrappers.cpp
index a15794e2a..a15794e2a 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CWrappers.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CWrappers.h
index 4fe7dea3e..4fe7dea3e 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/CWrappers.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CWrappers.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/Common.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/Common.pri
index a23ad30b1..a23ad30b1 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/Common.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CreateCoder.cpp
index 01ccbe12a..01ccbe12a 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CreateCoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CreateCoder.h
index fe1f6ccfe..fe1f6ccfe 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/CreateCoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/CreateCoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp
index 958360fac..958360fac 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilePathAutoRename.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h
index 7b576591c..7b576591c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilePathAutoRename.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FileStreams.cpp
index ee1cc54e2..ee1cc54e2 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FileStreams.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FileStreams.h
index a80cbad4d..a80cbad4d 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FileStreams.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilterCoder.cpp
index 3a2023b35..3a2023b35 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilterCoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilterCoder.h
index 2b8f142f5..2b8f142f5 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/FilterCoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/FilterCoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InBuffer.cpp
index 133d95b38..133d95b38 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InBuffer.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InBuffer.h
index dd3c66808..dd3c66808 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/InBuffer.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InBuffer.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp
index be65ba32f..be65ba32f 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InOutTempBuffer.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h
index 256d72420..256d72420 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/InOutTempBuffer.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp
index 5f20dcda4..5f20dcda4 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LimitedStreams.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LimitedStreams.h
index b14616f3b..b14616f3b 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/LimitedStreams.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LimitedStreams.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/LockedStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LockedStream.cpp
index f05601cb6..f05601cb6 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/LockedStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LockedStream.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/LockedStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LockedStream.h
index 486e4220b..486e4220b 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/LockedStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/LockedStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodId.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodId.h
index 28b615fcd..28b615fcd 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/MethodId.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodId.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodProps.cpp
index ff61995b7..ff61995b7 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodProps.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodProps.h
index 39e2ee937..39e2ee937 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/MethodProps.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/MethodProps.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/OutBuffer.cpp
index 4ba34a053..4ba34a053 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/OutBuffer.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/OutBuffer.h
index 0baad3636..0baad3636 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/OutBuffer.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/OutBuffer.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp
index bac45c1c2..bac45c1c2 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/ProgressUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/ProgressUtils.h
index bae5395c1..bae5395c1 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/ProgressUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/ProgressUtils.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/PropId.cpp
index 10daef715..10daef715 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/PropId.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/PropId.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/RegisterArc.h
index 82bd09673..82bd09673 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/RegisterArc.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/RegisterCodec.h
index 0c6662a6c..0c6662a6c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/RegisterCodec.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamBinder.cpp
index 43feef1ba..43feef1ba 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamBinder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamBinder.h
index aba6b8e17..aba6b8e17 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/StreamBinder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamBinder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamObjects.cpp
index 7721c3a7e..7721c3a7e 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamObjects.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamObjects.h
index d0c86b566..d0c86b566 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/StreamObjects.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamObjects.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamUtils.cpp
index 1402f4205..1402f4205 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamUtils.h
index ae914c004..ae914c004 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/StreamUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/StreamUtils.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp
index 7fcc88f5e..7fcc88f5e 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/UniqBlocks.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/UniqBlocks.h
index 9c08b09f4..9c08b09f4 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/UniqBlocks.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/UniqBlocks.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/VirtThread.cpp
index 77e3c1acf..77e3c1acf 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/VirtThread.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/VirtThread.h
index ebee158ca..ebee158ca 100644
--- a/src/libs/7zip/unix/CPP/7zip/Common/VirtThread.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Common/VirtThread.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp
index 9da6b9c28..9da6b9c28 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Coder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h
index e7bd37951..e7bd37951 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Coder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Register.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Register.cpp
index 8eb1e7360..8eb1e7360 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Bcj2Register.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Bcj2Register.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BcjCoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjCoder.cpp
index 0e34ef488..0e34ef488 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BcjCoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjCoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BcjCoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjCoder.h
index 0754bcd23..0754bcd23 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BcjCoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjCoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BcjRegister.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjRegister.cpp
index 648ad8e03..648ad8e03 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BcjRegister.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BcjRegister.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BranchCoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchCoder.cpp
index 431709526..431709526 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BranchCoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchCoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BranchCoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchCoder.h
index 0e3a5c4e1..0e3a5c4e1 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BranchCoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchCoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp
index 239f25138..239f25138 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchMisc.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchMisc.h
index 81198b21c..81198b21c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BranchMisc.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchMisc.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/BranchRegister.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchRegister.cpp
index 380828c6d..380828c6d 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/BranchRegister.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/BranchRegister.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/ByteSwap.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/ByteSwap.cpp
index 645b6ffcd..645b6ffcd 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/ByteSwap.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/ByteSwap.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Compress.pri
index c9a7a5045..c9a7a5045 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Compress.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Compress.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp
index f0863202a..f0863202a 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyCoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyCoder.h
index 5e0bb6436..5e0bb6436 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/CopyCoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyCoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/CopyRegister.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyRegister.cpp
index efb9b9e95..efb9b9e95 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/CopyRegister.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/CopyRegister.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp
index d8378a60e..d8378a60e 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/DeltaFilter.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp
index b20ae5f5e..b20ae5f5e 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.h
index fd7ca2f39..fd7ca2f39 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Decoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp
index f867881c0..f867881c0 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h
index 6a2318076..6a2318076 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Encoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Register.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Register.cpp
index cace871ef..cace871ef 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Lzma2Register.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/Lzma2Register.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp
index d378ba668..d378ba668 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaDecoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h
index 140c48b9c..140c48b9c 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaDecoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp
index 484d04523..484d04523 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaEncoder.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h
index 7e15a132d..7e15a132d 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaEncoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaRegister.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaRegister.cpp
index 96ed0baed..96ed0baed 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/LzmaRegister.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/LzmaRegister.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/RangeCoder.h
index 1555bd705..1555bd705 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/RangeCoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h
index 0eddd5586..0eddd5586 100644
--- a/src/libs/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Compress/RangeCoderBit.h
diff --git a/src/libs/7zip/unix/CPP/7zip/Guid.txt b/src/libs/3rdparty/7zip/unix/CPP/7zip/Guid.txt
index c1e7446be..c1e7446be 100644
--- a/src/libs/7zip/unix/CPP/7zip/Guid.txt
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/Guid.txt
diff --git a/src/libs/7zip/unix/CPP/7zip/ICoder.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/ICoder.h
index 74ee0e453..74ee0e453 100644
--- a/src/libs/7zip/unix/CPP/7zip/ICoder.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/ICoder.h
diff --git a/src/libs/7zip/unix/CPP/7zip/IDecl.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/IDecl.h
index 8316eb3ac..8316eb3ac 100644
--- a/src/libs/7zip/unix/CPP/7zip/IDecl.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/IDecl.h
diff --git a/src/libs/7zip/unix/CPP/7zip/IPassword.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/IPassword.h
index 7ea45537e..7ea45537e 100644
--- a/src/libs/7zip/unix/CPP/7zip/IPassword.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/IPassword.h
diff --git a/src/libs/7zip/unix/CPP/7zip/IProgress.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/IProgress.h
index a270e693b..a270e693b 100644
--- a/src/libs/7zip/unix/CPP/7zip/IProgress.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/IProgress.h
diff --git a/src/libs/7zip/unix/CPP/7zip/IStream.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/IStream.h
index 48643e7b3..48643e7b3 100644
--- a/src/libs/7zip/unix/CPP/7zip/IStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/IStream.h
diff --git a/src/libs/7zip/unix/CPP/7zip/PropID.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/PropID.h
index 82a7462bb..82a7462bb 100644
--- a/src/libs/7zip/unix/CPP/7zip/PropID.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/PropID.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 48587264f..48587264f 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h
index 255e12c3c..255e12c3c 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 250f66797..250f66797 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 374297651..374297651 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index 9eab39d31..9eab39d31 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index b72892c2f..b72892c2f 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Common.pri
index a1d75b674..a1d75b674 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Common.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp
index ce0b327b5..ce0b327b5 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DefaultName.h
index df1645602..df1645602 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DefaultName.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DirItem.h
index 82203c03a..82203c03a 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/DirItem.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp
index b94e6274c..b94e6274c 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h
index 803a64e7d..803a64e7d 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
index 5f94254ef..5f94254ef 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Extract.h
index 052b2f7d3..052b2f7d3 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Extract.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h
index a54376705..a54376705 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index 852fd5adb..852fd5adb 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h
index 751248a97..751248a97 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp
index 2d13a2af1..2d13a2af1 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/HashCalc.h
index 68e2404cc..68e2404cc 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/HashCalc.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h
index 7bb852795..7bb852795 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp
index 09c79147d..09c79147d 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h
index d254ae659..d254ae659 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp
index 7c53bd99f..7c53bd99f 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h
index f2a5ce9fe..f2a5ce9fe 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp
index 5ba8c7a89..5ba8c7a89 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h
index 3ee2981de..3ee2981de 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Property.h
index 8b57a2a64..8b57a2a64 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Property.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp
index 64b9d92a6..64b9d92a6 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SetProperties.h
index 892f1a210..892f1a210 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SetProperties.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp
index b7e422a29..b7e422a29 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SortUtils.h
index 8e42e0682..8e42e0682 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/SortUtils.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp
index 0c13ae158..0c13ae158 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/TempFiles.h
index 4099e6558..4099e6558 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/TempFiles.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Update.cpp
index 4697dca46..4697dca46 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Update.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Update.h
index b2fdb4647..b2fdb4647 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/Update.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp
index a80db7212..a80db7212 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h
index b6645cbdd..b6645cbdd 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp
index 609ece856..609ece856 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h
index 81982e61d..81982e61d 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp
index 95afdd694..95afdd694 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h
index 296d3b097..296d3b097 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp
index 2c4c28583..2c4c28583 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h
index ef7b0f7a3..ef7b0f7a3 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/Console.pri
index cdb025475..cdb025475 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/Console.pri
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp
index f2889957a..f2889957a 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h
index 509bab5fc..509bab5fc 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h
diff --git a/src/libs/7zip/unix/CPP/Common/ComTry.h b/src/libs/3rdparty/7zip/unix/CPP/Common/ComTry.h
index 04bfe6320..04bfe6320 100644
--- a/src/libs/7zip/unix/CPP/Common/ComTry.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/ComTry.h
diff --git a/src/libs/7zip/unix/CPP/Common/CommandLineParser.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/CommandLineParser.cpp
index 749c4a2ea..749c4a2ea 100644
--- a/src/libs/7zip/unix/CPP/Common/CommandLineParser.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/CommandLineParser.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/CommandLineParser.h b/src/libs/3rdparty/7zip/unix/CPP/Common/CommandLineParser.h
index e3e6e6b14..e3e6e6b14 100644
--- a/src/libs/7zip/unix/CPP/Common/CommandLineParser.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/CommandLineParser.h
diff --git a/src/libs/7zip/unix/CPP/Common/Common.h b/src/libs/3rdparty/7zip/unix/CPP/Common/Common.h
index 9dd30f4be..9dd30f4be 100644
--- a/src/libs/7zip/unix/CPP/Common/Common.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/Common.h
diff --git a/src/libs/7zip/unix/CPP/Common/Common.pri b/src/libs/3rdparty/7zip/unix/CPP/Common/Common.pri
index eec23a144..eec23a144 100644
--- a/src/libs/7zip/unix/CPP/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/Common.pri
diff --git a/src/libs/7zip/unix/CPP/Common/Defs.h b/src/libs/3rdparty/7zip/unix/CPP/Common/Defs.h
index dad3ae8f1..dad3ae8f1 100644
--- a/src/libs/7zip/unix/CPP/Common/Defs.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/Defs.h
diff --git a/src/libs/7zip/unix/CPP/Common/IntToString.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/IntToString.cpp
index ed217c72c..ed217c72c 100644
--- a/src/libs/7zip/unix/CPP/Common/IntToString.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/IntToString.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/IntToString.h b/src/libs/3rdparty/7zip/unix/CPP/Common/IntToString.h
index 69605ab76..69605ab76 100644
--- a/src/libs/7zip/unix/CPP/Common/IntToString.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/IntToString.h
diff --git a/src/libs/7zip/unix/CPP/Common/ListFileUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/ListFileUtils.cpp
index cede1ae54..cede1ae54 100644
--- a/src/libs/7zip/unix/CPP/Common/ListFileUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/ListFileUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/ListFileUtils.h b/src/libs/3rdparty/7zip/unix/CPP/Common/ListFileUtils.h
index e8d833fdb..e8d833fdb 100644
--- a/src/libs/7zip/unix/CPP/Common/ListFileUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/ListFileUtils.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyBuffer.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyBuffer.h
index 7bd79f6f4..7bd79f6f4 100644
--- a/src/libs/7zip/unix/CPP/Common/MyBuffer.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyBuffer.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyCom.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyCom.h
index 466407cde..466407cde 100644
--- a/src/libs/7zip/unix/CPP/Common/MyCom.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyCom.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyException.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyException.h
index f0ad11158..f0ad11158 100644
--- a/src/libs/7zip/unix/CPP/Common/MyException.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyException.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyGuidDef.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyGuidDef.h
index 68745870e..68745870e 100644
--- a/src/libs/7zip/unix/CPP/Common/MyGuidDef.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyGuidDef.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyInitGuid.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyInitGuid.h
index 279fba5d6..279fba5d6 100644
--- a/src/libs/7zip/unix/CPP/Common/MyInitGuid.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyInitGuid.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyString.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/MyString.cpp
index 6fbfa334b..6fbfa334b 100644
--- a/src/libs/7zip/unix/CPP/Common/MyString.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyString.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/MyString.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyString.h
index 638ceed9b..638ceed9b 100644
--- a/src/libs/7zip/unix/CPP/Common/MyString.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyString.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyTypes.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyTypes.h
index fe41188db..fe41188db 100644
--- a/src/libs/7zip/unix/CPP/Common/MyTypes.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyTypes.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyUnknown.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyUnknown.h
index 8b95afd38..8b95afd38 100644
--- a/src/libs/7zip/unix/CPP/Common/MyUnknown.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyUnknown.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyVector.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyVector.h
index 7e61dec31..7e61dec31 100644
--- a/src/libs/7zip/unix/CPP/Common/MyVector.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyVector.h
diff --git a/src/libs/7zip/unix/CPP/Common/MyWindows.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/MyWindows.cpp
index 9acddc974..9acddc974 100644
--- a/src/libs/7zip/unix/CPP/Common/MyWindows.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyWindows.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/MyWindows.h b/src/libs/3rdparty/7zip/unix/CPP/Common/MyWindows.h
index 83a896283..83a896283 100644
--- a/src/libs/7zip/unix/CPP/Common/MyWindows.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/MyWindows.h
diff --git a/src/libs/7zip/unix/CPP/Common/NewHandler.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/NewHandler.cpp
index e53f1d14d..e53f1d14d 100644
--- a/src/libs/7zip/unix/CPP/Common/NewHandler.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/NewHandler.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/NewHandler.h b/src/libs/3rdparty/7zip/unix/CPP/Common/NewHandler.h
index e3e7422c8..e3e7422c8 100644
--- a/src/libs/7zip/unix/CPP/Common/NewHandler.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/NewHandler.h
diff --git a/src/libs/7zip/unix/CPP/Common/StdOutStream.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/StdOutStream.cpp
index 6aed31a31..6aed31a31 100644
--- a/src/libs/7zip/unix/CPP/Common/StdOutStream.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/StdOutStream.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/StdOutStream.h b/src/libs/3rdparty/7zip/unix/CPP/Common/StdOutStream.h
index 0a8c0febb..0a8c0febb 100644
--- a/src/libs/7zip/unix/CPP/Common/StdOutStream.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/StdOutStream.h
diff --git a/src/libs/7zip/unix/CPP/Common/StringConvert.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/StringConvert.cpp
index 78f3d90ef..78f3d90ef 100644
--- a/src/libs/7zip/unix/CPP/Common/StringConvert.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/StringConvert.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/StringConvert.h b/src/libs/3rdparty/7zip/unix/CPP/Common/StringConvert.h
index 8eea72ef2..8eea72ef2 100644
--- a/src/libs/7zip/unix/CPP/Common/StringConvert.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/StringConvert.h
diff --git a/src/libs/7zip/unix/CPP/Common/StringToInt.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/StringToInt.cpp
index 2023fcc2c..2023fcc2c 100644
--- a/src/libs/7zip/unix/CPP/Common/StringToInt.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/StringToInt.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/StringToInt.h b/src/libs/3rdparty/7zip/unix/CPP/Common/StringToInt.h
index 5c5d7d7fe..5c5d7d7fe 100644
--- a/src/libs/7zip/unix/CPP/Common/StringToInt.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/StringToInt.h
diff --git a/src/libs/7zip/unix/CPP/Common/UTFConvert.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/UTFConvert.cpp
index 38bac3331..38bac3331 100644
--- a/src/libs/7zip/unix/CPP/Common/UTFConvert.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/UTFConvert.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/UTFConvert.h b/src/libs/3rdparty/7zip/unix/CPP/Common/UTFConvert.h
index 16b02fe45..16b02fe45 100644
--- a/src/libs/7zip/unix/CPP/Common/UTFConvert.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/UTFConvert.h
diff --git a/src/libs/7zip/unix/CPP/Common/Wildcard.cpp b/src/libs/3rdparty/7zip/unix/CPP/Common/Wildcard.cpp
index e88a1cf1c..e88a1cf1c 100644
--- a/src/libs/7zip/unix/CPP/Common/Wildcard.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/Wildcard.cpp
diff --git a/src/libs/7zip/unix/CPP/Common/Wildcard.h b/src/libs/3rdparty/7zip/unix/CPP/Common/Wildcard.h
index a645e28b5..a645e28b5 100644
--- a/src/libs/7zip/unix/CPP/Common/Wildcard.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Common/Wildcard.h
diff --git a/src/libs/7zip/unix/CPP/Windows/DLL.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/DLL.cpp
index 345153cb2..345153cb2 100644
--- a/src/libs/7zip/unix/CPP/Windows/DLL.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/DLL.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/DLL.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/DLL.h
index 2e044ec59..2e044ec59 100644
--- a/src/libs/7zip/unix/CPP/Windows/DLL.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/DLL.h
diff --git a/src/libs/7zip/unix/CPP/Windows/Defs.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/Defs.h
index b88df748d..b88df748d 100644
--- a/src/libs/7zip/unix/CPP/Windows/Defs.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/Defs.h
diff --git a/src/libs/7zip/unix/CPP/Windows/FileDir.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileDir.cpp
index 9915bd8b8..9915bd8b8 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileDir.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileDir.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/FileDir.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileDir.h
index 02d3e5a57..02d3e5a57 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileDir.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileDir.h
diff --git a/src/libs/7zip/unix/CPP/Windows/FileFind.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileFind.cpp
index eb2f93835..eb2f93835 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileFind.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileFind.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/FileFind.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileFind.h
index 06435bb3d..06435bb3d 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileFind.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileFind.h
diff --git a/src/libs/7zip/unix/CPP/Windows/FileIO.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileIO.cpp
index 5da074a0f..5da074a0f 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileIO.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileIO.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/FileIO.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileIO.h
index a262e5610..a262e5610 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileIO.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileIO.h
diff --git a/src/libs/7zip/unix/CPP/Windows/FileName.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileName.cpp
index b726976fe..b726976fe 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileName.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileName.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/FileName.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileName.h
index 19c585fc9..19c585fc9 100644
--- a/src/libs/7zip/unix/CPP/Windows/FileName.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/FileName.h
diff --git a/src/libs/7zip/unix/CPP/Windows/PropVariant.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariant.cpp
index d16f576cc..d16f576cc 100644
--- a/src/libs/7zip/unix/CPP/Windows/PropVariant.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariant.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/PropVariant.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariant.h
index d71b85e1d..d71b85e1d 100644
--- a/src/libs/7zip/unix/CPP/Windows/PropVariant.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariant.h
diff --git a/src/libs/7zip/unix/CPP/Windows/PropVariantConv.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariantConv.cpp
index dfb93d6d6..dfb93d6d6 100644
--- a/src/libs/7zip/unix/CPP/Windows/PropVariantConv.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariantConv.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/PropVariantConv.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariantConv.h
index 5d26357f0..5d26357f0 100644
--- a/src/libs/7zip/unix/CPP/Windows/PropVariantConv.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/PropVariantConv.h
diff --git a/src/libs/7zip/unix/CPP/Windows/Synchronization.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization.cpp
index 4be33e1e9..4be33e1e9 100644
--- a/src/libs/7zip/unix/CPP/Windows/Synchronization.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/Synchronization.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization.h
index 1c45a1b78..1c45a1b78 100644
--- a/src/libs/7zip/unix/CPP/Windows/Synchronization.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization.h
diff --git a/src/libs/7zip/unix/CPP/Windows/Synchronization2.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization2.h
index ff8f7a752..ff8f7a752 100644
--- a/src/libs/7zip/unix/CPP/Windows/Synchronization2.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/Synchronization2.h
diff --git a/src/libs/7zip/unix/CPP/Windows/System.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/System.cpp
index 55e723c40..55e723c40 100644
--- a/src/libs/7zip/unix/CPP/Windows/System.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/System.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/System.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/System.h
index 4133a7b30..4133a7b30 100644
--- a/src/libs/7zip/unix/CPP/Windows/System.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/System.h
diff --git a/src/libs/7zip/unix/CPP/Windows/Thread.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/Thread.h
index 944f19744..944f19744 100644
--- a/src/libs/7zip/unix/CPP/Windows/Thread.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/Thread.h
diff --git a/src/libs/7zip/unix/CPP/Windows/TimeUtils.cpp b/src/libs/3rdparty/7zip/unix/CPP/Windows/TimeUtils.cpp
index 7ef44d9cc..7ef44d9cc 100644
--- a/src/libs/7zip/unix/CPP/Windows/TimeUtils.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/TimeUtils.cpp
diff --git a/src/libs/7zip/unix/CPP/Windows/TimeUtils.h b/src/libs/3rdparty/7zip/unix/CPP/Windows/TimeUtils.h
index 2967214e6..2967214e6 100644
--- a/src/libs/7zip/unix/CPP/Windows/TimeUtils.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/TimeUtils.h
diff --git a/src/libs/7zip/unix/CPP/Windows/Windows.pri b/src/libs/3rdparty/7zip/unix/CPP/Windows/Windows.pri
index 117fb37b3..117fb37b3 100644
--- a/src/libs/7zip/unix/CPP/Windows/Windows.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/Windows/Windows.pri
diff --git a/src/libs/7zip/unix/CPP/include_windows/basetyps.h b/src/libs/3rdparty/7zip/unix/CPP/include_windows/basetyps.h
index 2200cb7c3..2200cb7c3 100644
--- a/src/libs/7zip/unix/CPP/include_windows/basetyps.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/include_windows/basetyps.h
diff --git a/src/libs/7zip/unix/CPP/include_windows/include_windows.pri b/src/libs/3rdparty/7zip/unix/CPP/include_windows/include_windows.pri
index 5ef72fddd..5ef72fddd 100644
--- a/src/libs/7zip/unix/CPP/include_windows/include_windows.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/include_windows/include_windows.pri
diff --git a/src/libs/7zip/unix/CPP/include_windows/tchar.h b/src/libs/3rdparty/7zip/unix/CPP/include_windows/tchar.h
index 5e89145af..5e89145af 100644
--- a/src/libs/7zip/unix/CPP/include_windows/tchar.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/include_windows/tchar.h
diff --git a/src/libs/7zip/unix/CPP/include_windows/windows.h b/src/libs/3rdparty/7zip/unix/CPP/include_windows/windows.h
index 59541864c..59541864c 100644
--- a/src/libs/7zip/unix/CPP/include_windows/windows.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/include_windows/windows.h
diff --git a/src/libs/7zip/unix/CPP/myWindows/StdAfx.h b/src/libs/3rdparty/7zip/unix/CPP/myWindows/StdAfx.h
index 86ce117a9..86ce117a9 100644
--- a/src/libs/7zip/unix/CPP/myWindows/StdAfx.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/StdAfx.h
diff --git a/src/libs/7zip/unix/CPP/myWindows/config.h b/src/libs/3rdparty/7zip/unix/CPP/myWindows/config.h
index ee7d11882..ee7d11882 100644
--- a/src/libs/7zip/unix/CPP/myWindows/config.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/config.h
diff --git a/src/libs/7zip/unix/CPP/myWindows/initguid.h b/src/libs/3rdparty/7zip/unix/CPP/myWindows/initguid.h
index f7580d571..f7580d571 100644
--- a/src/libs/7zip/unix/CPP/myWindows/initguid.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/initguid.h
diff --git a/src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
index b4b444392..e101db855 100644
--- a/src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
@@ -1,32 +1,26 @@
/**************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -43,7 +37,7 @@ void SplitCommandLine(const UString &s, UStringVector &parts)
parts.Clear();
const QString cmdLine = QString::fromStdWString(static_cast<const wchar_t*>(s));
- const QStringList args = cmdLine.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const QStringList args = cmdLine.simplified().split(QLatin1Char(' '), Qt::SkipEmptyParts);
foreach (const QString &arg, args)
parts.Add(arg.toStdWString().c_str());
}
diff --git a/src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myDateAndTime.cpp
index 0c8deef18..0c8deef18 100644
--- a/src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myDateAndTime.cpp
diff --git a/src/libs/7zip/unix/CPP/myWindows/myPrivate.h b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myPrivate.h
index 73739d095..73739d095 100644
--- a/src/libs/7zip/unix/CPP/myWindows/myPrivate.h
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myPrivate.h
diff --git a/src/libs/7zip/unix/CPP/myWindows/myWindows.pri b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myWindows.pri
index 0875fdb1f..0875fdb1f 100644
--- a/src/libs/7zip/unix/CPP/myWindows/myWindows.pri
+++ b/src/libs/3rdparty/7zip/unix/CPP/myWindows/myWindows.pri
diff --git a/src/libs/7zip/unix/unix.pri b/src/libs/3rdparty/7zip/unix/unix.pri
index 6071add8f..6071add8f 100644
--- a/src/libs/7zip/unix/unix.pri
+++ b/src/libs/3rdparty/7zip/unix/unix.pri
diff --git a/src/libs/7zip/win/C/7zCrc.c b/src/libs/3rdparty/7zip/win/C/7zCrc.c
index 5f32380dd..5f32380dd 100644
--- a/src/libs/7zip/win/C/7zCrc.c
+++ b/src/libs/3rdparty/7zip/win/C/7zCrc.c
diff --git a/src/libs/7zip/win/C/7zCrc.h b/src/libs/3rdparty/7zip/win/C/7zCrc.h
index 8fd579587..8fd579587 100644
--- a/src/libs/7zip/win/C/7zCrc.h
+++ b/src/libs/3rdparty/7zip/win/C/7zCrc.h
diff --git a/src/libs/7zip/win/C/7zCrcOpt.c b/src/libs/3rdparty/7zip/win/C/7zCrcOpt.c
index ce132b5d4..ce132b5d4 100644
--- a/src/libs/7zip/win/C/7zCrcOpt.c
+++ b/src/libs/3rdparty/7zip/win/C/7zCrcOpt.c
diff --git a/src/libs/7zip/win/C/7zStream.c b/src/libs/3rdparty/7zip/win/C/7zStream.c
index 88f9c42b1..88f9c42b1 100644
--- a/src/libs/7zip/win/C/7zStream.c
+++ b/src/libs/3rdparty/7zip/win/C/7zStream.c
diff --git a/src/libs/7zip/win/C/7zTypes.h b/src/libs/3rdparty/7zip/win/C/7zTypes.h
index 778413ef4..778413ef4 100644
--- a/src/libs/7zip/win/C/7zTypes.h
+++ b/src/libs/3rdparty/7zip/win/C/7zTypes.h
diff --git a/src/libs/7zip/win/C/7zVersion.h b/src/libs/3rdparty/7zip/win/C/7zVersion.h
index 475918352..475918352 100644
--- a/src/libs/7zip/win/C/7zVersion.h
+++ b/src/libs/3rdparty/7zip/win/C/7zVersion.h
diff --git a/src/libs/7zip/win/C/Alloc.c b/src/libs/3rdparty/7zip/win/C/Alloc.c
index 1f3f6c661..1f3f6c661 100644
--- a/src/libs/7zip/win/C/Alloc.c
+++ b/src/libs/3rdparty/7zip/win/C/Alloc.c
diff --git a/src/libs/7zip/win/C/Alloc.h b/src/libs/3rdparty/7zip/win/C/Alloc.h
index b8e414367..b8e414367 100644
--- a/src/libs/7zip/win/C/Alloc.h
+++ b/src/libs/3rdparty/7zip/win/C/Alloc.h
diff --git a/src/libs/7zip/win/C/Bra.c b/src/libs/3rdparty/7zip/win/C/Bra.c
index 33f7a391c..33f7a391c 100644
--- a/src/libs/7zip/win/C/Bra.c
+++ b/src/libs/3rdparty/7zip/win/C/Bra.c
diff --git a/src/libs/7zip/win/C/Bra.h b/src/libs/3rdparty/7zip/win/C/Bra.h
index 184c291a7..184c291a7 100644
--- a/src/libs/7zip/win/C/Bra.h
+++ b/src/libs/3rdparty/7zip/win/C/Bra.h
diff --git a/src/libs/7zip/win/C/Bra86.c b/src/libs/3rdparty/7zip/win/C/Bra86.c
index 6db15e7ec..6db15e7ec 100644
--- a/src/libs/7zip/win/C/Bra86.c
+++ b/src/libs/3rdparty/7zip/win/C/Bra86.c
diff --git a/src/libs/7zip/win/C/BraIA64.c b/src/libs/3rdparty/7zip/win/C/BraIA64.c
index aa1a44e1e..aa1a44e1e 100644
--- a/src/libs/7zip/win/C/BraIA64.c
+++ b/src/libs/3rdparty/7zip/win/C/BraIA64.c
diff --git a/src/libs/7zip/win/C/C.pri b/src/libs/3rdparty/7zip/win/C/C.pri
index 23d688642..23d688642 100644
--- a/src/libs/7zip/win/C/C.pri
+++ b/src/libs/3rdparty/7zip/win/C/C.pri
diff --git a/src/libs/7zip/win/C/Compiler.h b/src/libs/3rdparty/7zip/win/C/Compiler.h
index 6e964897e..6e964897e 100644
--- a/src/libs/7zip/win/C/Compiler.h
+++ b/src/libs/3rdparty/7zip/win/C/Compiler.h
diff --git a/src/libs/7zip/win/C/CpuArch.c b/src/libs/3rdparty/7zip/win/C/CpuArch.c
index 4feb028a2..4feb028a2 100644
--- a/src/libs/7zip/win/C/CpuArch.c
+++ b/src/libs/3rdparty/7zip/win/C/CpuArch.c
diff --git a/src/libs/7zip/win/C/CpuArch.h b/src/libs/3rdparty/7zip/win/C/CpuArch.h
index 4fee00937..4fee00937 100644
--- a/src/libs/7zip/win/C/CpuArch.h
+++ b/src/libs/3rdparty/7zip/win/C/CpuArch.h
diff --git a/src/libs/7zip/win/C/Delta.c b/src/libs/3rdparty/7zip/win/C/Delta.c
index e3edd21ed..e3edd21ed 100644
--- a/src/libs/7zip/win/C/Delta.c
+++ b/src/libs/3rdparty/7zip/win/C/Delta.c
diff --git a/src/libs/7zip/win/C/Delta.h b/src/libs/3rdparty/7zip/win/C/Delta.h
index 2fa54ad67..2fa54ad67 100644
--- a/src/libs/7zip/win/C/Delta.h
+++ b/src/libs/3rdparty/7zip/win/C/Delta.h
diff --git a/src/libs/7zip/win/C/LzFind.c b/src/libs/3rdparty/7zip/win/C/LzFind.c
index 9a4d25b80..9a4d25b80 100644
--- a/src/libs/7zip/win/C/LzFind.c
+++ b/src/libs/3rdparty/7zip/win/C/LzFind.c
diff --git a/src/libs/7zip/win/C/LzFind.h b/src/libs/3rdparty/7zip/win/C/LzFind.h
index 706143d25..706143d25 100644
--- a/src/libs/7zip/win/C/LzFind.h
+++ b/src/libs/3rdparty/7zip/win/C/LzFind.h
diff --git a/src/libs/7zip/win/C/LzFindMt.c b/src/libs/3rdparty/7zip/win/C/LzFindMt.c
index 8be0adaaf..8be0adaaf 100644
--- a/src/libs/7zip/win/C/LzFindMt.c
+++ b/src/libs/3rdparty/7zip/win/C/LzFindMt.c
diff --git a/src/libs/7zip/win/C/LzFindMt.h b/src/libs/3rdparty/7zip/win/C/LzFindMt.h
index 65cc12783..65cc12783 100644
--- a/src/libs/7zip/win/C/LzFindMt.h
+++ b/src/libs/3rdparty/7zip/win/C/LzFindMt.h
diff --git a/src/libs/7zip/win/C/LzHash.h b/src/libs/3rdparty/7zip/win/C/LzHash.h
index f3e89966c..f3e89966c 100644
--- a/src/libs/7zip/win/C/LzHash.h
+++ b/src/libs/3rdparty/7zip/win/C/LzHash.h
diff --git a/src/libs/7zip/win/C/Lzma2Dec.c b/src/libs/3rdparty/7zip/win/C/Lzma2Dec.c
index e7dcc2725..e7dcc2725 100644
--- a/src/libs/7zip/win/C/Lzma2Dec.c
+++ b/src/libs/3rdparty/7zip/win/C/Lzma2Dec.c
diff --git a/src/libs/7zip/win/C/Lzma2Dec.h b/src/libs/3rdparty/7zip/win/C/Lzma2Dec.h
index 367daf6b3..367daf6b3 100644
--- a/src/libs/7zip/win/C/Lzma2Dec.h
+++ b/src/libs/3rdparty/7zip/win/C/Lzma2Dec.h
diff --git a/src/libs/7zip/win/C/Lzma2Enc.c b/src/libs/3rdparty/7zip/win/C/Lzma2Enc.c
index 5d67cc344..5d67cc344 100644
--- a/src/libs/7zip/win/C/Lzma2Enc.c
+++ b/src/libs/3rdparty/7zip/win/C/Lzma2Enc.c
diff --git a/src/libs/7zip/win/C/Lzma2Enc.h b/src/libs/3rdparty/7zip/win/C/Lzma2Enc.h
index f409f184c..f409f184c 100644
--- a/src/libs/7zip/win/C/Lzma2Enc.h
+++ b/src/libs/3rdparty/7zip/win/C/Lzma2Enc.h
diff --git a/src/libs/7zip/win/C/LzmaDec.c b/src/libs/3rdparty/7zip/win/C/LzmaDec.c
index b1a2ad150..b1a2ad150 100644
--- a/src/libs/7zip/win/C/LzmaDec.c
+++ b/src/libs/3rdparty/7zip/win/C/LzmaDec.c
diff --git a/src/libs/7zip/win/C/LzmaDec.h b/src/libs/3rdparty/7zip/win/C/LzmaDec.h
index 63efc351f..63efc351f 100644
--- a/src/libs/7zip/win/C/LzmaDec.h
+++ b/src/libs/3rdparty/7zip/win/C/LzmaDec.h
diff --git a/src/libs/7zip/win/C/LzmaEnc.c b/src/libs/3rdparty/7zip/win/C/LzmaEnc.c
index bf3cc2ddb..bf3cc2ddb 100644
--- a/src/libs/7zip/win/C/LzmaEnc.c
+++ b/src/libs/3rdparty/7zip/win/C/LzmaEnc.c
diff --git a/src/libs/7zip/win/C/LzmaEnc.h b/src/libs/3rdparty/7zip/win/C/LzmaEnc.h
index cffe220bb..cffe220bb 100644
--- a/src/libs/7zip/win/C/LzmaEnc.h
+++ b/src/libs/3rdparty/7zip/win/C/LzmaEnc.h
diff --git a/src/libs/7zip/win/C/MtCoder.c b/src/libs/3rdparty/7zip/win/C/MtCoder.c
index 3d4dd2d14..3d4dd2d14 100644
--- a/src/libs/7zip/win/C/MtCoder.c
+++ b/src/libs/3rdparty/7zip/win/C/MtCoder.c
diff --git a/src/libs/7zip/win/C/MtCoder.h b/src/libs/3rdparty/7zip/win/C/MtCoder.h
index e2cbdc3ab..e2cbdc3ab 100644
--- a/src/libs/7zip/win/C/MtCoder.h
+++ b/src/libs/3rdparty/7zip/win/C/MtCoder.h
diff --git a/src/libs/7zip/win/C/Precomp.h b/src/libs/3rdparty/7zip/win/C/Precomp.h
index e8ff8b40e..e8ff8b40e 100644
--- a/src/libs/7zip/win/C/Precomp.h
+++ b/src/libs/3rdparty/7zip/win/C/Precomp.h
diff --git a/src/libs/7zip/win/C/RotateDefs.h b/src/libs/3rdparty/7zip/win/C/RotateDefs.h
index 1b83e5ea1..1b83e5ea1 100644
--- a/src/libs/7zip/win/C/RotateDefs.h
+++ b/src/libs/3rdparty/7zip/win/C/RotateDefs.h
diff --git a/src/libs/7zip/win/C/Sha256.c b/src/libs/3rdparty/7zip/win/C/Sha256.c
index 10df0874f..10df0874f 100644
--- a/src/libs/7zip/win/C/Sha256.c
+++ b/src/libs/3rdparty/7zip/win/C/Sha256.c
diff --git a/src/libs/7zip/win/C/Sha256.h b/src/libs/3rdparty/7zip/win/C/Sha256.h
index 3f455dbc0..3f455dbc0 100644
--- a/src/libs/7zip/win/C/Sha256.h
+++ b/src/libs/3rdparty/7zip/win/C/Sha256.h
diff --git a/src/libs/7zip/win/C/Threads.c b/src/libs/3rdparty/7zip/win/C/Threads.c
index 5c67a1e26..5c67a1e26 100644
--- a/src/libs/7zip/win/C/Threads.c
+++ b/src/libs/3rdparty/7zip/win/C/Threads.c
diff --git a/src/libs/7zip/win/C/Threads.h b/src/libs/3rdparty/7zip/win/C/Threads.h
index 9b3e1c556..9b3e1c556 100644
--- a/src/libs/7zip/win/C/Threads.h
+++ b/src/libs/3rdparty/7zip/win/C/Threads.h
diff --git a/src/libs/7zip/win/C/Xz.c b/src/libs/3rdparty/7zip/win/C/Xz.c
index fbc732a8a..fbc732a8a 100644
--- a/src/libs/7zip/win/C/Xz.c
+++ b/src/libs/3rdparty/7zip/win/C/Xz.c
diff --git a/src/libs/7zip/win/C/Xz.h b/src/libs/3rdparty/7zip/win/C/Xz.h
index 9268d5bc6..9268d5bc6 100644
--- a/src/libs/7zip/win/C/Xz.h
+++ b/src/libs/3rdparty/7zip/win/C/Xz.h
diff --git a/src/libs/7zip/win/C/XzCrc64.c b/src/libs/3rdparty/7zip/win/C/XzCrc64.c
index 2c04c0af4..2c04c0af4 100644
--- a/src/libs/7zip/win/C/XzCrc64.c
+++ b/src/libs/3rdparty/7zip/win/C/XzCrc64.c
diff --git a/src/libs/7zip/win/C/XzCrc64.h b/src/libs/3rdparty/7zip/win/C/XzCrc64.h
index 08dbc330c..08dbc330c 100644
--- a/src/libs/7zip/win/C/XzCrc64.h
+++ b/src/libs/3rdparty/7zip/win/C/XzCrc64.h
diff --git a/src/libs/7zip/win/C/XzCrc64Opt.c b/src/libs/3rdparty/7zip/win/C/XzCrc64Opt.c
index dccae1c19..dccae1c19 100644
--- a/src/libs/7zip/win/C/XzCrc64Opt.c
+++ b/src/libs/3rdparty/7zip/win/C/XzCrc64Opt.c
diff --git a/src/libs/7zip/win/C/XzDec.c b/src/libs/3rdparty/7zip/win/C/XzDec.c
index 6eef587d3..6eef587d3 100644
--- a/src/libs/7zip/win/C/XzDec.c
+++ b/src/libs/3rdparty/7zip/win/C/XzDec.c
diff --git a/src/libs/7zip/win/C/XzEnc.c b/src/libs/3rdparty/7zip/win/C/XzEnc.c
index 56680fcd8..56680fcd8 100644
--- a/src/libs/7zip/win/C/XzEnc.c
+++ b/src/libs/3rdparty/7zip/win/C/XzEnc.c
diff --git a/src/libs/7zip/win/C/XzEnc.h b/src/libs/3rdparty/7zip/win/C/XzEnc.h
index c3c19eca0..c3c19eca0 100644
--- a/src/libs/7zip/win/C/XzEnc.h
+++ b/src/libs/3rdparty/7zip/win/C/XzEnc.h
diff --git a/src/libs/7zip/win/C/XzIn.c b/src/libs/3rdparty/7zip/win/C/XzIn.c
index ed9eac31a..ed9eac31a 100644
--- a/src/libs/7zip/win/C/XzIn.c
+++ b/src/libs/3rdparty/7zip/win/C/XzIn.c
diff --git a/src/libs/7zip/win/CPP/7zip/7zip.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/7zip.pri
index a2b70a1f2..a2b70a1f2 100644
--- a/src/libs/7zip/win/CPP/7zip/7zip.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/7zip.pri
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7z.pri
index 7763cf705..7763cf705 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7z.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7z.pri
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h
index 5cde97c38..5cde97c38 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zCompressionMode.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp
index 973966bd3..973966bd3 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zDecode.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zDecode.h
index 54e9d2b52..54e9d2b52 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zDecode.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zDecode.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp
index 5f1436fc7..5f1436fc7 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zEncode.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zEncode.h
index 8e20bdb5f..8e20bdb5f 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zEncode.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zEncode.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp
index bb350455c..bb350455c 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zExtract.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 3f420a513..3f420a513 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h
index 4ed4b2dd2..4ed4b2dd2 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderInStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
index 847f65bf2..847f65bf2 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h
index cc2d77343..cc2d77343 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zFolderOutStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp
index ed65dc20c..ed65dc20c 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandler.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandler.h
index 677a3e10a..677a3e10a 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandler.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandler.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 7de5b8140..7de5b8140 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHandlerOut.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp
index acff2fdd8..acff2fdd8 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHeader.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHeader.h
index 61dad655d..61dad655d 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zHeader.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zHeader.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp
index 28ec5e083..28ec5e083 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zIn.h
index 98f61c81e..98f61c81e 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zIn.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zItem.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zItem.h
index c112f83fd..c112f83fd 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zItem.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zItem.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp
index e20858ea7..e20858ea7 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zOut.h
index 391ca9d02..391ca9d02 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zOut.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp
index a29f8abe9..a29f8abe9 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zProperties.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zProperties.h
index 661817954..661817954 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zProperties.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zProperties.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp
index 37ea29d30..37ea29d30 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zRegister.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp
index 8e45d9875..8e45d9875 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.h
index 2e26efd5c..2e26efd5c 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zSpecStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp
index 26faf2a18..26faf2a18 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zUpdate.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h
index aee2d5ed3..aee2d5ed3 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/7zUpdate.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/StdAfx.h
index 2854ff3e9..2854ff3e9 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/7z/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Archive.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Archive.pri
index e8a1c7832..e8a1c7832 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Archive.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Archive.pri
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp
index e562fec58..e562fec58 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h
index 50e7077ae..50e7077ae 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
index 36b252600..36b252600 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h
index 2190cf867..2190cf867 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/CoderMixer2MT.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/Common.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/Common.pri
index e808619d3..e808619d3 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/Common.pri
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp
index 7c4f54879..7c4f54879 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h
index b5a51fc07..b5a51fc07 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/DummyOutStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp
index 7b875fbd0..7b875fbd0 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/HandlerOut.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h
index eba2a19e1..eba2a19e1 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/HandlerOut.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
index a2d688328..a2d688328 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h
index 31b761e45..31b761e45 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/InStreamWithCRC.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp
index 7cd3037be..7cd3037be 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h
index d0dc76a41..d0dc76a41 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ItemNameUtils.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp
index 17f749058..17f749058 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/MultiStream.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/MultiStream.h
index 93aff33bf..93aff33bf 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/MultiStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/MultiStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
index f955c2254..f955c2254 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h
index 09b899bbd..09b899bbd 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/OutStreamWithCRC.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h
index 1038a8c02..1038a8c02 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/ParseProperties.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/StdAfx.h
index 2854ff3e9..2854ff3e9 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/Common/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/Common/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/IArchive.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/IArchive.h
index a15a97f16..a15a97f16 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/IArchive.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/IArchive.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp
index 279cdefb7..279cdefb7 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/LzmaHandler.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/SplitHandler.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/SplitHandler.cpp
index db9f49aa0..db9f49aa0 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/SplitHandler.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/SplitHandler.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/StdAfx.h
index 1cbd7feae..1cbd7feae 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/XzHandler.cpp
index 789f41a72..789f41a72 100644
--- a/src/libs/7zip/win/CPP/7zip/Archive/XzHandler.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Archive/XzHandler.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/CWrappers.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CWrappers.cpp
index a15794e2a..a15794e2a 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/CWrappers.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CWrappers.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/CWrappers.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CWrappers.h
index 4fe7dea3e..4fe7dea3e 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/CWrappers.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CWrappers.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/Common.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/Common.pri
index e6b054a24..e6b054a24 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/Common.pri
diff --git a/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CreateCoder.cpp
index 01ccbe12a..01ccbe12a 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CreateCoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CreateCoder.h
index fe1f6ccfe..fe1f6ccfe 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/CreateCoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/CreateCoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp
index 958360fac..958360fac 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilePathAutoRename.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilePathAutoRename.h
index 7b576591c..7b576591c 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/FilePathAutoRename.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilePathAutoRename.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FileStreams.cpp
index 77e5463e6..77e5463e6 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FileStreams.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FileStreams.h
index cce71e582..cce71e582 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/FileStreams.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FileStreams.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilterCoder.cpp
index 3a2023b35..3a2023b35 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilterCoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilterCoder.h
index 2b8f142f5..2b8f142f5 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/FilterCoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/FilterCoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/InBuffer.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InBuffer.cpp
index 133d95b38..133d95b38 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/InBuffer.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InBuffer.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/InBuffer.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InBuffer.h
index dd3c66808..dd3c66808 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/InBuffer.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InBuffer.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp
index be65ba32f..be65ba32f 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InOutTempBuffer.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InOutTempBuffer.h
index 256d72420..256d72420 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/InOutTempBuffer.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/InOutTempBuffer.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LimitedStreams.cpp
index 5f20dcda4..5f20dcda4 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LimitedStreams.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LimitedStreams.h
index b14616f3b..b14616f3b 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/LimitedStreams.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LimitedStreams.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/LockedStream.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LockedStream.cpp
index f05601cb6..f05601cb6 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/LockedStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LockedStream.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/LockedStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LockedStream.h
index 486e4220b..486e4220b 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/LockedStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/LockedStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/MethodId.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodId.h
index 28b615fcd..28b615fcd 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/MethodId.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodId.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/MethodProps.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodProps.cpp
index ff61995b7..ff61995b7 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/MethodProps.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodProps.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/MethodProps.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodProps.h
index 39e2ee937..39e2ee937 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/MethodProps.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/MethodProps.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/OutBuffer.cpp
index 4ba34a053..4ba34a053 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/OutBuffer.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/OutBuffer.h
index 0baad3636..0baad3636 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/OutBuffer.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/OutBuffer.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/ProgressUtils.cpp
index bac45c1c2..bac45c1c2 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/ProgressUtils.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/ProgressUtils.h
index bae5395c1..bae5395c1 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/ProgressUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/ProgressUtils.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/PropId.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/PropId.cpp
index 10daef715..10daef715 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/PropId.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/PropId.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/RegisterArc.h
index 82bd09673..82bd09673 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/RegisterArc.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/RegisterCodec.h
index 0c6662a6c..0c6662a6c 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/RegisterCodec.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StdAfx.h
index 1cbd7feae..1cbd7feae 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamBinder.cpp
index 7a4c0ed26..7a4c0ed26 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamBinder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamBinder.h
index f3fb53228..f3fb53228 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StreamBinder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamBinder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamObjects.cpp
index 7721c3a7e..7721c3a7e 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamObjects.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamObjects.h
index d0c86b566..d0c86b566 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StreamObjects.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamObjects.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamUtils.cpp
index 1402f4205..1402f4205 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamUtils.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamUtils.h
index ae914c004..ae914c004 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/StreamUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/StreamUtils.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/UniqBlocks.cpp
index 7fcc88f5e..7fcc88f5e 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/UniqBlocks.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/UniqBlocks.h
index 9c08b09f4..9c08b09f4 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/UniqBlocks.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/UniqBlocks.h
diff --git a/src/libs/7zip/win/CPP/7zip/Common/VirtThread.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/VirtThread.cpp
index 77e3c1acf..77e3c1acf 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/VirtThread.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/VirtThread.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Common/VirtThread.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/VirtThread.h
index ebee158ca..ebee158ca 100644
--- a/src/libs/7zip/win/CPP/7zip/Common/VirtThread.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Common/VirtThread.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp
index 9da6b9c28..9da6b9c28 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Coder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Coder.h
index e7bd37951..e7bd37951 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Coder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Coder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Register.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Register.cpp
index 8eb1e7360..8eb1e7360 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Bcj2Register.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Bcj2Register.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BcjCoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjCoder.cpp
index 0e34ef488..0e34ef488 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BcjCoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjCoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BcjCoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjCoder.h
index 0754bcd23..0754bcd23 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BcjCoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjCoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BcjRegister.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjRegister.cpp
index 648ad8e03..648ad8e03 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BcjRegister.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BcjRegister.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BranchCoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchCoder.cpp
index 431709526..431709526 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BranchCoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchCoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BranchCoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchCoder.h
index 0e3a5c4e1..0e3a5c4e1 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BranchCoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchCoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchMisc.cpp
index 239f25138..239f25138 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchMisc.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchMisc.h
index 81198b21c..81198b21c 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BranchMisc.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchMisc.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/BranchRegister.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchRegister.cpp
index 380828c6d..380828c6d 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/BranchRegister.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/BranchRegister.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/ByteSwap.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/ByteSwap.cpp
index 645b6ffcd..645b6ffcd 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/ByteSwap.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/ByteSwap.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Compress.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Compress.pri
index db923a868..db923a868 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Compress.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Compress.pri
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyCoder.cpp
index f0863202a..f0863202a 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyCoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyCoder.h
index 5e0bb6436..5e0bb6436 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/CopyCoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyCoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/CopyRegister.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyRegister.cpp
index efb9b9e95..efb9b9e95 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/CopyRegister.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/CopyRegister.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp
index d8378a60e..d8378a60e 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/DeltaFilter.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp
index b20ae5f5e..b20ae5f5e 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Decoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Decoder.h
index fd7ca2f39..fd7ca2f39 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Decoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Decoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp
index f867881c0..f867881c0 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Encoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h
index 6a2318076..6a2318076 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Encoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Register.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Register.cpp
index cace871ef..cace871ef 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/Lzma2Register.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/Lzma2Register.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp
index d378ba668..d378ba668 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaDecoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaDecoder.h
index 140c48b9c..140c48b9c 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaDecoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaDecoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp
index 484d04523..484d04523 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaEncoder.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaEncoder.h
index 7e15a132d..7e15a132d 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaEncoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaEncoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/LzmaRegister.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaRegister.cpp
index 96ed0baed..96ed0baed 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/LzmaRegister.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/LzmaRegister.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/RangeCoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/RangeCoder.h
index 1555bd705..1555bd705 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/RangeCoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/RangeCoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/RangeCoderBit.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/RangeCoderBit.h
index 0eddd5586..0eddd5586 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/RangeCoderBit.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/RangeCoderBit.h
diff --git a/src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/StdAfx.h
index 1cbd7feae..1cbd7feae 100644
--- a/src/libs/7zip/win/CPP/7zip/Compress/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Compress/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/7zip/Guid.txt b/src/libs/3rdparty/7zip/win/CPP/7zip/Guid.txt
index c1e7446be..c1e7446be 100644
--- a/src/libs/7zip/win/CPP/7zip/Guid.txt
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/Guid.txt
diff --git a/src/libs/7zip/win/CPP/7zip/ICoder.h b/src/libs/3rdparty/7zip/win/CPP/7zip/ICoder.h
index 74ee0e453..74ee0e453 100644
--- a/src/libs/7zip/win/CPP/7zip/ICoder.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/ICoder.h
diff --git a/src/libs/7zip/win/CPP/7zip/IDecl.h b/src/libs/3rdparty/7zip/win/CPP/7zip/IDecl.h
index 8316eb3ac..8316eb3ac 100644
--- a/src/libs/7zip/win/CPP/7zip/IDecl.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/IDecl.h
diff --git a/src/libs/7zip/win/CPP/7zip/IPassword.h b/src/libs/3rdparty/7zip/win/CPP/7zip/IPassword.h
index 7ea45537e..7ea45537e 100644
--- a/src/libs/7zip/win/CPP/7zip/IPassword.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/IPassword.h
diff --git a/src/libs/7zip/win/CPP/7zip/IProgress.h b/src/libs/3rdparty/7zip/win/CPP/7zip/IProgress.h
index a270e693b..a270e693b 100644
--- a/src/libs/7zip/win/CPP/7zip/IProgress.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/IProgress.h
diff --git a/src/libs/7zip/win/CPP/7zip/IStream.h b/src/libs/3rdparty/7zip/win/CPP/7zip/IStream.h
index 48643e7b3..48643e7b3 100644
--- a/src/libs/7zip/win/CPP/7zip/IStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/IStream.h
diff --git a/src/libs/7zip/win/CPP/7zip/PropID.h b/src/libs/3rdparty/7zip/win/CPP/7zip/PropID.h
index 82a7462bb..82a7462bb 100644
--- a/src/libs/7zip/win/CPP/7zip/PropID.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/PropID.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 769d21604..769d21604 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h
index 87e6619e6..87e6619e6 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 250f66797..250f66797 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index fe7ef42bb..fe7ef42bb 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index 4157aa4f1..4157aa4f1 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index 3352eadef..3352eadef 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ArchiveOpenCallback.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Common.pri
index 9d829d2af..9d829d2af 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Common.pri
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp
index ce0b327b5..ce0b327b5 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DefaultName.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DefaultName.h
index df1645602..df1645602 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/DefaultName.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DefaultName.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/DirItem.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DirItem.h
index 82203c03a..82203c03a 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/DirItem.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/DirItem.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp
index 1e9562a0e..1e9562a0e 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h
index 803a64e7d..803a64e7d 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/EnumDirItems.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Extract.cpp
index 13d2ad29a..13d2ad29a 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Extract.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Extract.h
index 052b2f7d3..052b2f7d3 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Extract.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractMode.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractMode.h
index a54376705..a54376705 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractMode.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractMode.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index 852fd5adb..852fd5adb 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h
index 751248a97..751248a97 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/ExtractingFilePath.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp
index 2d13a2af1..2d13a2af1 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/HashCalc.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/HashCalc.h
index 68e2404cc..68e2404cc 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/HashCalc.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/HashCalc.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h
index 7bb852795..7bb852795 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/IFileExtractCallback.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp
index a1d801b04..a1d801b04 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/LoadCodecs.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h
index d254ae659..d254ae659 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/LoadCodecs.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp
index 4efbc9cc7..4efbc9cc7 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/OpenArchive.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/OpenArchive.h
index 2ee743adc..2ee743adc 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/OpenArchive.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/OpenArchive.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp
index 8f27cc0d1..8f27cc0d1 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/PropIDUtils.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h
index 3ee2981de..3ee2981de 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/PropIDUtils.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Property.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Property.h
index 8b57a2a64..8b57a2a64 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/Property.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Property.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp
index 64b9d92a6..64b9d92a6 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SetProperties.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SetProperties.h
index 892f1a210..892f1a210 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/SetProperties.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SetProperties.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp
index b7e422a29..b7e422a29 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SortUtils.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SortUtils.h
index 8e42e0682..8e42e0682 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/SortUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/SortUtils.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/StdAfx.h
index 2854ff3e9..2854ff3e9 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp
index 0c13ae158..0c13ae158 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/TempFiles.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/TempFiles.h
index 4099e6558..4099e6558 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/TempFiles.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/TempFiles.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Update.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Update.cpp
index e3d538f10..e3d538f10 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/Update.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Update.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Update.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Update.h
index ff53cd992..ff53cd992 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/Update.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/Update.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp
index a80db7212..a80db7212 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateAction.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateAction.h
index 8c7609fb4..8c7609fb4 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateAction.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateAction.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp
index e490cde24..e490cde24 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateCallback.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h
index 81982e61d..81982e61d 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateCallback.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp
index 95afdd694..95afdd694 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdatePair.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdatePair.h
index 296d3b097..296d3b097 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdatePair.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdatePair.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp
index 2c4c28583..2c4c28583 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateProduce.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h
index ef7b0f7a3..ef7b0f7a3 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Common/UpdateProduce.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/Console.pri
index 14668f8b3..14668f8b3 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Console/Console.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/Console.pri
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp
index f2889957a..f2889957a 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/PercentPrinter.cpp
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h
index 509bab5fc..509bab5fc 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/PercentPrinter.h
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/StdAfx.h
index 2854ff3e9..2854ff3e9 100644
--- a/src/libs/7zip/win/CPP/7zip/UI/Console/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/7zip/UI/Console/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/Common/ComTry.h b/src/libs/3rdparty/7zip/win/CPP/Common/ComTry.h
index c8aa4aedc..c8aa4aedc 100644
--- a/src/libs/7zip/win/CPP/Common/ComTry.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/ComTry.h
diff --git a/src/libs/7zip/win/CPP/Common/CommandLineParser.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/CommandLineParser.cpp
index ac9ae1960..ac9ae1960 100644
--- a/src/libs/7zip/win/CPP/Common/CommandLineParser.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/CommandLineParser.cpp
diff --git a/src/libs/7zip/win/CPP/Common/CommandLineParser.h b/src/libs/3rdparty/7zip/win/CPP/Common/CommandLineParser.h
index e3e6e6b14..e3e6e6b14 100644
--- a/src/libs/7zip/win/CPP/Common/CommandLineParser.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/CommandLineParser.h
diff --git a/src/libs/7zip/win/CPP/Common/Common.h b/src/libs/3rdparty/7zip/win/CPP/Common/Common.h
index 9dd30f4be..9dd30f4be 100644
--- a/src/libs/7zip/win/CPP/Common/Common.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/Common.h
diff --git a/src/libs/7zip/win/CPP/Common/Common.pri b/src/libs/3rdparty/7zip/win/CPP/Common/Common.pri
index ecc997d89..ecc997d89 100644
--- a/src/libs/7zip/win/CPP/Common/Common.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/Common.pri
diff --git a/src/libs/7zip/win/CPP/Common/Defs.h b/src/libs/3rdparty/7zip/win/CPP/Common/Defs.h
index dad3ae8f1..dad3ae8f1 100644
--- a/src/libs/7zip/win/CPP/Common/Defs.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/Defs.h
diff --git a/src/libs/7zip/win/CPP/Common/IntToString.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/IntToString.cpp
index ed217c72c..ed217c72c 100644
--- a/src/libs/7zip/win/CPP/Common/IntToString.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/IntToString.cpp
diff --git a/src/libs/7zip/win/CPP/Common/IntToString.h b/src/libs/3rdparty/7zip/win/CPP/Common/IntToString.h
index 69605ab76..69605ab76 100644
--- a/src/libs/7zip/win/CPP/Common/IntToString.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/IntToString.h
diff --git a/src/libs/7zip/win/CPP/Common/ListFileUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/ListFileUtils.cpp
index 4d7faeca3..4d7faeca3 100644
--- a/src/libs/7zip/win/CPP/Common/ListFileUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/ListFileUtils.cpp
diff --git a/src/libs/7zip/win/CPP/Common/ListFileUtils.h b/src/libs/3rdparty/7zip/win/CPP/Common/ListFileUtils.h
index e8d833fdb..e8d833fdb 100644
--- a/src/libs/7zip/win/CPP/Common/ListFileUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/ListFileUtils.h
diff --git a/src/libs/7zip/win/CPP/Common/MyBuffer.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyBuffer.h
index 7bd79f6f4..7bd79f6f4 100644
--- a/src/libs/7zip/win/CPP/Common/MyBuffer.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyBuffer.h
diff --git a/src/libs/7zip/win/CPP/Common/MyCom.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyCom.h
index 466407cde..466407cde 100644
--- a/src/libs/7zip/win/CPP/Common/MyCom.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyCom.h
diff --git a/src/libs/7zip/win/CPP/Common/MyException.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyException.h
index f0ad11158..f0ad11158 100644
--- a/src/libs/7zip/win/CPP/Common/MyException.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyException.h
diff --git a/src/libs/7zip/win/CPP/Common/MyGuidDef.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyGuidDef.h
index 68745870e..68745870e 100644
--- a/src/libs/7zip/win/CPP/Common/MyGuidDef.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyGuidDef.h
diff --git a/src/libs/7zip/win/CPP/Common/MyInitGuid.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyInitGuid.h
index 279fba5d6..279fba5d6 100644
--- a/src/libs/7zip/win/CPP/Common/MyInitGuid.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyInitGuid.h
diff --git a/src/libs/7zip/win/CPP/Common/MyString.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/MyString.cpp
index 6fbfa334b..6fbfa334b 100644
--- a/src/libs/7zip/win/CPP/Common/MyString.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyString.cpp
diff --git a/src/libs/7zip/win/CPP/Common/MyString.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyString.h
index 8417815cf..8417815cf 100644
--- a/src/libs/7zip/win/CPP/Common/MyString.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyString.h
diff --git a/src/libs/7zip/win/CPP/Common/MyTypes.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyTypes.h
index d81788816..d81788816 100644
--- a/src/libs/7zip/win/CPP/Common/MyTypes.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyTypes.h
diff --git a/src/libs/7zip/win/CPP/Common/MyUnknown.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyUnknown.h
index 8b95afd38..8b95afd38 100644
--- a/src/libs/7zip/win/CPP/Common/MyUnknown.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyUnknown.h
diff --git a/src/libs/7zip/win/CPP/Common/MyVector.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyVector.h
index 7e61dec31..7e61dec31 100644
--- a/src/libs/7zip/win/CPP/Common/MyVector.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyVector.h
diff --git a/src/libs/7zip/win/CPP/Common/MyWindows.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/MyWindows.cpp
index 38c93fdb2..38c93fdb2 100644
--- a/src/libs/7zip/win/CPP/Common/MyWindows.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyWindows.cpp
diff --git a/src/libs/7zip/win/CPP/Common/MyWindows.h b/src/libs/3rdparty/7zip/win/CPP/Common/MyWindows.h
index 139a4e8b9..139a4e8b9 100644
--- a/src/libs/7zip/win/CPP/Common/MyWindows.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/MyWindows.h
diff --git a/src/libs/7zip/win/CPP/Common/NewHandler.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/NewHandler.cpp
index 9072376df..9072376df 100644
--- a/src/libs/7zip/win/CPP/Common/NewHandler.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/NewHandler.cpp
diff --git a/src/libs/7zip/win/CPP/Common/NewHandler.h b/src/libs/3rdparty/7zip/win/CPP/Common/NewHandler.h
index e3e7422c8..e3e7422c8 100644
--- a/src/libs/7zip/win/CPP/Common/NewHandler.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/NewHandler.h
diff --git a/src/libs/7zip/win/CPP/Common/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/Common/StdAfx.h
index 420f5c326..420f5c326 100644
--- a/src/libs/7zip/win/CPP/Common/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/Common/StdOutStream.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/StdOutStream.cpp
index 6aed31a31..6aed31a31 100644
--- a/src/libs/7zip/win/CPP/Common/StdOutStream.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StdOutStream.cpp
diff --git a/src/libs/7zip/win/CPP/Common/StdOutStream.h b/src/libs/3rdparty/7zip/win/CPP/Common/StdOutStream.h
index 0a8c0febb..0a8c0febb 100644
--- a/src/libs/7zip/win/CPP/Common/StdOutStream.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StdOutStream.h
diff --git a/src/libs/7zip/win/CPP/Common/StringConvert.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/StringConvert.cpp
index 0443a06ca..0443a06ca 100644
--- a/src/libs/7zip/win/CPP/Common/StringConvert.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StringConvert.cpp
diff --git a/src/libs/7zip/win/CPP/Common/StringConvert.h b/src/libs/3rdparty/7zip/win/CPP/Common/StringConvert.h
index 8eea72ef2..8eea72ef2 100644
--- a/src/libs/7zip/win/CPP/Common/StringConvert.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StringConvert.h
diff --git a/src/libs/7zip/win/CPP/Common/StringToInt.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/StringToInt.cpp
index 2023fcc2c..2023fcc2c 100644
--- a/src/libs/7zip/win/CPP/Common/StringToInt.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StringToInt.cpp
diff --git a/src/libs/7zip/win/CPP/Common/StringToInt.h b/src/libs/3rdparty/7zip/win/CPP/Common/StringToInt.h
index 5c5d7d7fe..5c5d7d7fe 100644
--- a/src/libs/7zip/win/CPP/Common/StringToInt.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/StringToInt.h
diff --git a/src/libs/7zip/win/CPP/Common/UTFConvert.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/UTFConvert.cpp
index 38bac3331..38bac3331 100644
--- a/src/libs/7zip/win/CPP/Common/UTFConvert.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/UTFConvert.cpp
diff --git a/src/libs/7zip/win/CPP/Common/UTFConvert.h b/src/libs/3rdparty/7zip/win/CPP/Common/UTFConvert.h
index 16b02fe45..16b02fe45 100644
--- a/src/libs/7zip/win/CPP/Common/UTFConvert.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/UTFConvert.h
diff --git a/src/libs/7zip/win/CPP/Common/Wildcard.cpp b/src/libs/3rdparty/7zip/win/CPP/Common/Wildcard.cpp
index e88a1cf1c..e88a1cf1c 100644
--- a/src/libs/7zip/win/CPP/Common/Wildcard.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/Wildcard.cpp
diff --git a/src/libs/7zip/win/CPP/Common/Wildcard.h b/src/libs/3rdparty/7zip/win/CPP/Common/Wildcard.h
index 137d71ced..137d71ced 100644
--- a/src/libs/7zip/win/CPP/Common/Wildcard.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Common/Wildcard.h
diff --git a/src/libs/7zip/win/CPP/Windows/DLL.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/DLL.cpp
index cf3dd1ceb..cf3dd1ceb 100644
--- a/src/libs/7zip/win/CPP/Windows/DLL.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/DLL.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/DLL.h b/src/libs/3rdparty/7zip/win/CPP/Windows/DLL.h
index d8848ce95..d8848ce95 100644
--- a/src/libs/7zip/win/CPP/Windows/DLL.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/DLL.h
diff --git a/src/libs/7zip/win/CPP/Windows/Defs.h b/src/libs/3rdparty/7zip/win/CPP/Windows/Defs.h
index 281c40c33..281c40c33 100644
--- a/src/libs/7zip/win/CPP/Windows/Defs.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/Defs.h
diff --git a/src/libs/7zip/win/CPP/Windows/FileDir.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/FileDir.cpp
index 097f81efb..097f81efb 100644
--- a/src/libs/7zip/win/CPP/Windows/FileDir.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileDir.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/FileDir.h b/src/libs/3rdparty/7zip/win/CPP/Windows/FileDir.h
index 02d3e5a57..02d3e5a57 100644
--- a/src/libs/7zip/win/CPP/Windows/FileDir.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileDir.h
diff --git a/src/libs/7zip/win/CPP/Windows/FileFind.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/FileFind.cpp
index 7f58288fe..7f58288fe 100644
--- a/src/libs/7zip/win/CPP/Windows/FileFind.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileFind.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/FileFind.h b/src/libs/3rdparty/7zip/win/CPP/Windows/FileFind.h
index aaa7499bd..aaa7499bd 100644
--- a/src/libs/7zip/win/CPP/Windows/FileFind.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileFind.h
diff --git a/src/libs/7zip/win/CPP/Windows/FileIO.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/FileIO.cpp
index fec859ed3..fec859ed3 100644
--- a/src/libs/7zip/win/CPP/Windows/FileIO.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileIO.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/FileIO.h b/src/libs/3rdparty/7zip/win/CPP/Windows/FileIO.h
index f595121ef..f595121ef 100644
--- a/src/libs/7zip/win/CPP/Windows/FileIO.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileIO.h
diff --git a/src/libs/7zip/win/CPP/Windows/FileLink.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/FileLink.cpp
index dc524700d..dc524700d 100644
--- a/src/libs/7zip/win/CPP/Windows/FileLink.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileLink.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/FileMapping.h b/src/libs/3rdparty/7zip/win/CPP/Windows/FileMapping.h
index f90c429f1..f90c429f1 100644
--- a/src/libs/7zip/win/CPP/Windows/FileMapping.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileMapping.h
diff --git a/src/libs/7zip/win/CPP/Windows/FileName.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/FileName.cpp
index 0a6aee100..0a6aee100 100644
--- a/src/libs/7zip/win/CPP/Windows/FileName.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileName.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/FileName.h b/src/libs/3rdparty/7zip/win/CPP/Windows/FileName.h
index 04fc79b2d..04fc79b2d 100644
--- a/src/libs/7zip/win/CPP/Windows/FileName.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/FileName.h
diff --git a/src/libs/7zip/win/CPP/Windows/Handle.h b/src/libs/3rdparty/7zip/win/CPP/Windows/Handle.h
index bb7cb705d..bb7cb705d 100644
--- a/src/libs/7zip/win/CPP/Windows/Handle.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/Handle.h
diff --git a/src/libs/7zip/win/CPP/Windows/PropVariant.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariant.cpp
index d16f576cc..d16f576cc 100644
--- a/src/libs/7zip/win/CPP/Windows/PropVariant.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariant.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/PropVariant.h b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariant.h
index d71b85e1d..d71b85e1d 100644
--- a/src/libs/7zip/win/CPP/Windows/PropVariant.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariant.h
diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariantConv.cpp
index dfb93d6d6..dfb93d6d6 100644
--- a/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariantConv.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConv.h b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariantConv.h
index 5d26357f0..5d26357f0 100644
--- a/src/libs/7zip/win/CPP/Windows/PropVariantConv.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/PropVariantConv.h
diff --git a/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/SecurityUtils.cpp
index f997738ce..f997738ce 100644
--- a/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/SecurityUtils.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/SecurityUtils.h b/src/libs/3rdparty/7zip/win/CPP/Windows/SecurityUtils.h
index 715de2505..715de2505 100644
--- a/src/libs/7zip/win/CPP/Windows/SecurityUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/SecurityUtils.h
diff --git a/src/libs/7zip/win/CPP/Windows/StdAfx.h b/src/libs/3rdparty/7zip/win/CPP/Windows/StdAfx.h
index 1766dfa86..1766dfa86 100644
--- a/src/libs/7zip/win/CPP/Windows/StdAfx.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/StdAfx.h
diff --git a/src/libs/7zip/win/CPP/Windows/Synchronization.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/Synchronization.cpp
index 5f86d1eb1..5f86d1eb1 100644
--- a/src/libs/7zip/win/CPP/Windows/Synchronization.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/Synchronization.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/Synchronization.h b/src/libs/3rdparty/7zip/win/CPP/Windows/Synchronization.h
index dc695f6f3..dc695f6f3 100644
--- a/src/libs/7zip/win/CPP/Windows/Synchronization.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/Synchronization.h
diff --git a/src/libs/7zip/win/CPP/Windows/System.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/System.cpp
index 4bc8d2a3f..4bc8d2a3f 100644
--- a/src/libs/7zip/win/CPP/Windows/System.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/System.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/System.h b/src/libs/3rdparty/7zip/win/CPP/Windows/System.h
index 4133a7b30..4133a7b30 100644
--- a/src/libs/7zip/win/CPP/Windows/System.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/System.h
diff --git a/src/libs/7zip/win/CPP/Windows/Thread.h b/src/libs/3rdparty/7zip/win/CPP/Windows/Thread.h
index f9ecaed85..f9ecaed85 100644
--- a/src/libs/7zip/win/CPP/Windows/Thread.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/Thread.h
diff --git a/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp b/src/libs/3rdparty/7zip/win/CPP/Windows/TimeUtils.cpp
index 7ef44d9cc..7ef44d9cc 100644
--- a/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/TimeUtils.cpp
diff --git a/src/libs/7zip/win/CPP/Windows/TimeUtils.h b/src/libs/3rdparty/7zip/win/CPP/Windows/TimeUtils.h
index 2967214e6..2967214e6 100644
--- a/src/libs/7zip/win/CPP/Windows/TimeUtils.h
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/TimeUtils.h
diff --git a/src/libs/7zip/win/CPP/Windows/Windows.pri b/src/libs/3rdparty/7zip/win/CPP/Windows/Windows.pri
index a69279060..a69279060 100644
--- a/src/libs/7zip/win/CPP/Windows/Windows.pri
+++ b/src/libs/3rdparty/7zip/win/CPP/Windows/Windows.pri
diff --git a/src/libs/7zip/win/win.pri b/src/libs/3rdparty/7zip/win/win.pri
index d29553cbd..d29553cbd 100644
--- a/src/libs/7zip/win/win.pri
+++ b/src/libs/3rdparty/7zip/win/win.pri
diff --git a/src/libs/3rdparty/libarchive/archive.h b/src/libs/3rdparty/libarchive/archive.h
index 52f4d7829..618b1a176 100644
--- a/src/libs/3rdparty/libarchive/archive.h
+++ b/src/libs/3rdparty/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3005001
+#define ARCHIVE_VERSION_NUMBER 3007001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -97,7 +97,7 @@ typedef ssize_t la_ssize_t;
#endif
/* Large file support for Android */
-#ifdef __ANDROID__
+#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
#include "android_lf.h"
#endif
@@ -120,6 +120,8 @@ typedef ssize_t la_ssize_t;
# define __LA_DECL __declspec(dllimport)
# endif
# endif
+#elif defined __LIBARCHIVE_ENABLE_VISIBILITY
+# define __LA_DECL __attribute__((visibility("default")))
#else
/* Static libraries or non-Windows needs no special declaration. */
# define __LA_DECL
@@ -155,7 +157,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.5.1"
+#define ARCHIVE_VERSION_ONLY_STRING "3.7.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -319,6 +321,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
+#define ARCHIVE_FORMAT_CPIO_PWB (ARCHIVE_FORMAT_CPIO | 7)
#define ARCHIVE_FORMAT_SHAR 0x20000
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
@@ -800,7 +803,10 @@ __LA_DECL int archive_write_set_format_7zip(struct archive *);
__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
__LA_DECL int archive_write_set_format_cpio(struct archive *);
+__LA_DECL int archive_write_set_format_cpio_bin(struct archive *);
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
+__LA_DECL int archive_write_set_format_cpio_odc(struct archive *);
+__LA_DECL int archive_write_set_format_cpio_pwb(struct archive *);
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
__LA_DECL int archive_write_set_format_mtree(struct archive *);
@@ -1020,6 +1026,8 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
#define ARCHIVE_READDISK_NO_ACL (0x0020)
/* Default: File flags are read from disk. */
#define ARCHIVE_READDISK_NO_FFLAGS (0x0040)
+/* Default: Sparse file information is read from disk. */
+#define ARCHIVE_READDISK_NO_SPARSE (0x0080)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
diff --git a/src/libs/3rdparty/libarchive/archive_blake2.h b/src/libs/3rdparty/libarchive/archive_blake2.h
index dd6fe6fe5..8f6b5e922 100644
--- a/src/libs/3rdparty/libarchive/archive_blake2.h
+++ b/src/libs/3rdparty/libarchive/archive_blake2.h
@@ -21,8 +21,10 @@
#if defined(_MSC_VER)
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
-#else
+#elif defined(__GNUC__)
#define BLAKE2_PACKED(x) x __attribute__((packed))
+#else
+#define BLAKE2_PACKED(x) _Pragma("pack 1") x _Pragma("pack 0")
#endif
#if defined(__cplusplus)
diff --git a/src/libs/3rdparty/libarchive/archive_blake2_impl.h b/src/libs/3rdparty/libarchive/archive_blake2_impl.h
index 0f05defea..eb8619ca7 100644
--- a/src/libs/3rdparty/libarchive/archive_blake2_impl.h
+++ b/src/libs/3rdparty/libarchive/archive_blake2_impl.h
@@ -154,7 +154,7 @@ static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
/* prevents compiler optimizing out memset() */
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
{
- static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
+ static void *(__LA_LIBC_CC *const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
diff --git a/src/libs/3rdparty/libarchive/archive_blake2s_ref.c b/src/libs/3rdparty/libarchive/archive_blake2s_ref.c
index d92ffd0fc..93d328118 100644
--- a/src/libs/3rdparty/libarchive/archive_blake2s_ref.c
+++ b/src/libs/3rdparty/libarchive/archive_blake2s_ref.c
@@ -13,6 +13,8 @@
https://blake2.net.
*/
+#include "archive_platform.h"
+
#include <stdint.h>
#include <string.h>
#include <stdio.h>
diff --git a/src/libs/3rdparty/libarchive/archive_blake2sp_ref.c b/src/libs/3rdparty/libarchive/archive_blake2sp_ref.c
index aef101084..b913a4db6 100644
--- a/src/libs/3rdparty/libarchive/archive_blake2sp_ref.c
+++ b/src/libs/3rdparty/libarchive/archive_blake2sp_ref.c
@@ -13,6 +13,8 @@
https://blake2.net.
*/
+#include "archive_platform.h"
+
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
diff --git a/src/libs/3rdparty/libarchive/archive_cryptor.c b/src/libs/3rdparty/libarchive/archive_cryptor.c
index d4bca906b..112baf161 100644
--- a/src/libs/3rdparty/libarchive/archive_cryptor.c
+++ b/src/libs/3rdparty/libarchive/archive_cryptor.c
@@ -401,14 +401,6 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
memcpy(ctx->key, key, key_len);
memset(ctx->nonce, 0, sizeof(ctx->nonce));
ctx->encr_pos = AES_BLOCK_SIZE;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
- if (!EVP_CIPHER_CTX_reset(ctx->ctx)) {
- EVP_CIPHER_CTX_free(ctx->ctx);
- ctx->ctx = NULL;
- }
-#else
- EVP_CIPHER_CTX_init(ctx->ctx);
-#endif
return 0;
}
diff --git a/src/libs/3rdparty/libarchive/archive_digest.c b/src/libs/3rdparty/libarchive/archive_digest.c
index 410df0156..08a9aeb02 100644
--- a/src/libs/3rdparty/libarchive/archive_digest.c
+++ b/src/libs/3rdparty/libarchive/archive_digest.c
@@ -36,6 +36,11 @@
#error Cannot use both OpenSSL and libmd.
#endif
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
/*
* Message digest functions for Windows platform.
*/
@@ -48,17 +53,37 @@
/*
* Initialize a Message digest.
*/
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+static int
+win_crypto_init(Digest_CTX *ctx, const WCHAR *algo)
+{
+ NTSTATUS status;
+ ctx->valid = 0;
+
+ status = BCryptOpenAlgorithmProvider(&ctx->hAlg, algo, NULL, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return (ARCHIVE_FAILED);
+ status = BCryptCreateHash(ctx->hAlg, &ctx->hHash, NULL, 0, NULL, 0, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+ return (ARCHIVE_FAILED);
+ }
+
+ ctx->valid = 1;
+ return (ARCHIVE_OK);
+}
+#else
static int
-win_crypto_init(Digest_CTX *ctx, ALG_ID algId)
+win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
{
ctx->valid = 0;
if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ prov, CRYPT_VERIFYCONTEXT)) {
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
return (ARCHIVE_FAILED);
if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
- PROV_RSA_FULL, CRYPT_NEWKEYSET))
+ prov, CRYPT_NEWKEYSET))
return (ARCHIVE_FAILED);
}
@@ -70,6 +95,7 @@ win_crypto_init(Digest_CTX *ctx, ALG_ID algId)
ctx->valid = 1;
return (ARCHIVE_OK);
}
+#endif
/*
* Update a Message digest.
@@ -81,23 +107,37 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
if (!ctx->valid)
return (ARCHIVE_FAILED);
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCryptHashData(ctx->hHash,
+ (PUCHAR)(uintptr_t)buf,
+ len, 0);
+#else
CryptHashData(ctx->hash,
(unsigned char *)(uintptr_t)buf,
(DWORD)len, 0);
+#endif
return (ARCHIVE_OK);
}
static int
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
{
+#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
DWORD siglen = (DWORD)bufsize;
+#endif
if (!ctx->valid)
return (ARCHIVE_FAILED);
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0);
+ BCryptDestroyHash(ctx->hHash);
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+#else
CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0);
CryptDestroyHash(ctx->hash);
CryptReleaseContext(ctx->cryptProv, 0);
+#endif
ctx->valid = 0;
return (ARCHIVE_OK);
}
@@ -243,7 +283,8 @@ __archive_md5init(archive_md5_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_md5());
+ if (!EVP_DigestInit(*ctx, EVP_md5()))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}
@@ -275,7 +316,11 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
static int
__archive_md5init(archive_md5_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_MD5));
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
+#else
+ return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
+#endif
}
static int
@@ -434,7 +479,8 @@ __archive_ripemd160init(archive_rmd160_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_ripemd160());
+ if (!EVP_DigestInit(*ctx, EVP_ripemd160()))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}
@@ -624,7 +670,8 @@ __archive_sha1init(archive_sha1_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_sha1());
+ if (!EVP_DigestInit(*ctx, EVP_sha1()))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}
@@ -656,7 +703,11 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA1));
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
+#else
+ return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
+#endif
}
static int
@@ -887,7 +938,8 @@ __archive_sha256init(archive_sha256_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_sha256());
+ if (!EVP_DigestInit(*ctx, EVP_sha256()))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}
@@ -915,7 +967,11 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA_256));
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
+#else
+ return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
+#endif
}
static int
@@ -1122,7 +1178,8 @@ __archive_sha384init(archive_sha384_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_sha384());
+ if (!EVP_DigestInit(*ctx, EVP_sha384()))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}
@@ -1150,7 +1207,11 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA_384));
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
+#else
+ return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
+#endif
}
static int
@@ -1381,7 +1442,8 @@ __archive_sha512init(archive_sha512_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_sha512());
+ if (!EVP_DigestInit(*ctx, EVP_sha512()))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}
@@ -1409,7 +1471,11 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
- return (win_crypto_init(ctx, CALG_SHA_512));
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
+#else
+ return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
+#endif
}
static int
diff --git a/src/libs/3rdparty/libarchive/archive_digest_private.h b/src/libs/3rdparty/libarchive/archive_digest_private.h
index 9b3bd6621..339b4edca 100644
--- a/src/libs/3rdparty/libarchive/archive_digest_private.h
+++ b/src/libs/3rdparty/libarchive/archive_digest_private.h
@@ -164,6 +164,15 @@
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+typedef struct {
+ int valid;
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_HASH_HANDLE hHash;
+} Digest_CTX;
+#else
#include <windows.h>
#include <wincrypt.h>
typedef struct {
@@ -172,6 +181,7 @@ typedef struct {
HCRYPTHASH hash;
} Digest_CTX;
#endif
+#endif
/* typedefs */
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
diff --git a/src/libs/3rdparty/libarchive/archive_disk_acl_freebsd.c b/src/libs/3rdparty/libarchive/archive_disk_acl_freebsd.c
index aba41e5da..ed4e7a789 100644
--- a/src/libs/3rdparty/libarchive/archive_disk_acl_freebsd.c
+++ b/src/libs/3rdparty/libarchive/archive_disk_acl_freebsd.c
@@ -319,7 +319,7 @@ translate_acl(struct archive_read_disk *a,
static int
set_acl(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
int ae_requested_type, const char *tname)
{
int acl_type = 0;
@@ -364,6 +364,13 @@ set_acl(struct archive *a, int fd, const char *name,
return (ARCHIVE_FAILED);
}
+ if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
+ errno = EINVAL;
+ archive_set_error(a, errno,
+ "Cannot set default ACL on non-directory");
+ return (ARCHIVE_WARN);
+ }
+
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
@@ -542,7 +549,10 @@ set_acl(struct archive *a, int fd, const char *name,
else if (acl_set_link_np(name, acl_type, acl) != 0)
#else
/* FreeBSD older than 8.0 */
- else if (acl_set_file(name, acl_type, acl) != 0)
+ else if (S_ISLNK(mode)) {
+ /* acl_set_file() follows symbolic links, skip */
+ ret = ARCHIVE_OK;
+ } else if (acl_set_file(name, acl_type, acl) != 0)
#endif
{
if (errno == EOPNOTSUPP) {
@@ -677,14 +687,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
if (ret != ARCHIVE_OK)
return (ret);
}
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
/* Simultaneous POSIX.1e and NFSv4 is not supported */
@@ -693,7 +703,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
#if ARCHIVE_ACL_FREEBSD_NFS4
else if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#endif
diff --git a/src/libs/3rdparty/libarchive/archive_disk_acl_linux.c b/src/libs/3rdparty/libarchive/archive_disk_acl_linux.c
index 3928f3d6f..31d270535 100644
--- a/src/libs/3rdparty/libarchive/archive_disk_acl_linux.c
+++ b/src/libs/3rdparty/libarchive/archive_disk_acl_linux.c
@@ -343,6 +343,11 @@ set_richacl(struct archive *a, int fd, const char *name,
return (ARCHIVE_FAILED);
}
+ if (S_ISLNK(mode)) {
+ /* Linux does not support RichACLs on symbolic links */
+ return (ARCHIVE_OK);
+ }
+
richacl = richacl_alloc(entries);
if (richacl == NULL) {
archive_set_error(a, errno,
@@ -455,7 +460,7 @@ exit_free:
#if ARCHIVE_ACL_LIBACL
static int
set_acl(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
int ae_requested_type, const char *tname)
{
int acl_type = 0;
@@ -488,6 +493,18 @@ set_acl(struct archive *a, int fd, const char *name,
return (ARCHIVE_FAILED);
}
+ if (S_ISLNK(mode)) {
+ /* Linux does not support ACLs on symbolic links */
+ return (ARCHIVE_OK);
+ }
+
+ if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
+ errno = EINVAL;
+ archive_set_error(a, errno,
+ "Cannot set default ACL on non-directory");
+ return (ARCHIVE_WARN);
+ }
+
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
@@ -727,14 +744,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
if (ret != ARCHIVE_OK)
return (ret);
}
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
}
#endif /* ARCHIVE_ACL_LIBACL */
diff --git a/src/libs/3rdparty/libarchive/archive_disk_acl_sunos.c b/src/libs/3rdparty/libarchive/archive_disk_acl_sunos.c
index b0f5dfad9..0ef3ad52e 100644
--- a/src/libs/3rdparty/libarchive/archive_disk_acl_sunos.c
+++ b/src/libs/3rdparty/libarchive/archive_disk_acl_sunos.c
@@ -443,7 +443,7 @@ translate_acl(struct archive_read_disk *a,
static int
set_acl(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl,
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
int ae_requested_type, const char *tname)
{
aclent_t *aclent;
@@ -467,7 +467,6 @@ set_acl(struct archive *a, int fd, const char *name,
if (entries == 0)
return (ARCHIVE_OK);
-
switch (ae_requested_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
cmd = SETACL;
@@ -492,6 +491,12 @@ set_acl(struct archive *a, int fd, const char *name,
return (ARCHIVE_FAILED);
}
+ if (S_ISLNK(mode)) {
+ /* Skip ACLs on symbolic links */
+ ret = ARCHIVE_OK;
+ goto exit_free;
+ }
+
e = 0;
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
@@ -801,7 +806,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
/* Solaris writes POSIX.1e access and default ACLs together */
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
/* Simultaneous POSIX.1e and NFSv4 is not supported */
@@ -810,7 +815,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
#if ARCHIVE_ACL_SUNOS_NFS4
else if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
- ret = set_acl(a, fd, name, abstract_acl,
+ ret = set_acl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#endif
diff --git a/src/libs/3rdparty/libarchive/archive_entry.c b/src/libs/3rdparty/libarchive/archive_entry.c
index ca7a4bdb5..ae6dc3336 100644
--- a/src/libs/3rdparty/libarchive/archive_entry.c
+++ b/src/libs/3rdparty/libarchive/archive_entry.c
@@ -568,6 +568,13 @@ archive_entry_nlink(struct archive_entry *entry)
return (entry->ae_stat.aest_nlink);
}
+/* Instead, our caller could have chosen a specific encoding
+ * (archive_mstring_get_mbs, archive_mstring_get_utf8,
+ * archive_mstring_get_wcs). So we should try multiple
+ * encodings. Try mbs first because of history, even though
+ * utf8 might be better for pathname portability.
+ * Also omit wcs because of type mismatch (char * versus wchar *)
+ */
const char *
archive_entry_pathname(struct archive_entry *entry)
{
@@ -575,6 +582,13 @@ archive_entry_pathname(struct archive_entry *entry)
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
+#if HAVE_EILSEQ /*{*/
+ if (errno == EILSEQ) {
+ if (archive_mstring_get_utf8(
+ entry->archive, &entry->ae_pathname, &p) == 0)
+ return (p);
+ }
+#endif /*}*/
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
diff --git a/src/libs/3rdparty/libarchive/archive_entry.h b/src/libs/3rdparty/libarchive/archive_entry.h
index c0e75bf9f..c15460b96 100644
--- a/src/libs/3rdparty/libarchive/archive_entry.h
+++ b/src/libs/3rdparty/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3005001
+#define ARCHIVE_VERSION_NUMBER 3007001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -99,7 +99,7 @@ typedef ssize_t la_ssize_t;
#endif
/* Large file support for Android */
-#ifdef __ANDROID__
+#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
#include "android_lf.h"
#endif
@@ -122,6 +122,8 @@ typedef ssize_t la_ssize_t;
# define __LA_DECL __declspec(dllimport)
# endif
# endif
+#elif defined __LIBARCHIVE_ENABLE_VISIBILITY
+# define __LA_DECL __attribute__((visibility("default")))
#else
/* Static libraries on all platforms and shared libraries on non-Windows. */
# define __LA_DECL
diff --git a/src/libs/3rdparty/libarchive/archive_getdate.c b/src/libs/3rdparty/libarchive/archive_getdate.c
index 3ec5bba88..20ab1b158 100644
--- a/src/libs/3rdparty/libarchive/archive_getdate.c
+++ b/src/libs/3rdparty/libarchive/archive_getdate.c
@@ -698,13 +698,9 @@ Convert(time_t Month, time_t Day, time_t Year,
time_t Julian;
int i;
struct tm *ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (Year < 69)
Year += 2000;
@@ -714,7 +710,7 @@ Convert(time_t Month, time_t Day, time_t Year,
? 29 : 28;
/* Checking for 2038 bogusly assumes that time_t is 32 bits. But
I'm too lazy to try to check for time_t overflow in another way. */
- if (Year < EPOCH || Year > 2038
+ if (Year < EPOCH || Year >= 2038
|| Month < 1 || Month > 12
/* Lint fluff: "conversion from long may lose accuracy" */
|| Day < 1 || Day > DaysInMonth[(int)--Month]
@@ -731,15 +727,10 @@ Convert(time_t Month, time_t Day, time_t Year,
Julian *= DAY;
Julian += Timezone;
Julian += Hours * HOUR + Minutes * MINUTE + Seconds;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &Julian) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&Julian, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Julian;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&Julian);
#endif
@@ -755,36 +746,21 @@ DSTcorrect(time_t Start, time_t Future)
time_t StartDay;
time_t FutureDay;
struct tm *ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
-
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &Start) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&Start, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Start;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&Start);
#endif
StartDay = (ltime->tm_hour + 1) % 24;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &Future) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&Future, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Future;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&Future);
#endif
@@ -799,24 +775,15 @@ RelativeDate(time_t Start, time_t zone, int dstmode,
{
struct tm *tm;
time_t t, now;
-#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
+#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__GMTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
t = Start - zone;
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ tm = gmtime_s(&tmbuf, &t) ? NULL : &tmbuf;
+#elif defined(HAVE_GMTIME_R)
tm = gmtime_r(&t, &tmbuf);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = t;
- terr = _gmtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = gmtime(&t);
#endif
@@ -835,25 +802,16 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
struct tm *tm;
time_t Month;
time_t Year;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (RelMonth == 0)
return 0;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &Start) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&Start, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Start;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&Start);
#endif
@@ -993,10 +951,6 @@ __archive_get_date(time_t now, const char *p)
time_t Start;
time_t tod;
long tzone;
-#if defined(HAVE__LOCALTIME64_S) || defined(HAVE__GMTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
/* Clear out the parsed token array. */
memset(tokens, 0, sizeof(tokens));
@@ -1005,36 +959,26 @@ __archive_get_date(time_t now, const char *p)
gds = &_gds;
/* Look up the current time. */
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&local, &now) ? NULL : &local;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&now, &local);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = now;
- terr = _localtime64_s(&local, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &local;
#else
memset(&local, 0, sizeof(local));
tm = localtime(&now);
#endif
if (tm == NULL)
return -1;
-#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE__LOCALTIME64_S)
+#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S)
local = *tm;
#endif
/* Look up UTC if we can and use that to determine the current
* timezone offset. */
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ gmt_ptr = gmtime_s(&gmt, &now) ? NULL : &gmt;
+#elif defined(HAVE_GMTIME_R)
gmt_ptr = gmtime_r(&now, &gmt);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = now;
- terr = _gmtime64_s(&gmt, &tmptime);
- if (terr)
- gmt_ptr = NULL;
- else
- gmt_ptr = &gmt;
#else
memset(&gmt, 0, sizeof(gmt));
gmt_ptr = gmtime(&now);
@@ -1076,15 +1020,10 @@ __archive_get_date(time_t now, const char *p)
* time components instead of the local timezone. */
if (gds->HaveZone && gmt_ptr != NULL) {
now -= gds->Timezone;
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ gmt_ptr = gmtime_s(&gmt, &now) ? NULL : &gmt;
+#elif defined(HAVE_GMTIME_R)
gmt_ptr = gmtime_r(&now, &gmt);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = now;
- terr = _gmtime64_s(&gmt, &tmptime);
- if (terr)
- gmt_ptr = NULL;
- else
- gmt_ptr = &gmt;
#else
gmt_ptr = gmtime(&now);
#endif
diff --git a/src/libs/3rdparty/libarchive/archive_hmac.c b/src/libs/3rdparty/libarchive/archive_hmac.c
index 2a9d04c8d..edb3bf5ab 100644
--- a/src/libs/3rdparty/libarchive/archive_hmac.c
+++ b/src/libs/3rdparty/libarchive/archive_hmac.c
@@ -230,10 +230,28 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC *mac;
+
+ char sha1[] = "SHA1";
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string("digest", sha1, sizeof(sha1) - 1),
+ OSSL_PARAM_END
+ };
+
+ mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ *ctx = EVP_MAC_CTX_new(mac);
+ EVP_MAC_free(mac);
+ if (*ctx == NULL)
+ return -1;
+
+ EVP_MAC_init(*ctx, key, key_len, params);
+#else
*ctx = HMAC_CTX_new();
if (*ctx == NULL)
return -1;
HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL);
+#endif
return 0;
}
@@ -241,22 +259,38 @@ static void
__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
size_t data_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_update(*ctx, data, data_len);
+#else
HMAC_Update(*ctx, data, data_len);
+#endif
}
static void
__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ size_t len = *out_len;
+#else
unsigned int len = (unsigned int)*out_len;
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_final(*ctx, out, &len, *out_len);
+#else
HMAC_Final(*ctx, out, &len);
+#endif
*out_len = len;
}
static void
__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_CTX_free(*ctx);
+#else
HMAC_CTX_free(*ctx);
+#endif
*ctx = NULL;
}
diff --git a/src/libs/3rdparty/libarchive/archive_hmac_private.h b/src/libs/3rdparty/libarchive/archive_hmac_private.h
index 13a67d495..d0fda7f96 100644
--- a/src/libs/3rdparty/libarchive/archive_hmac_private.h
+++ b/src/libs/3rdparty/libarchive/archive_hmac_private.h
@@ -74,9 +74,18 @@ typedef mbedtls_md_context_t archive_hmac_sha1_ctx;
typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx;
#elif defined(HAVE_LIBCRYPTO)
+#include <openssl/opensslv.h>
+#include <openssl/hmac.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/params.h>
+
+typedef EVP_MAC_CTX *archive_hmac_sha1_ctx;
+
+#else
#include "archive_openssl_hmac_private.h"
typedef HMAC_CTX* archive_hmac_sha1_ctx;
+#endif
#else
diff --git a/src/libs/3rdparty/libarchive/archive_openssl_evp_private.h b/src/libs/3rdparty/libarchive/archive_openssl_evp_private.h
index ebb06702d..8ac477280 100644
--- a/src/libs/3rdparty/libarchive/archive_openssl_evp_private.h
+++ b/src/libs/3rdparty/libarchive/archive_openssl_evp_private.h
@@ -33,7 +33,8 @@
#include <openssl/evp.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline EVP_MD_CTX *EVP_MD_CTX_new(void)
diff --git a/src/libs/3rdparty/libarchive/archive_pack_dev.c b/src/libs/3rdparty/libarchive/archive_pack_dev.c
index f8286d821..d95444d97 100644
--- a/src/libs/3rdparty/libarchive/archive_pack_dev.c
+++ b/src/libs/3rdparty/libarchive/archive_pack_dev.c
@@ -77,7 +77,7 @@ static pack_t pack_12_20;
static pack_t pack_14_18;
static pack_t pack_8_24;
static pack_t pack_bsdos;
-static int compare_format(const void *, const void *);
+static int __LA_LIBC_CC compare_format(const void *, const void *);
static const char iMajorError[] = "invalid major number";
static const char iMinorError[] = "invalid minor number";
@@ -310,6 +310,7 @@ static const struct format {
};
static int
+__LA_LIBC_CC
compare_format(const void *key, const void *element)
{
const char *name;
diff --git a/src/libs/3rdparty/libarchive/archive_pathmatch.c b/src/libs/3rdparty/libarchive/archive_pathmatch.c
index 619e2b622..0867a268e 100644
--- a/src/libs/3rdparty/libarchive/archive_pathmatch.c
+++ b/src/libs/3rdparty/libarchive/archive_pathmatch.c
@@ -384,6 +384,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
/* Empty pattern only matches the empty string. */
if (p == NULL || *p == '\0')
return (s == NULL || *s == '\0');
+ else if (s == NULL)
+ return (0);
/* Leading '^' anchors the start of the pattern. */
if (*p == '^') {
@@ -424,6 +426,8 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
/* Empty pattern only matches the empty string. */
if (p == NULL || *p == L'\0')
return (s == NULL || *s == L'\0');
+ else if (s == NULL)
+ return (0);
/* Leading '^' anchors the start of the pattern. */
if (*p == L'^') {
diff --git a/src/libs/3rdparty/libarchive/archive_platform.h b/src/libs/3rdparty/libarchive/archive_platform.h
index b8bcb52bc..1038932ac 100644
--- a/src/libs/3rdparty/libarchive/archive_platform.h
+++ b/src/libs/3rdparty/libarchive/archive_platform.h
@@ -69,8 +69,16 @@
* either Windows or Posix APIs. */
#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
#include "archive_windows.h"
+/* The C library on Windows specifies a calling convention for callback
+ * functions and exports; when we interact with them (capture pointers,
+ * call and pass function pointers) we need to match their calling
+ * convention.
+ * This only matters when libarchive is built with /Gr, /Gz or /Gv
+ * (which change the default calling convention.) */
+#define __LA_LIBC_CC __cdecl
#else
#define la_stat(path,stref) stat(path,stref)
+#define __LA_LIBC_CC
#endif
/*
@@ -155,6 +163,28 @@
#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
#endif
+/* Some platforms lack the standard PRIxN/PRIdN definitions. */
+#if !HAVE_INTTYPES_H || !defined(PRIx32) || !defined(PRId32)
+#ifndef PRIx32
+#if SIZEOF_INT == 4
+#define PRIx32 "x"
+#elif SIZEOF_LONG == 4
+#define PRIx32 "lx"
+#else
+#error No suitable 32-bit unsigned integer type found for this platform
+#endif
+#endif // PRIx32
+#ifndef PRId32
+#if SIZEOF_INT == 4
+#define PRId32 "d"
+#elif SIZEOF_LONG == 4
+#define PRId32 "ld"
+#else
+#error No suitable 32-bit signed integer type found for this platform
+#endif
+#endif // PRId32
+#endif // !HAVE_INTTYPES_H || !defined(PRIx32) || !defined(PRId32)
+
/*
* If we can't restore metadata using a file descriptor, then
* for compatibility's sake, close files before trying to restore metadata.
@@ -165,8 +195,9 @@
/*
* glibc 2.24 deprecates readdir_r
+ * bionic c deprecates readdir_r too
*/
-#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
+#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) && (!defined(__ANDROID__))
#define USE_READDIR_R 1
#else
#undef USE_READDIR_R
diff --git a/src/libs/3rdparty/libarchive/archive_private.h b/src/libs/3rdparty/libarchive/archive_private.h
index 937a87bb1..b2a2cda25 100644
--- a/src/libs/3rdparty/libarchive/archive_private.h
+++ b/src/libs/3rdparty/libarchive/archive_private.h
@@ -46,6 +46,13 @@
#define __LA_DEAD
#endif
+#if defined(__GNUC__) && (__GNUC__ > 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
+#define __LA_UNUSED __attribute__((__unused__))
+#else
+#define __LA_UNUSED
+#endif
+
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
@@ -100,14 +107,11 @@ struct archive {
* Some public API functions depend on the "real" type of the
* archive object.
*/
- struct archive_vtable *vtable;
+ const struct archive_vtable *vtable;
int archive_format;
const char *archive_format_name;
- int compression_code; /* Currently active compression. */
- const char *compression_name;
-
/* Number of file entries processed. */
int file_count;
diff --git a/src/libs/3rdparty/libarchive/archive_random.c b/src/libs/3rdparty/libarchive/archive_random.c
index 65ea69157..301765acd 100644
--- a/src/libs/3rdparty/libarchive/archive_random.c
+++ b/src/libs/3rdparty/libarchive/archive_random.c
@@ -51,16 +51,27 @@ __FBSDID("$FreeBSD$");
#include <pthread.h>
#endif
-static void arc4random_buf(void *, size_t);
+static void la_arc4random_buf(void *, size_t);
#endif /* HAVE_ARC4RANDOM_BUF */
#include "archive.h"
#include "archive_random_private.h"
-#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#elif defined(HAVE_WINCRYPT_H)
#include <wincrypt.h>
#endif
+#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
@@ -75,6 +86,20 @@ int
archive_random(void *buf, size_t nbytes)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE hAlg;
+
+ status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return ARCHIVE_FAILED;
+ status = BCryptGenRandom(hAlg, buf, nbytes, 0);
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return ARCHIVE_FAILED;
+
+ return ARCHIVE_OK;
+# else
HCRYPTPROV hProv;
BOOL success;
@@ -92,6 +117,10 @@ archive_random(void *buf, size_t nbytes)
}
/* TODO: Does this case really happen? */
return ARCHIVE_FAILED;
+# endif
+#elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
+ la_arc4random_buf(buf, nbytes);
+ return ARCHIVE_OK;
#else
arc4random_buf(buf, nbytes);
return ARCHIVE_OK;
@@ -173,7 +202,7 @@ arc4_init(void)
}
static inline void
-arc4_addrandom(u_char *dat, int datlen)
+arc4_addrandom(uint8_t *dat, int datlen)
{
int n;
uint8_t si;
@@ -196,7 +225,7 @@ arc4_stir(void)
struct {
struct timeval tv;
pid_t pid;
- u_char rnd[KEYSIZE];
+ uint8_t rnd[KEYSIZE];
} rdat;
if (!rs_initialized) {
@@ -216,7 +245,7 @@ arc4_stir(void)
/* We'll just take whatever was on the stack too... */
}
- arc4_addrandom((u_char *)&rdat, KEYSIZE);
+ arc4_addrandom((uint8_t *)&rdat, KEYSIZE);
/*
* Discard early keystream, as per recommendations in:
@@ -256,9 +285,9 @@ arc4_getbyte(void)
}
static void
-arc4random_buf(void *_buf, size_t n)
+la_arc4random_buf(void *_buf, size_t n)
{
- u_char *buf = (u_char *)_buf;
+ uint8_t *buf = (uint8_t *)_buf;
_ARC4_LOCK();
arc4_stir_if_needed();
while (n--) {
diff --git a/src/libs/3rdparty/libarchive/archive_read.c b/src/libs/3rdparty/libarchive/archive_read.c
index c59f05153..45a38aed0 100644
--- a/src/libs/3rdparty/libarchive/archive_read.c
+++ b/src/libs/3rdparty/libarchive/archive_read.c
@@ -58,7 +58,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
static int choose_filters(struct archive_read *);
static int choose_format(struct archive_read *);
static int close_filters(struct archive_read *);
-static struct archive_vtable *archive_read_vtable(void);
static int64_t _archive_filter_bytes(struct archive *, int);
static int _archive_filter_code(struct archive *, int);
static const char *_archive_filter_name(struct archive *, int);
@@ -73,26 +72,18 @@ static int _archive_read_next_header2(struct archive *,
struct archive_entry *);
static int64_t advance_file_pointer(struct archive_read_filter *, int64_t);
-static struct archive_vtable *
-archive_read_vtable(void)
-{
- static struct archive_vtable av;
- static int inited = 0;
-
- if (!inited) {
- av.archive_filter_bytes = _archive_filter_bytes;
- av.archive_filter_code = _archive_filter_code;
- av.archive_filter_name = _archive_filter_name;
- av.archive_filter_count = _archive_filter_count;
- av.archive_read_data_block = _archive_read_data_block;
- av.archive_read_next_header = _archive_read_next_header;
- av.archive_read_next_header2 = _archive_read_next_header2;
- av.archive_free = _archive_read_free;
- av.archive_close = _archive_read_close;
- inited = 1;
- }
- return (&av);
-}
+static const struct archive_vtable
+archive_read_vtable = {
+ .archive_filter_bytes = _archive_filter_bytes,
+ .archive_filter_code = _archive_filter_code,
+ .archive_filter_name = _archive_filter_name,
+ .archive_filter_count = _archive_filter_count,
+ .archive_read_data_block = _archive_read_data_block,
+ .archive_read_next_header = _archive_read_next_header,
+ .archive_read_next_header2 = _archive_read_next_header2,
+ .archive_free = _archive_read_free,
+ .archive_close = _archive_read_close,
+};
/*
* Allocate, initialize and return a struct archive object.
@@ -109,7 +100,7 @@ archive_read_new(void)
a->archive.state = ARCHIVE_STATE_NEW;
a->entry = archive_entry_new2(&a->archive);
- a->archive.vtable = archive_read_vtable();
+ a->archive.vtable = &archive_read_vtable;
a->passphrases.last = &a->passphrases.first;
@@ -245,18 +236,17 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
}
static int
-client_close_proxy(struct archive_read_filter *self)
+read_client_close_proxy(struct archive_read *a)
{
int r = ARCHIVE_OK, r2;
unsigned int i;
- if (self->archive->client.closer == NULL)
+ if (a->client.closer == NULL)
return (r);
- for (i = 0; i < self->archive->client.nodes; i++)
+ for (i = 0; i < a->client.nodes; i++)
{
- r2 = (self->archive->client.closer)
- ((struct archive *)self->archive,
- self->archive->client.dataset[i].data);
+ r2 = (a->client.closer)
+ ((struct archive *)a, a->client.dataset[i].data);
if (r > r2)
r = r2;
}
@@ -264,6 +254,12 @@ client_close_proxy(struct archive_read_filter *self)
}
static int
+client_close_proxy(struct archive_read_filter *self)
+{
+ return read_client_close_proxy(self->archive);
+}
+
+static int
client_open_proxy(struct archive_read_filter *self)
{
int r = ARCHIVE_OK;
@@ -298,9 +294,7 @@ client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
r1 = (self->archive->client.closer)
((struct archive *)self->archive, self->data);
self->data = data2;
- if (self->archive->client.opener != NULL)
- r2 = (self->archive->client.opener)
- ((struct archive *)self->archive, self->data);
+ r2 = client_open_proxy(self);
}
return (r1 < r2) ? r1 : r2;
}
@@ -457,13 +451,18 @@ archive_read_prepend_callback_data(struct archive *_a, void *client_data)
return archive_read_add_callback_data(_a, client_data, 0);
}
+static const struct archive_read_filter_vtable
+none_reader_vtable = {
+ .read = client_read_proxy,
+ .close = client_close_proxy,
+};
+
int
archive_read_open1(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *filter, *tmp;
int slot, e = ARCHIVE_OK;
- unsigned int i;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_open");
@@ -481,11 +480,7 @@ archive_read_open1(struct archive *_a)
e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
if (e != 0) {
/* If the open failed, call the closer to clean up. */
- if (a->client.closer) {
- for (i = 0; i < a->client.nodes; i++)
- (a->client.closer)(&a->archive,
- a->client.dataset[i].data);
- }
+ read_client_close_proxy(a);
return (e);
}
}
@@ -497,14 +492,11 @@ archive_read_open1(struct archive *_a)
filter->upstream = NULL;
filter->archive = a;
filter->data = a->client.dataset[0].data;
- filter->open = client_open_proxy;
- filter->read = client_read_proxy;
- filter->skip = client_skip_proxy;
- filter->seek = client_seek_proxy;
- filter->close = client_close_proxy;
- filter->sswitch = client_switch_proxy;
+ filter->vtable = &none_reader_vtable;
filter->name = "none";
filter->code = ARCHIVE_FILTER_NONE;
+ filter->can_skip = 1;
+ filter->can_seek = 1;
a->client.dataset[0].begin_position = 0;
if (!a->filter || !a->bypass_filter_bidding)
@@ -570,12 +562,12 @@ choose_filters(struct archive_read *a)
bidder = a->bidders;
for (i = 0; i < number_bidders; i++, bidder++) {
- if (bidder->bid != NULL) {
- bid = (bidder->bid)(bidder, a->filter);
- if (bid > best_bid) {
- best_bid = bid;
- best_bidder = bidder;
- }
+ if (bidder->vtable == NULL)
+ continue;
+ bid = (bidder->vtable->bid)(bidder, a->filter);
+ if (bid > best_bid) {
+ best_bid = bid;
+ best_bidder = bidder;
}
}
@@ -587,8 +579,6 @@ choose_filters(struct archive_read *a)
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
- a->archive.compression_name = a->filter->name;
- a->archive.compression_code = a->filter->code;
return (ARCHIVE_OK);
}
@@ -600,7 +590,7 @@ choose_filters(struct archive_read *a)
filter->archive = a;
filter->upstream = a->filter;
a->filter = filter;
- r = (best_bidder->init)(a->filter);
+ r = (best_bidder->vtable->init)(a->filter);
if (r != ARCHIVE_OK) {
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
@@ -614,10 +604,9 @@ choose_filters(struct archive_read *a)
int
__archive_read_header(struct archive_read *a, struct archive_entry *entry)
{
- if (a->filter->read_header)
- return a->filter->read_header(a->filter, entry);
- else
+ if (!a->filter->vtable->read_header)
return (ARCHIVE_OK);
+ return a->filter->vtable->read_header(a->filter, entry);
}
/*
@@ -1006,8 +995,8 @@ close_filters(struct archive_read *a)
/* Close each filter in the pipeline. */
while (f != NULL) {
struct archive_read_filter *t = f->upstream;
- if (!f->closed && f->close != NULL) {
- int r1 = (f->close)(f);
+ if (!f->closed && f->vtable != NULL) {
+ int r1 = (f->vtable->close)(f);
f->closed = 1;
if (r1 < r)
r = r1;
@@ -1112,11 +1101,10 @@ _archive_read_free(struct archive *_a)
/* Release the bidder objects. */
n = sizeof(a->bidders)/sizeof(a->bidders[0]);
for (i = 0; i < n; i++) {
- if (a->bidders[i].free != NULL) {
- int r1 = (a->bidders[i].free)(&a->bidders[i]);
- if (r1 < r)
- r = r1;
- }
+ if (a->bidders[i].vtable == NULL ||
+ a->bidders[i].vtable->free == NULL)
+ continue;
+ (a->bidders[i].vtable->free)(&a->bidders[i]);
}
/* Release passphrase list. */
@@ -1241,19 +1229,35 @@ __archive_read_register_format(struct archive_read *a,
* initialization functions.
*/
int
-__archive_read_get_bidder(struct archive_read *a,
- struct archive_read_filter_bidder **bidder)
+__archive_read_register_bidder(struct archive_read *a,
+ void *bidder_data,
+ const char *name,
+ const struct archive_read_filter_bidder_vtable *vtable)
{
+ struct archive_read_filter_bidder *bidder;
int i, number_slots;
+ archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "__archive_read_register_bidder");
+
number_slots = sizeof(a->bidders) / sizeof(a->bidders[0]);
for (i = 0; i < number_slots; i++) {
- if (a->bidders[i].bid == NULL) {
- memset(a->bidders + i, 0, sizeof(a->bidders[0]));
- *bidder = (a->bidders + i);
- return (ARCHIVE_OK);
+ if (a->bidders[i].vtable != NULL)
+ continue;
+ memset(a->bidders + i, 0, sizeof(a->bidders[0]));
+ bidder = (a->bidders + i);
+ bidder->data = bidder_data;
+ bidder->name = name;
+ bidder->vtable = vtable;
+ if (bidder->vtable->bid == NULL || bidder->vtable->init == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: "
+ "no bid/init for filter bidder");
+ return (ARCHIVE_FATAL);
}
+
+ return (ARCHIVE_OK);
}
archive_set_error(&a->archive, ENOMEM,
@@ -1382,7 +1386,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
*avail = 0;
return (NULL);
}
- bytes_read = (filter->read)(filter,
+ bytes_read = (filter->vtable->read)(filter,
&filter->client_buff);
if (bytes_read < 0) { /* Read error. */
filter->client_total = filter->client_avail = 0;
@@ -1561,8 +1565,8 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
return (total_bytes_skipped);
/* If there's an optimized skip function, use it. */
- if (filter->skip != NULL) {
- bytes_skipped = (filter->skip)(filter, request);
+ if (filter->can_skip != 0) {
+ bytes_skipped = client_skip_proxy(filter, request);
if (bytes_skipped < 0) { /* error */
filter->fatal = 1;
return (bytes_skipped);
@@ -1576,7 +1580,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
/* Use ordinary reads as necessary to complete the request. */
for (;;) {
- bytes_read = (filter->read)(filter, &filter->client_buff);
+ bytes_read = (filter->vtable->read)(filter, &filter->client_buff);
if (bytes_read < 0) {
filter->client_buff = NULL;
filter->fatal = 1;
@@ -1631,7 +1635,7 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
if (filter->closed || filter->fatal)
return (ARCHIVE_FATAL);
- if (filter->seek == NULL)
+ if (filter->can_seek == 0)
return (ARCHIVE_FAILED);
client = &(filter->archive->client);
diff --git a/src/libs/3rdparty/libarchive/archive_read_append_filter.c b/src/libs/3rdparty/libarchive/archive_read_append_filter.c
index da7c55b9b..25dc4b2a2 100644
--- a/src/libs/3rdparty/libarchive/archive_read_append_filter.c
+++ b/src/libs/3rdparty/libarchive/archive_read_append_filter.c
@@ -135,7 +135,7 @@ archive_read_append_filter(struct archive *_a, int code)
filter->archive = a;
filter->upstream = a->filter;
a->filter = filter;
- r2 = (bidder->init)(a->filter);
+ r2 = (bidder->vtable->init)(a->filter);
if (r2 != ARCHIVE_OK) {
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
@@ -192,7 +192,7 @@ archive_read_append_filter_program_signature(struct archive *_a,
filter->archive = a;
filter->upstream = a->filter;
a->filter = filter;
- r = (bidder->init)(a->filter);
+ r = (bidder->vtable->init)(a->filter);
if (r != ARCHIVE_OK) {
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
diff --git a/src/libs/3rdparty/libarchive/archive_read_data_into_fd.c b/src/libs/3rdparty/libarchive/archive_read_data_into_fd.c
index b4398f1ec..f16ca5c82 100644
--- a/src/libs/3rdparty/libarchive/archive_read_data_into_fd.c
+++ b/src/libs/3rdparty/libarchive/archive_read_data_into_fd.c
@@ -95,8 +95,13 @@ archive_read_data_into_fd(struct archive *a, int fd)
"archive_read_data_into_fd");
can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode);
- if (!can_lseek)
+ if (!can_lseek) {
nulls = calloc(1, nulls_size);
+ if (!nulls) {
+ r = ARCHIVE_FATAL;
+ goto cleanup;
+ }
+ }
while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) ==
ARCHIVE_OK) {
diff --git a/src/libs/3rdparty/libarchive/archive_read_disk_entry_from_file.c b/src/libs/3rdparty/libarchive/archive_read_disk_entry_from_file.c
index 9c9cf38ee..ab0270bc2 100644
--- a/src/libs/3rdparty/libarchive/archive_read_disk_entry_from_file.c
+++ b/src/libs/3rdparty/libarchive/archive_read_disk_entry_from_file.c
@@ -303,9 +303,11 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (r1 < r)
r = r1;
}
- r1 = setup_sparse(a, entry, &fd);
- if (r1 < r)
- r = r1;
+ if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
+ r1 = setup_sparse(a, entry, &fd);
+ if (r1 < r)
+ r = r1;
+ }
/* If we opened the file earlier in this function, close it. */
if (initial_fd != fd)
diff --git a/src/libs/3rdparty/libarchive/archive_read_disk_posix.c b/src/libs/3rdparty/libarchive/archive_read_disk_posix.c
index 289820695..8d5c32f03 100644
--- a/src/libs/3rdparty/libarchive/archive_read_disk_posix.c
+++ b/src/libs/3rdparty/libarchive/archive_read_disk_posix.c
@@ -34,9 +34,6 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -54,6 +51,8 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
+#elif HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
#endif
/*
* Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
@@ -109,6 +108,11 @@ __FBSDID("$FreeBSD$");
#define O_CLOEXEC 0
#endif
+#if defined(__hpux) && !defined(HAVE_DIRFD)
+#define dirfd(x) ((x)->__dd_fd)
+#define HAVE_DIRFD
+#endif
+
/*-
* This is a new directory-walking system that addresses a number
* of problems I've had with fts(3). In particular, it has no
@@ -369,22 +373,14 @@ static int open_on_current_dir(struct tree *, const char *, int);
static int tree_dup(int);
-static struct archive_vtable *
-archive_read_disk_vtable(void)
-{
- static struct archive_vtable av;
- static int inited = 0;
-
- if (!inited) {
- av.archive_free = _archive_read_free;
- av.archive_close = _archive_read_close;
- av.archive_read_data_block = _archive_read_data_block;
- av.archive_read_next_header = _archive_read_next_header;
- av.archive_read_next_header2 = _archive_read_next_header2;
- inited = 1;
- }
- return (&av);
-}
+static const struct archive_vtable
+archive_read_disk_vtable = {
+ .archive_free = _archive_read_free,
+ .archive_close = _archive_read_close,
+ .archive_read_data_block = _archive_read_data_block,
+ .archive_read_next_header = _archive_read_next_header,
+ .archive_read_next_header2 = _archive_read_next_header2,
+};
const char *
archive_read_disk_gname(struct archive *_a, la_int64_t gid)
@@ -461,7 +457,7 @@ archive_read_disk_new(void)
return (NULL);
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
- a->archive.vtable = archive_read_disk_vtable();
+ a->archive.vtable = &archive_read_disk_vtable;
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
@@ -1290,7 +1286,7 @@ archive_read_disk_descend(struct archive *_a)
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_disk_descend");
- if (t->visit_type != TREE_REGULAR || !t->descend)
+ if (!archive_read_disk_can_descend(_a))
return (ARCHIVE_OK);
/*
@@ -1522,8 +1518,40 @@ get_xfer_size(struct tree *t, int fd, const char *path)
}
#endif
-#if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \
- && !defined(ST_LOCAL)
+#if defined(HAVE_STATVFS)
+static inline __LA_UNUSED void
+set_statvfs_transfer_size(struct filesystem *fs, const struct statvfs *sfs)
+{
+ fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1;
+ fs->max_xfer_size = -1;
+#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
+ fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
+ fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
+#else
+ fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
+ fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
+#endif
+}
+#endif
+
+#if defined(HAVE_STRUCT_STATFS)
+static inline __LA_UNUSED void
+set_statfs_transfer_size(struct filesystem *fs, const struct statfs *sfs)
+{
+ fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
+ fs->max_xfer_size = -1;
+#if defined(HAVE_STRUCT_STATFS_F_IOSIZE)
+ fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
+ fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
+#else
+ fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
+ fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
+#endif
+}
+#endif
+
+#if defined(HAVE_STRUCT_STATFS) && defined(HAVE_STATFS) && \
+ defined(HAVE_FSTATFS) && defined(MNT_LOCAL) && !defined(ST_LOCAL)
/*
* Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
@@ -1593,10 +1621,7 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
- t->current_filesystem->xfer_align = sfs.f_bsize;
- t->current_filesystem->max_xfer_size = -1;
- t->current_filesystem->min_xfer_size = sfs.f_iosize;
- t->current_filesystem->incr_xfer_size = sfs.f_iosize;
+ set_statfs_transfer_size(t->current_filesystem, &sfs);
}
if (sfs.f_flags & MNT_LOCAL)
t->current_filesystem->remote = 0;
@@ -1645,6 +1670,11 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
#endif
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -1688,15 +1718,7 @@ setup_current_filesystem(struct archive_read_disk *a)
} else if (xr == 1) {
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
* for pathconf() function. */
- t->current_filesystem->xfer_align = svfs.f_frsize;
- t->current_filesystem->max_xfer_size = -1;
-#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
- t->current_filesystem->min_xfer_size = svfs.f_iosize;
- t->current_filesystem->incr_xfer_size = svfs.f_iosize;
-#else
- t->current_filesystem->min_xfer_size = svfs.f_bsize;
- t->current_filesystem->incr_xfer_size = svfs.f_bsize;
-#endif
+ set_statvfs_transfer_size(t->current_filesystem, &svfs);
}
if (svfs.f_flag & ST_LOCAL)
t->current_filesystem->remote = 0;
@@ -1803,15 +1825,9 @@ setup_current_filesystem(struct archive_read_disk *a)
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
#if defined(HAVE_STATVFS)
- t->current_filesystem->xfer_align = svfs.f_frsize;
- t->current_filesystem->max_xfer_size = -1;
- t->current_filesystem->min_xfer_size = svfs.f_bsize;
- t->current_filesystem->incr_xfer_size = svfs.f_bsize;
+ set_statvfs_transfer_size(t->current_filesystem, &svfs);
#else
- t->current_filesystem->xfer_align = sfs.f_frsize;
- t->current_filesystem->max_xfer_size = -1;
- t->current_filesystem->min_xfer_size = sfs.f_bsize;
- t->current_filesystem->incr_xfer_size = sfs.f_bsize;
+ set_statfs_transfer_size(t->current_filesystem, &sfs);
#endif
}
switch (sfs.f_type) {
@@ -1849,8 +1865,17 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
+#if defined(HAVE_STATVFS)
+ t->current_filesystem->name_max = svfs.f_namemax;
+#else
t->current_filesystem->name_max = sfs.f_namelen;
#endif
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
+#endif
return (ARCHIVE_OK);
}
@@ -1918,10 +1943,7 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
- t->current_filesystem->xfer_align = svfs.f_frsize;
- t->current_filesystem->max_xfer_size = -1;
- t->current_filesystem->min_xfer_size = svfs.f_bsize;
- t->current_filesystem->incr_xfer_size = svfs.f_bsize;
+ set_statvfs_transfer_size(t->current_filesystem, &svfs);
}
#if defined(ST_NOATIME)
@@ -1934,6 +1956,11 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = svfs.f_namemax;
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
#endif
return (ARCHIVE_OK);
}
@@ -1988,6 +2015,11 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
# endif /* _PC_NAME_MAX */
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -2094,6 +2126,8 @@ tree_push(struct tree *t, const char *path, int filesystem_id,
struct tree_entry *te;
te = calloc(1, sizeof(*te));
+ if (te == NULL)
+ __archive_errx(1, "Out of memory");
te->next = t->stack;
te->parent = t->current;
if (te->parent)
@@ -2424,7 +2458,7 @@ tree_dir_next_posix(struct tree *t)
#else /* HAVE_FDOPENDIR */
if (tree_enter_working_dir(t) == 0) {
t->d = opendir(".");
-#if HAVE_DIRFD || defined(dirfd)
+#ifdef HAVE_DIRFD
__archive_ensure_cloexec_flag(dirfd(t->d));
#endif
}
@@ -2533,7 +2567,11 @@ tree_current_lstat(struct tree *t)
#else
if (tree_enter_working_dir(t) != 0)
return NULL;
+#ifdef HAVE_LSTAT
if (lstat(tree_current_access_path(t), &t->lst) != 0)
+#else
+ if (la_stat(tree_current_access_path(t), &t->lst) != 0)
+#endif
#endif
return NULL;
t->flags |= hasLstat;
diff --git a/src/libs/3rdparty/libarchive/archive_read_disk_windows.c b/src/libs/3rdparty/libarchive/archive_read_disk_windows.c
index fdd376f9b..f92a78a21 100644
--- a/src/libs/3rdparty/libarchive/archive_read_disk_windows.c
+++ b/src/libs/3rdparty/libarchive/archive_read_disk_windows.c
@@ -418,8 +418,19 @@ la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype)
FILE_FLAG_OPEN_REPARSE_POINT;
int ret;
- h = CreateFileW(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, flag,
- NULL);
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = flag;
+ h = CreateFile2(path, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ OPEN_EXISTING, &createExParams);
+#else
+ h = CreateFileW(path, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+ OPEN_EXISTING, flag, NULL);
+#endif
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
return (-1);
@@ -449,22 +460,14 @@ entry_symlink_from_pathw(struct archive_entry *entry, const wchar_t *path)
return;
}
-static struct archive_vtable *
-archive_read_disk_vtable(void)
-{
- static struct archive_vtable av;
- static int inited = 0;
-
- if (!inited) {
- av.archive_free = _archive_read_free;
- av.archive_close = _archive_read_close;
- av.archive_read_data_block = _archive_read_data_block;
- av.archive_read_next_header = _archive_read_next_header;
- av.archive_read_next_header2 = _archive_read_next_header2;
- inited = 1;
- }
- return (&av);
-}
+static const struct archive_vtable
+archive_read_disk_vtable = {
+ .archive_free = _archive_read_free,
+ .archive_close = _archive_read_close,
+ .archive_read_data_block = _archive_read_data_block,
+ .archive_read_next_header = _archive_read_next_header,
+ .archive_read_next_header2 = _archive_read_next_header2,
+};
const char *
archive_read_disk_gname(struct archive *_a, la_int64_t gid)
@@ -541,7 +544,7 @@ archive_read_disk_new(void)
return (NULL);
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
- a->archive.vtable = archive_read_disk_vtable();
+ a->archive.vtable = &archive_read_disk_vtable;
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
@@ -1074,14 +1077,29 @@ next_entry(struct archive_read_disk *a, struct tree *t,
if (archive_entry_filetype(entry) == AE_IFREG &&
archive_entry_size(entry) > 0) {
DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
+#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
if (t->async_io)
flags |= FILE_FLAG_OVERLAPPED;
if (t->direct_io)
flags |= FILE_FLAG_NO_BUFFERING;
else
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
+#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = flags;
+ t->entry_fh = CreateFile2(tree_current_access_path(t),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ OPEN_EXISTING, &createExParams);
+#else
t->entry_fh = CreateFileW(tree_current_access_path(t),
- GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, flags, NULL);
+#endif
if (t->entry_fh == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
@@ -1090,9 +1108,11 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
/* Find sparse data from the disk. */
- if (archive_entry_hardlink(entry) == NULL &&
- (st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0)
- r = setup_sparse_from_disk(a, entry, t->entry_fh);
+ if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
+ if (archive_entry_hardlink(entry) == NULL &&
+ (st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0)
+ r = setup_sparse_from_disk(a, entry, t->entry_fh);
+ }
}
return (r);
}
@@ -1300,7 +1320,7 @@ archive_read_disk_descend(struct archive *_a)
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_disk_descend");
- if (t->visit_type != TREE_REGULAR || !t->descend)
+ if (!archive_read_disk_can_descend(_a))
return (ARCHIVE_OK);
if (tree_current_is_physical_dir(t)) {
@@ -1550,6 +1570,9 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
{
HANDLE handle;
int r = 0;
+#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
return (0);
@@ -1563,8 +1586,16 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
if ((t->flags & needsRestoreTimes) == 0)
return (r);
+#if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
+ handle = CreateFile2(rt->full_path, FILE_WRITE_ATTRIBUTES,
+ 0, OPEN_EXISTING, &createExParams);
+#else
handle = CreateFileW(rt->full_path, FILE_WRITE_ATTRIBUTES,
0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+#endif
if (handle == INVALID_HANDLE_VALUE) {
errno = EINVAL;
return (-1);
@@ -1844,7 +1875,7 @@ tree_next(struct tree *t)
continue;
return (r);
} else {
- HANDLE h = FindFirstFileW(d, &t->_findData);
+ HANDLE h = FindFirstFileW(t->stack->full_path.s, &t->_findData);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
t->tree_errno = errno;
@@ -2049,11 +2080,24 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
HANDLE h;
int r;
DWORD flag = FILE_FLAG_BACKUP_SEMANTICS;
-
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
+
if (sim_lstat && tree_current_is_physical_link(t))
flag |= FILE_FLAG_OPEN_REPARSE_POINT;
- h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL,
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = flag;
+ h = CreateFile2(tree_current_access_path(t), 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ OPEN_EXISTING, &createExParams);
+#else
+ h = CreateFileW(tree_current_access_path(t), 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, flag, NULL);
+#endif
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
t->tree_errno = errno;
@@ -2259,7 +2303,10 @@ archive_read_disk_entry_from_file(struct archive *_a,
} else {
WIN32_FIND_DATAW findData;
DWORD flag, desiredAccess;
-
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
+
h = FindFirstFileW(path, &findData);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
@@ -2281,8 +2328,18 @@ archive_read_disk_entry_from_file(struct archive *_a,
} else
desiredAccess = GENERIC_READ;
- h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL,
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = flag;
+ h = CreateFile2(path, desiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ OPEN_EXISTING, &createExParams);
+#else
+ h = CreateFileW(path, desiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, flag, NULL);
+#endif
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
@@ -2343,8 +2400,19 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (fd >= 0) {
h = (HANDLE)_get_osfhandle(fd);
} else {
- h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
+ h = CreateFile2(path, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ OPEN_EXISTING, &createExParams);
+#else
+ h = CreateFileW(path, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+#endif
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
@@ -2371,9 +2439,11 @@ archive_read_disk_entry_from_file(struct archive *_a,
return (ARCHIVE_OK);
}
- r = setup_sparse_from_disk(a, entry, h);
- if (fd < 0)
- CloseHandle(h);
+ if ((a->flags & ARCHIVE_READDISK_NO_SPARSE) == 0) {
+ r = setup_sparse_from_disk(a, entry, h);
+ if (fd < 0)
+ CloseHandle(h);
+ }
return (r);
}
diff --git a/src/libs/3rdparty/libarchive/archive_read_open_file.c b/src/libs/3rdparty/libarchive/archive_read_open_file.c
index 101dae6cd..03719e8bf 100644
--- a/src/libs/3rdparty/libarchive/archive_read_open_file.c
+++ b/src/libs/3rdparty/libarchive/archive_read_open_file.c
@@ -154,10 +154,10 @@ file_skip(struct archive *a, void *client_data, int64_t request)
#ifdef __ANDROID__
/* fileno() isn't safe on all platforms ... see above. */
if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
-#elif HAVE_FSEEKO
- if (fseeko(mine->f, skip, SEEK_CUR) != 0)
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
+#elif HAVE_FSEEKO
+ if (fseeko(mine->f, skip, SEEK_CUR) != 0)
#else
if (fseek(mine->f, skip, SEEK_CUR) != 0)
#endif
diff --git a/src/libs/3rdparty/libarchive/archive_read_private.h b/src/libs/3rdparty/libarchive/archive_read_private.h
index c842e6f09..383405d52 100644
--- a/src/libs/3rdparty/libarchive/archive_read_private.h
+++ b/src/libs/3rdparty/libarchive/archive_read_private.h
@@ -42,6 +42,16 @@ struct archive_read;
struct archive_read_filter_bidder;
struct archive_read_filter;
+struct archive_read_filter_bidder_vtable {
+ /* Taste the upstream filter to see if we handle this. */
+ int (*bid)(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+ /* Initialize a newly-created filter. */
+ int (*init)(struct archive_read_filter *);
+ /* Release the bidder's configuration data. */
+ void (*free)(struct archive_read_filter_bidder *);
+};
+
/*
* How bidding works for filters:
* * The bid manager initializes the client-provided reader as the
@@ -62,16 +72,16 @@ struct archive_read_filter_bidder {
void *data;
/* Name of the filter */
const char *name;
- /* Taste the upstream filter to see if we handle this. */
- int (*bid)(struct archive_read_filter_bidder *,
- struct archive_read_filter *);
- /* Initialize a newly-created filter. */
- int (*init)(struct archive_read_filter *);
- /* Set an option for the filter bidder. */
- int (*options)(struct archive_read_filter_bidder *,
- const char *key, const char *value);
- /* Release the bidder's configuration data. */
- int (*free)(struct archive_read_filter_bidder *);
+ const struct archive_read_filter_bidder_vtable *vtable;
+};
+
+struct archive_read_filter_vtable {
+ /* Return next block. */
+ ssize_t (*read)(struct archive_read_filter *, const void **);
+ /* Close (just this filter) and free(self). */
+ int (*close)(struct archive_read_filter *self);
+ /* Read any header metadata if available. */
+ int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry);
};
/*
@@ -86,25 +96,14 @@ struct archive_read_filter {
struct archive_read_filter_bidder *bidder; /* My bidder. */
struct archive_read_filter *upstream; /* Who I read from. */
struct archive_read *archive; /* Associated archive. */
- /* Open a block for reading */
- int (*open)(struct archive_read_filter *self);
- /* Return next block. */
- ssize_t (*read)(struct archive_read_filter *, const void **);
- /* Skip forward this many bytes. */
- int64_t (*skip)(struct archive_read_filter *self, int64_t request);
- /* Seek to an absolute location. */
- int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
- /* Close (just this filter) and free(self). */
- int (*close)(struct archive_read_filter *self);
- /* Function that handles switching from reading one block to the next/prev */
- int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
- /* Read any header metadata if available. */
- int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry);
+ const struct archive_read_filter_vtable *vtable;
/* My private data. */
void *data;
const char *name;
int code;
+ int can_skip;
+ int can_seek;
/* Used by reblocking logic. */
char *buffer;
@@ -242,8 +241,10 @@ int __archive_read_register_format(struct archive_read *a,
int (*format_capabilities)(struct archive_read *),
int (*has_encrypted_entries)(struct archive_read *));
-int __archive_read_get_bidder(struct archive_read *a,
- struct archive_read_filter_bidder **bidder);
+int __archive_read_register_bidder(struct archive_read *a,
+ void *bidder_data,
+ const char *name,
+ const struct archive_read_filter_bidder_vtable *vtable);
const void *__archive_read_ahead(struct archive_read *, size_t, ssize_t *);
const void *__archive_read_filter_ahead(struct archive_read_filter *,
diff --git a/src/libs/3rdparty/libarchive/archive_read_set_options.c b/src/libs/3rdparty/libarchive/archive_read_set_options.c
index 2e2eea690..2bd9b811e 100644
--- a/src/libs/3rdparty/libarchive/archive_read_set_options.c
+++ b/src/libs/3rdparty/libarchive/archive_read_set_options.c
@@ -112,37 +112,15 @@ static int
archive_set_filter_option(struct archive *_a, const char *m, const char *o,
const char *v)
{
- struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter *filter;
- struct archive_read_filter_bidder *bidder;
- int r, rv = ARCHIVE_WARN, matched_modules = 0;
-
- for (filter = a->filter; filter != NULL; filter = filter->upstream) {
- bidder = filter->bidder;
- if (bidder == NULL)
- continue;
- if (bidder->options == NULL)
- /* This bidder does not support option */
- continue;
- if (m != NULL) {
- if (strcmp(filter->name, m) != 0)
- continue;
- ++matched_modules;
- }
+ (void)_a; /* UNUSED */
+ (void)o; /* UNUSED */
+ (void)v; /* UNUSED */
- r = bidder->options(bidder, o, v);
-
- if (r == ARCHIVE_FATAL)
- return (ARCHIVE_FATAL);
-
- if (r == ARCHIVE_OK)
- rv = ARCHIVE_OK;
- }
/* If the filter name didn't match, return a special code for
* _archive_set_option[s]. */
- if (m != NULL && matched_modules == 0)
+ if (m != NULL)
return ARCHIVE_WARN - 1;
- return (rv);
+ return ARCHIVE_WARN;
}
static int
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_bzip2.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_bzip2.c
index 3885a7cf6..9158e668e 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_bzip2.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_bzip2.c
@@ -70,7 +70,6 @@ static int bzip2_filter_close(struct archive_read_filter *);
*/
static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
static int bzip2_reader_init(struct archive_read_filter *);
-static int bzip2_reader_free(struct archive_read_filter_bidder *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Deprecated; remove in libarchive 4.0 */
@@ -81,24 +80,21 @@ archive_read_support_compression_bzip2(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+bzip2_bidder_vtable = {
+ .bid = bzip2_reader_bid,
+ .init = bzip2_reader_init,
+};
+
int
archive_read_support_filter_bzip2(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *reader;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_bzip2");
- if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "bzip2",
+ &bzip2_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- reader->data = NULL;
- reader->name = "bzip2";
- reader->bid = bzip2_reader_bid;
- reader->init = bzip2_reader_init;
- reader->options = NULL;
- reader->free = bzip2_reader_free;
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
return (ARCHIVE_OK);
#else
@@ -108,12 +104,6 @@ archive_read_support_filter_bzip2(struct archive *_a)
#endif
}
-static int
-bzip2_reader_free(struct archive_read_filter_bidder *self){
- (void)self; /* UNUSED */
- return (ARCHIVE_OK);
-}
-
/*
* Test whether we can handle this data.
*
@@ -183,6 +173,12 @@ bzip2_reader_init(struct archive_read_filter *self)
#else
+static const struct archive_read_filter_vtable
+bzip2_reader_vtable = {
+ .read = bzip2_filter_read,
+ .close = bzip2_filter_close,
+};
+
/*
* Setup the callbacks.
*/
@@ -209,9 +205,7 @@ bzip2_reader_init(struct archive_read_filter *self)
self->data = state;
state->out_block_size = out_block_size;
state->out_block = out_block;
- self->read = bzip2_filter_read;
- self->skip = NULL; /* not supported */
- self->close = bzip2_filter_close;
+ self->vtable = &bzip2_reader_vtable;
return (ARCHIVE_OK);
}
@@ -236,7 +230,7 @@ bzip2_filter_read(struct archive_read_filter *self, const void **p)
/* Empty our output buffer. */
state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
+ state->stream.avail_out = (uint32_t)state->out_block_size;
/* Try to fill the output buffer. */
for (;;) {
@@ -294,7 +288,7 @@ bzip2_filter_read(struct archive_read_filter *self, const void **p)
return (ARCHIVE_FATAL);
}
state->stream.next_in = (char *)(uintptr_t)read_buf;
- state->stream.avail_in = ret;
+ state->stream.avail_in = (uint32_t)ret;
/* There is no more data, return whatever we have. */
if (ret == 0) {
state->eof = 1;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_compress.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_compress.c
index e05132dbf..05b80a576 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_compress.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_compress.c
@@ -133,7 +133,6 @@ struct private_data {
static int compress_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
static int compress_bidder_init(struct archive_read_filter *);
-static int compress_bidder_free(struct archive_read_filter_bidder *);
static ssize_t compress_filter_read(struct archive_read_filter *, const void **);
static int compress_filter_close(struct archive_read_filter *);
@@ -150,25 +149,19 @@ archive_read_support_compression_compress(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+compress_bidder_vtable = {
+ .bid = compress_bidder_bid,
+ .init = compress_bidder_init,
+};
+
int
archive_read_support_filter_compress(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_compress");
-
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "compress (.Z)";
- bidder->bid = compress_bidder_bid;
- bidder->init = compress_bidder_init;
- bidder->options = NULL;
- bidder->free = compress_bidder_free;
- return (ARCHIVE_OK);
+ return __archive_read_register_bidder(a, NULL, "compress (.Z)",
+ &compress_bidder_vtable);
}
/*
@@ -205,6 +198,12 @@ compress_bidder_bid(struct archive_read_filter_bidder *self,
return (bits_checked);
}
+static const struct archive_read_filter_vtable
+compress_reader_vtable = {
+ .read = compress_filter_read,
+ .close = compress_filter_close,
+};
+
/*
* Setup the callbacks.
*/
@@ -233,9 +232,7 @@ compress_bidder_init(struct archive_read_filter *self)
self->data = state;
state->out_block_size = out_block_size;
state->out_block = out_block;
- self->read = compress_filter_read;
- self->skip = NULL; /* not supported */
- self->close = compress_filter_close;
+ self->vtable = &compress_reader_vtable;
/* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */
@@ -306,16 +303,6 @@ compress_filter_read(struct archive_read_filter *self, const void **pblock)
}
/*
- * Clean up the reader.
- */
-static int
-compress_bidder_free(struct archive_read_filter_bidder *self)
-{
- self->data = NULL;
- return (ARCHIVE_OK);
-}
-
-/*
* Close and release the filter.
*/
static int
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_grzip.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_grzip.c
index 84c86aeb4..d4d1737cd 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_grzip.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_grzip.c
@@ -54,30 +54,21 @@ static int grzip_bidder_bid(struct archive_read_filter_bidder *,
static int grzip_bidder_init(struct archive_read_filter *);
-static int
-grzip_reader_free(struct archive_read_filter_bidder *self)
-{
- (void)self; /* UNUSED */
- return (ARCHIVE_OK);
-}
+static const struct archive_read_filter_bidder_vtable
+grzip_bidder_vtable = {
+ .bid = grzip_bidder_bid,
+ .init = grzip_bidder_init,
+};
int
archive_read_support_filter_grzip(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *reader;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip");
- if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, NULL,
+ &grzip_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- reader->data = NULL;
- reader->bid = grzip_bidder_bid;
- reader->init = grzip_bidder_init;
- reader->options = NULL;
- reader->free = grzip_reader_free;
/* This filter always uses an external program. */
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external grzip program for grzip decompression");
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_gzip.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_gzip.c
index 9fa9e2b0d..4135a6361 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_gzip.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_gzip.c
@@ -94,24 +94,21 @@ archive_read_support_compression_gzip(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+gzip_bidder_vtable = {
+ .bid = gzip_bidder_bid,
+ .init = gzip_bidder_init,
+};
+
int
archive_read_support_filter_gzip(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_gzip");
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "gzip",
+ &gzip_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "gzip";
- bidder->bid = gzip_bidder_bid;
- bidder->init = gzip_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL; /* No data, so no cleanup necessary. */
/* Signal the extent of gzip support with the return value here. */
#if HAVE_ZLIB_H
return (ARCHIVE_OK);
@@ -291,6 +288,15 @@ gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry)
return (ARCHIVE_OK);
}
+static const struct archive_read_filter_vtable
+gzip_reader_vtable = {
+ .read = gzip_filter_read,
+ .close = gzip_filter_close,
+#ifdef HAVE_ZLIB_H
+ .read_header = gzip_read_header,
+#endif
+};
+
/*
* Initialize the filter object.
*/
@@ -317,12 +323,7 @@ gzip_bidder_init(struct archive_read_filter *self)
self->data = state;
state->out_block_size = out_block_size;
state->out_block = out_block;
- self->read = gzip_filter_read;
- self->skip = NULL; /* not supported */
- self->close = gzip_filter_close;
-#ifdef HAVE_ZLIB_H
- self->read_header = gzip_read_header;
-#endif
+ self->vtable = &gzip_reader_vtable;
state->in_stream = 0; /* We're not actually within a stream yet. */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_lrzip.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_lrzip.c
index c82a8e2f1..a2389894f 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_lrzip.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_lrzip.c
@@ -53,31 +53,21 @@ static int lrzip_bidder_bid(struct archive_read_filter_bidder *,
static int lrzip_bidder_init(struct archive_read_filter *);
-static int
-lrzip_reader_free(struct archive_read_filter_bidder *self)
-{
- (void)self; /* UNUSED */
- return (ARCHIVE_OK);
-}
+static const struct archive_read_filter_bidder_vtable
+lrzip_bidder_vtable = {
+ .bid = lrzip_bidder_bid,
+ .init = lrzip_bidder_init,
+};
int
archive_read_support_filter_lrzip(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *reader;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip");
- if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "lrzip",
+ &lrzip_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- reader->data = NULL;
- reader->name = "lrzip";
- reader->bid = lrzip_bidder_bid;
- reader->init = lrzip_bidder_init;
- reader->options = NULL;
- reader->free = lrzip_reader_free;
/* This filter always uses an external program. */
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external lrzip program for lrzip decompression");
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c
index 43ee6c2b7..d0fc1a83e 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_lz4.c
@@ -99,7 +99,6 @@ static int lz4_filter_close(struct archive_read_filter *);
*/
static int lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
static int lz4_reader_init(struct archive_read_filter *);
-static int lz4_reader_free(struct archive_read_filter_bidder *);
#if defined(HAVE_LIBLZ4)
static ssize_t lz4_filter_read_default_stream(struct archive_read_filter *,
const void **);
@@ -107,24 +106,21 @@ static ssize_t lz4_filter_read_legacy_stream(struct archive_read_filter *,
const void **);
#endif
+static const struct archive_read_filter_bidder_vtable
+lz4_bidder_vtable = {
+ .bid = lz4_reader_bid,
+ .init = lz4_reader_init,
+};
+
int
archive_read_support_filter_lz4(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *reader;
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_lz4");
-
- if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "lz4",
+ &lz4_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- reader->data = NULL;
- reader->name = "lz4";
- reader->bid = lz4_reader_bid;
- reader->init = lz4_reader_init;
- reader->options = NULL;
- reader->free = lz4_reader_free;
#if defined(HAVE_LIBLZ4)
return (ARCHIVE_OK);
#else
@@ -134,12 +130,6 @@ archive_read_support_filter_lz4(struct archive *_a)
#endif
}
-static int
-lz4_reader_free(struct archive_read_filter_bidder *self){
- (void)self; /* UNUSED */
- return (ARCHIVE_OK);
-}
-
/*
* Test whether we can handle this data.
*
@@ -218,6 +208,12 @@ lz4_reader_init(struct archive_read_filter *self)
#else
+static const struct archive_read_filter_vtable
+lz4_reader_vtable = {
+ .read = lz4_filter_read,
+ .close = lz4_filter_close,
+};
+
/*
* Setup the callbacks.
*/
@@ -238,9 +234,7 @@ lz4_reader_init(struct archive_read_filter *self)
self->data = state;
state->stage = SELECT_STREAM;
- self->read = lz4_filter_read;
- self->skip = NULL; /* not supported */
- self->close = lz4_filter_close;
+ self->vtable = &lz4_reader_vtable;
return (ARCHIVE_OK);
}
@@ -456,7 +450,9 @@ lz4_filter_read_descriptor(struct archive_read_filter *self)
chsum = (chsum >> 8) & 0xff;
chsum_verifier = read_buf[descriptor_bytes-1] & 0xff;
if (chsum != chsum_verifier)
+#ifndef DONT_FAIL_ON_CRC_ERROR
goto malformed_error;
+#endif
__archive_read_filter_consume(self->upstream, descriptor_bytes);
@@ -527,7 +523,9 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
unsigned int chsum_block =
archive_le32dec(read_buf + 4 + compressed_size);
if (chsum != chsum_block)
+#ifndef DONT_FAIL_ON_CRC_ERROR
goto malformed_error;
+#endif
}
@@ -586,7 +584,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
state->out_block + prefix64k, (int)compressed_size,
state->flags.block_maximum_size,
state->out_block,
- prefix64k);
+ (int)prefix64k);
#else
uncompressed_size = LZ4_decompress_safe_withPrefix64k(
read_buf + 4,
@@ -658,10 +656,12 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
state->xxh32_state);
state->xxh32_state = NULL;
if (checksum != checksum_stream) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
"lz4 stream checksum error");
return (ARCHIVE_FATAL);
+#endif
}
} else if (ret > 0)
__archive_xxhash.XXH32_update(state->xxh32_state,
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c
index a1c392f4f..4ebdd3bf3 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_lzop.c
@@ -101,23 +101,21 @@ static int lzop_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
static int lzop_bidder_init(struct archive_read_filter *);
+static const struct archive_read_filter_bidder_vtable
+lzop_bidder_vtable = {
+ .bid = lzop_bidder_bid,
+ .init = lzop_bidder_init,
+};
+
int
archive_read_support_filter_lzop(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *reader;
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop");
-
- if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, NULL,
+ &lzop_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- reader->data = NULL;
- reader->bid = lzop_bidder_bid;
- reader->init = lzop_bidder_init;
- reader->options = NULL;
- reader->free = NULL;
/* Signal the extent of lzop support with the return value here. */
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
return (ARCHIVE_OK);
@@ -171,6 +169,13 @@ lzop_bidder_init(struct archive_read_filter *self)
return (r);
}
#else
+
+static const struct archive_read_filter_vtable
+lzop_reader_vtable = {
+ .read = lzop_filter_read,
+ .close = lzop_filter_close
+};
+
/*
* Initialize the filter object.
*/
@@ -190,9 +195,7 @@ lzop_bidder_init(struct archive_read_filter *self)
}
self->data = state;
- self->read = lzop_filter_read;
- self->skip = NULL; /* not supported */
- self->close = lzop_filter_close;
+ self->vtable = &lzop_reader_vtable;
return (ARCHIVE_OK);
}
@@ -280,7 +283,9 @@ consume_header(struct archive_read_filter *self)
else
checksum = adler32(adler32(0, NULL, 0), p, len);
if (archive_be32dec(p + len) != checksum)
+#ifndef DONT_FAIL_ON_CRC_ERROR
goto corrupted;
+#endif
__archive_read_filter_consume(self->upstream, len + 4);
if (flags & EXTRA_FIELD) {
/* Skip extra field */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_program.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_program.c
index bf5b6f2b3..885b2c205 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_program.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_program.c
@@ -98,7 +98,7 @@ struct program_bidder {
static int program_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *upstream);
static int program_bidder_init(struct archive_read_filter *);
-static int program_bidder_free(struct archive_read_filter_bidder *);
+static void program_bidder_free(struct archive_read_filter_bidder *);
/*
* The actual filter needs to track input and output data.
@@ -123,43 +123,21 @@ static ssize_t program_filter_read(struct archive_read_filter *,
static int program_filter_close(struct archive_read_filter *);
static void free_state(struct program_bidder *);
-static int
-set_bidder_signature(struct archive_read_filter_bidder *bidder,
- struct program_bidder *state, const void *signature, size_t signature_len)
-{
-
- if (signature != NULL && signature_len > 0) {
- state->signature_len = signature_len;
- state->signature = malloc(signature_len);
- memcpy(state->signature, signature, signature_len);
- }
-
- /*
- * Fill in the bidder object.
- */
- bidder->data = state;
- bidder->bid = program_bidder_bid;
- bidder->init = program_bidder_init;
- bidder->options = NULL;
- bidder->free = program_bidder_free;
- return (ARCHIVE_OK);
-}
+static const struct archive_read_filter_bidder_vtable
+program_bidder_vtable = {
+ .bid = program_bidder_bid,
+ .init = program_bidder_init,
+ .free = program_bidder_free,
+};
int
archive_read_support_filter_program_signature(struct archive *_a,
const char *cmd, const void *signature, size_t signature_len)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
struct program_bidder *state;
/*
- * Get a bidder object from the read core.
- */
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
-
- /*
* Allocate our private state.
*/
state = (struct program_bidder *)calloc(1, sizeof (*state));
@@ -169,20 +147,31 @@ archive_read_support_filter_program_signature(struct archive *_a,
if (state->cmd == NULL)
goto memerr;
- return set_bidder_signature(bidder, state, signature, signature_len);
+ if (signature != NULL && signature_len > 0) {
+ state->signature_len = signature_len;
+ state->signature = malloc(signature_len);
+ memcpy(state->signature, signature, signature_len);
+ }
+
+ if (__archive_read_register_bidder(a, state, NULL,
+ &program_bidder_vtable) != ARCHIVE_OK) {
+ free_state(state);
+ return (ARCHIVE_FATAL);
+ }
+ return (ARCHIVE_OK);
+
memerr:
free_state(state);
archive_set_error(_a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
-static int
+static void
program_bidder_free(struct archive_read_filter_bidder *self)
{
struct program_bidder *state = (struct program_bidder *)self->data;
free_state(state);
- return (ARCHIVE_OK);
}
static void
@@ -393,6 +382,12 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
}
}
+static const struct archive_read_filter_vtable
+program_reader_vtable = {
+ .read = program_filter_read,
+ .close = program_filter_close,
+};
+
int
__archive_read_program(struct archive_read_filter *self, const char *cmd)
{
@@ -439,9 +434,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
}
self->data = state;
- self->read = program_filter_read;
- self->skip = NULL;
- self->close = program_filter_close;
+ self->vtable = &program_reader_vtable;
/* XXX Check that we can read at least one byte? */
return (ARCHIVE_OK);
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_rpm.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_rpm.c
index e7e58e51f..67a979cd7 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_rpm.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_rpm.c
@@ -72,25 +72,19 @@ archive_read_support_compression_rpm(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+rpm_bidder_vtable = {
+ .bid = rpm_bidder_bid,
+ .init = rpm_bidder_init,
+};
+
int
archive_read_support_filter_rpm(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_rpm");
-
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "rpm";
- bidder->bid = rpm_bidder_bid;
- bidder->init = rpm_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL;
- return (ARCHIVE_OK);
+ return __archive_read_register_bidder(a, NULL, "rpm",
+ &rpm_bidder_vtable);
}
static int
@@ -133,6 +127,12 @@ rpm_bidder_bid(struct archive_read_filter_bidder *self,
return (bits_checked);
}
+static const struct archive_read_filter_vtable
+rpm_reader_vtable = {
+ .read = rpm_filter_read,
+ .close = rpm_filter_close,
+};
+
static int
rpm_bidder_init(struct archive_read_filter *self)
{
@@ -140,9 +140,6 @@ rpm_bidder_init(struct archive_read_filter *self)
self->code = ARCHIVE_FILTER_RPM;
self->name = "rpm";
- self->read = rpm_filter_read;
- self->skip = NULL; /* not supported */
- self->close = rpm_filter_close;
rpm = (struct rpm *)calloc(sizeof(*rpm), 1);
if (rpm == NULL) {
@@ -153,6 +150,7 @@ rpm_bidder_init(struct archive_read_filter *self)
self->data = rpm;
rpm->state = ST_LEAD;
+ self->vtable = &rpm_reader_vtable;
return (ARCHIVE_OK);
}
@@ -216,7 +214,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
archive_set_error(
&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
- "Unrecoginized rpm header");
+ "Unrecognized rpm header");
return (ARCHIVE_FATAL);
}
rpm->state = ST_ARCHIVE;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_uu.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_uu.c
index 67ddffb06..209b2a159 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_uu.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_uu.c
@@ -76,25 +76,19 @@ archive_read_support_compression_uu(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+uudecode_bidder_vtable = {
+ .bid = uudecode_bidder_bid,
+ .init = uudecode_bidder_init,
+};
+
int
archive_read_support_filter_uu(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_uu");
-
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "uu";
- bidder->bid = uudecode_bidder_bid;
- bidder->init = uudecode_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL;
- return (ARCHIVE_OK);
+ return __archive_read_register_bidder(a, NULL, "uu",
+ &uudecode_bidder_vtable);
}
static const unsigned char ascii[256] = {
@@ -248,7 +242,7 @@ bid_get_line(struct archive_read_filter *filter,
*ravail = *avail;
*b += diff;
*avail -= diff;
- tested = len;/* Skip some bytes we already determinated. */
+ tested = len;/* Skip some bytes we already determined. */
len = get_line(*b + tested, *avail - tested, nl);
if (len >= 0)
len += tested;
@@ -357,6 +351,12 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
return (0);
}
+static const struct archive_read_filter_vtable
+uudecode_reader_vtable = {
+ .read = uudecode_filter_read,
+ .close = uudecode_filter_close,
+};
+
static int
uudecode_bidder_init(struct archive_read_filter *self)
{
@@ -366,9 +366,6 @@ uudecode_bidder_init(struct archive_read_filter *self)
self->code = ARCHIVE_FILTER_UU;
self->name = "uu";
- self->read = uudecode_filter_read;
- self->skip = NULL; /* not supported */
- self->close = uudecode_filter_close;
uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1);
out_buff = malloc(OUT_BUFF_SIZE);
@@ -388,6 +385,7 @@ uudecode_bidder_init(struct archive_read_filter *self)
uudecode->in_allocated = IN_BUFF_SIZE;
uudecode->out_buff = out_buff;
uudecode->state = ST_FIND_HEAD;
+ self->vtable = &uudecode_reader_vtable;
return (ARCHIVE_OK);
}
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c
index 11807cf67..e313d39c0 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_xz.c
@@ -108,24 +108,21 @@ archive_read_support_compression_xz(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+xz_bidder_vtable = {
+ .bid = xz_bidder_bid,
+ .init = xz_bidder_init,
+};
+
int
archive_read_support_filter_xz(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_xz");
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "xz",
+ &xz_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "xz";
- bidder->bid = xz_bidder_bid;
- bidder->init = xz_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL;
#if HAVE_LZMA_H && HAVE_LIBLZMA
return (ARCHIVE_OK);
#else
@@ -143,24 +140,21 @@ archive_read_support_compression_lzma(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+lzma_bidder_vtable = {
+ .bid = lzma_bidder_bid,
+ .init = lzma_bidder_init,
+};
+
int
archive_read_support_filter_lzma(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_lzma");
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "lzma",
+ &lzma_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "lzma";
- bidder->bid = lzma_bidder_bid;
- bidder->init = lzma_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL;
#if HAVE_LZMA_H && HAVE_LIBLZMA
return (ARCHIVE_OK);
#else
@@ -179,24 +173,21 @@ archive_read_support_compression_lzip(struct archive *a)
}
#endif
+static const struct archive_read_filter_bidder_vtable
+lzip_bidder_vtable = {
+ .bid = lzip_bidder_bid,
+ .init = lzip_bidder_init,
+};
+
int
archive_read_support_filter_lzip(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_lzip");
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "lzip",
+ &lzip_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "lzip";
- bidder->bid = lzip_bidder_bid;
- bidder->init = lzip_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL;
#if HAVE_LZMA_H && HAVE_LIBLZMA
return (ARCHIVE_OK);
#else
@@ -293,8 +284,8 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
/* Second through fifth bytes are dictionary size, stored in
* little-endian order. The minimum dictionary size is
* 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
- * -d12 and the maximum dictionary size is 1 << 27(128MiB)
- * which the one uses with option -d27.
+ * -d12 and the maximum dictionary size is 1 << 29(512MiB)
+ * which the one uses with option -d29.
* NOTE: A comment of LZMA SDK source code says this dictionary
* range is from 1 << 12 to 1 << 30. */
dicsize = archive_le32dec(buffer+1);
@@ -377,7 +368,7 @@ lzip_has_member(struct archive_read_filter *filter)
/* Dictionary size. */
log2dic = buffer[5] & 0x1f;
- if (log2dic < 12 || log2dic > 27)
+ if (log2dic < 12 || log2dic > 29)
return (0);
bits_checked += 8;
@@ -470,6 +461,12 @@ set_error(struct archive_read_filter *self, int ret)
}
}
+static const struct archive_read_filter_vtable
+xz_lzma_reader_vtable = {
+ .read = xz_filter_read,
+ .close = xz_filter_close,
+};
+
/*
* Setup the callbacks.
*/
@@ -494,9 +491,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
self->data = state;
state->out_block_size = out_block_size;
state->out_block = out_block;
- self->read = xz_filter_read;
- self->skip = NULL; /* not supported */
- self->close = xz_filter_close;
+ self->vtable = &xz_lzma_reader_vtable;
state->stream.avail_in = 0;
@@ -562,7 +557,7 @@ lzip_init(struct archive_read_filter *self)
/* Get dictionary size. */
log2dic = h[5] & 0x1f;
- if (log2dic < 12 || log2dic > 27)
+ if (log2dic < 12 || log2dic > 29)
return (ARCHIVE_FATAL);
dicsize = 1U << log2dic;
if (log2dic > 12)
@@ -617,9 +612,11 @@ lzip_tail(struct archive_read_filter *self)
/* Check the crc32 value of the uncompressed data of the current
* member */
if (state->crc32 != archive_le32dec(f)) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
"Lzip: CRC32 error");
return (ARCHIVE_FAILED);
+#endif
}
/* Check the uncompressed size of the current member */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_filter_zstd.c b/src/libs/3rdparty/libarchive/archive_read_support_filter_zstd.c
index af7eeb7c1..1959b5ac3 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_filter_zstd.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_filter_zstd.c
@@ -79,24 +79,21 @@ static int zstd_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
static int zstd_bidder_init(struct archive_read_filter *);
+static const struct archive_read_filter_bidder_vtable
+zstd_bidder_vtable = {
+ .bid = zstd_bidder_bid,
+ .init = zstd_bidder_init,
+};
+
int
archive_read_support_filter_zstd(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter_bidder *bidder;
-
- archive_check_magic(_a, ARCHIVE_READ_MAGIC,
- ARCHIVE_STATE_NEW, "archive_read_support_filter_zstd");
- if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ if (__archive_read_register_bidder(a, NULL, "zstd",
+ &zstd_bidder_vtable) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- bidder->data = NULL;
- bidder->name = "zstd";
- bidder->bid = zstd_bidder_bid;
- bidder->init = zstd_bidder_init;
- bidder->options = NULL;
- bidder->free = NULL;
#if HAVE_ZSTD_H && HAVE_LIBZSTD
return (ARCHIVE_OK);
#else
@@ -118,9 +115,9 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self,
unsigned prefix;
/* Zstd frame magic values */
- const unsigned zstd_magic = 0xFD2FB528U;
- const unsigned zstd_magic_skippable_start = 0x184D2A50U;
- const unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
+ unsigned zstd_magic = 0xFD2FB528U;
+ unsigned zstd_magic_skippable_start = 0x184D2A50U;
+ unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
(void) self; /* UNUSED */
@@ -160,6 +157,12 @@ zstd_bidder_init(struct archive_read_filter *self)
#else
+static const struct archive_read_filter_vtable
+zstd_reader_vtable = {
+ .read = zstd_filter_read,
+ .close = zstd_filter_close,
+};
+
/*
* Initialize the filter object
*/
@@ -167,7 +170,7 @@ static int
zstd_bidder_init(struct archive_read_filter *self)
{
struct private_data *state;
- const size_t out_block_size = ZSTD_DStreamOutSize();
+ size_t out_block_size = ZSTD_DStreamOutSize();
void *out_block;
ZSTD_DStream *dstream;
@@ -192,9 +195,7 @@ zstd_bidder_init(struct archive_read_filter *self)
state->out_block_size = out_block_size;
state->out_block = out_block;
state->dstream = dstream;
- self->read = zstd_filter_read;
- self->skip = NULL; /* not supported */
- self->close = zstd_filter_close;
+ self->vtable = &zstd_reader_vtable;
state->eof = 0;
state->in_frame = 0;
@@ -210,6 +211,7 @@ zstd_filter_read(struct archive_read_filter *self, const void **p)
ssize_t avail_in;
ZSTD_outBuffer out;
ZSTD_inBuffer in;
+ size_t ret;
state = (struct private_data *)self->data;
@@ -218,7 +220,7 @@ zstd_filter_read(struct archive_read_filter *self, const void **p)
/* Try to fill the output buffer. */
while (out.pos < out.size && !state->eof) {
if (!state->in_frame) {
- const size_t ret = ZSTD_initDStream(state->dstream);
+ ret = ZSTD_initDStream(state->dstream);
if (ZSTD_isError(ret)) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
@@ -248,8 +250,7 @@ zstd_filter_read(struct archive_read_filter *self, const void **p)
in.pos = 0;
{
- const size_t ret =
- ZSTD_decompressStream(state->dstream, &out, &in);
+ ret = ZSTD_decompressStream(state->dstream, &out, &in);
if (ZSTD_isError(ret)) {
archive_set_error(&self->archive->archive,
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c b/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c
index 6ce9d1a0e..b171bea01 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_7zip.c
@@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_entry.h"
@@ -80,8 +83,11 @@ __FBSDID("$FreeBSD$");
#define _7Z_IA64 0x03030401
#define _7Z_ARM 0x03030501
#define _7Z_ARMTHUMB 0x03030701
+#define _7Z_ARM64 0xa
#define _7Z_SPARC 0x03030805
+#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
+
/*
* 7-Zip header property IDs.
*/
@@ -278,6 +284,11 @@ struct _7zip {
z_stream stream;
int stream_valid;
#endif
+ /* Decoding Zstandard data. */
+#if HAVE_ZSTD_H
+ ZSTD_DStream *zstd_dstream;
+ int zstdstream_valid;
+#endif
/* Decoding PPMd data. */
int ppmd7_stat;
CPpmd7 ppmd7_context;
@@ -287,6 +298,7 @@ struct _7zip {
const unsigned char *next_in;
int64_t avail_in;
int64_t total_in;
+ int64_t stream_in;
unsigned char *next_out;
int64_t avail_out;
int64_t total_out;
@@ -396,6 +408,9 @@ static int setup_decode_folder(struct archive_read *, struct _7z_folder *,
int);
static void x86_Init(struct _7zip *);
static size_t x86_Convert(struct _7zip *, uint8_t *, size_t);
+static void arm_Init(struct _7zip *);
+static size_t arm_Convert(struct _7zip *, uint8_t *, size_t);
+static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t);
static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
@@ -775,7 +790,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
}
/* Set up a more descriptive format name. */
- sprintf(zip->format_name, "7-Zip");
+ snprintf(zip->format_name, sizeof(zip->format_name), "7-Zip");
a->archive.archive_format_name = zip->format_name;
return (ret);
@@ -808,8 +823,12 @@ archive_read_format_7zip_read_data(struct archive_read *a,
if (zip->end_of_entry)
return (ARCHIVE_EOF);
- bytes = read_stream(a, buff,
- (size_t)zip->entry_bytes_remaining, 0);
+ const uint64_t max_read_size = 16 * 1024 * 1024; // Don't try to read more than 16 MB at a time
+ size_t bytes_to_read = max_read_size;
+ if ((uint64_t)bytes_to_read > zip->entry_bytes_remaining) {
+ bytes_to_read = zip->entry_bytes_remaining;
+ }
+ bytes = read_stream(a, buff, bytes_to_read, 0);
if (bytes < 0)
return ((int)bytes);
if (bytes == 0) {
@@ -982,15 +1001,30 @@ ppmd_read(void *p)
struct _7zip *zip = (struct _7zip *)(a->format->data);
Byte b;
- if (zip->ppstream.avail_in == 0) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Truncated RAR file data");
- zip->ppstream.overconsumed = 1;
- return (0);
+ if (zip->ppstream.avail_in <= 0) {
+ /*
+ * Ppmd7_DecodeSymbol might require reading multiple bytes
+ * and we are on boundary;
+ * last resort to read using __archive_read_ahead.
+ */
+ ssize_t bytes_avail = 0;
+ const uint8_t* data = __archive_read_ahead(a,
+ zip->ppstream.stream_in+1, &bytes_avail);
+ if(bytes_avail < zip->ppstream.stream_in+1) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated 7z file data");
+ zip->ppstream.overconsumed = 1;
+ return (0);
+ }
+ zip->ppstream.next_in++;
+ b = data[zip->ppstream.stream_in];
+ } else {
+ b = *zip->ppstream.next_in++;
}
- b = *zip->ppstream.next_in++;
zip->ppstream.avail_in--;
zip->ppstream.total_in++;
+ zip->ppstream.stream_in++;
return (b);
}
@@ -1007,10 +1041,13 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
case _7Z_COPY:
case _7Z_BZ2:
case _7Z_DEFLATE:
+ case _7Z_ZSTD:
case _7Z_PPMD:
if (coder2 != NULL) {
if (coder2->codec != _7Z_X86 &&
- coder2->codec != _7Z_X86_BCJ2) {
+ coder2->codec != _7Z_X86_BCJ2 &&
+ coder2->codec != _7Z_ARM &&
+ coder2->codec != _7Z_ARM64) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Unsupported filter %lx for %lx",
@@ -1021,6 +1058,8 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
zip->bcj_state = 0;
if (coder2->codec == _7Z_X86)
x86_Init(zip);
+ else if (coder2->codec == _7Z_ARM)
+ arm_Init(zip);
}
break;
default:
@@ -1117,6 +1156,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_FILTER_ARMTHUMB;
fi++;
break;
+#ifdef LZMA_FILTER_ARM64
+ case _7Z_ARM64:
+ filters[fi].id = LZMA_FILTER_ARM64;
+ fi++;
+ break;
+#endif
case _7Z_SPARC:
filters[fi].id = LZMA_FILTER_SPARC;
fi++;
@@ -1202,6 +1247,22 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
"BZ2 codec is unsupported");
return (ARCHIVE_FAILED);
#endif
+ case _7Z_ZSTD:
+ {
+#if defined(HAVE_ZSTD_H)
+ if (zip->zstdstream_valid) {
+ ZSTD_freeDStream(zip->zstd_dstream);
+ zip->zstdstream_valid = 0;
+ }
+ zip->zstd_dstream = ZSTD_createDStream();
+ zip->zstdstream_valid = 1;
+ break;
+#else
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "ZSTD codec is unsupported");
+ return (ARCHIVE_FAILED);
+#endif
+ }
case _7Z_DEFLATE:
#ifdef HAVE_ZLIB_H
if (zip->stream_valid)
@@ -1416,9 +1477,9 @@ decompress(struct archive_read *a, struct _7zip *zip,
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
case _7Z_BZ2:
zip->bzstream.next_in = (char *)(uintptr_t)t_next_in;
- zip->bzstream.avail_in = t_avail_in;
+ zip->bzstream.avail_in = (uint32_t)t_avail_in;
zip->bzstream.next_out = (char *)(uintptr_t)t_next_out;
- zip->bzstream.avail_out = t_avail_out;
+ zip->bzstream.avail_out = (uint32_t)t_avail_out;
r = BZ2_bzDecompress(&(zip->bzstream));
switch (r) {
case BZ_STREAM_END: /* Found end of stream. */
@@ -1468,6 +1529,22 @@ decompress(struct archive_read *a, struct _7zip *zip,
t_avail_out = zip->stream.avail_out;
break;
#endif
+#ifdef HAVE_ZSTD_H
+ case _7Z_ZSTD:
+ {
+ ZSTD_inBuffer input = { t_next_in, t_avail_in, 0 }; // src, size, pos
+ ZSTD_outBuffer output = { t_next_out, t_avail_out, 0 }; // dst, size, pos
+
+ size_t const zret = ZSTD_decompressStream(zip->zstd_dstream, &output, &input);
+ if (ZSTD_isError(zret)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Zstd decompression failed: %s", ZSTD_getErrorName(zret));
+ return ARCHIVE_FAILED;
+ }
+ t_avail_in -= input.pos;
+ t_avail_out -= output.pos;
+ break;
+ }
+#endif
case _7Z_PPMD:
{
uint64_t flush_bytes;
@@ -1481,6 +1558,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
}
zip->ppstream.next_in = t_next_in;
zip->ppstream.avail_in = t_avail_in;
+ zip->ppstream.stream_in = 0;
zip->ppstream.next_out = t_next_out;
zip->ppstream.avail_out = t_avail_out;
if (zip->ppmd7_stat == 0) {
@@ -1493,7 +1571,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
zip->ppmd7_stat = -1;
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
- "Failed to initialize PPMd range decorder");
+ "Failed to initialize PPMd range decoder");
return (ARCHIVE_FAILED);
}
if (zip->ppstream.overconsumed) {
@@ -1551,16 +1629,23 @@ decompress(struct archive_read *a, struct _7zip *zip,
/*
* Decord BCJ.
*/
- if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) {
- size_t l = x86_Convert(zip, buff, *outbytes);
- zip->odd_bcj_size = *outbytes - l;
- if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 &&
- o_avail_in && ret != ARCHIVE_EOF) {
- memcpy(zip->odd_bcj, ((unsigned char *)buff) + l,
- zip->odd_bcj_size);
- *outbytes = l;
- } else
- zip->odd_bcj_size = 0;
+ if (zip->codec != _7Z_LZMA2) {
+ if (zip->codec2 == _7Z_X86) {
+ size_t l = x86_Convert(zip, buff, *outbytes);
+
+ zip->odd_bcj_size = *outbytes - l;
+ if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 &&
+ o_avail_in && ret != ARCHIVE_EOF) {
+ memcpy(zip->odd_bcj, ((unsigned char *)buff) + l,
+ zip->odd_bcj_size);
+ *outbytes = l;
+ } else
+ zip->odd_bcj_size = 0;
+ } else if (zip->codec2 == _7Z_ARM) {
+ *outbytes = arm_Convert(zip, buff, *outbytes);
+ } else if (zip->codec2 == _7Z_ARM64) {
+ *outbytes = arm64_Convert(zip, buff, *outbytes);
+ }
}
/*
@@ -2836,8 +2921,10 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
/* CRC check. */
if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8)) {
+#ifdef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, -1, "Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
next_header_offset = archive_le64dec(p + 12);
@@ -2887,8 +2974,10 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
/* Check the EncodedHeader CRC.*/
if (r == 0 && zip->header_crc32 != next_header_crc) {
archive_set_error(&a->archive, -1,
+#ifndef DONT_FAIL_ON_CRC_ERROR
"Damaged 7-Zip archive");
r = -1;
+#endif
}
if (r == 0) {
if (zip->si.ci.folders[0].digest_defined)
@@ -2939,9 +3028,11 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
/* Check the Header CRC.*/
if (check_header_crc && zip->header_crc32 != next_header_crc) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, -1,
"Malformed 7-Zip archive");
return (ARCHIVE_FATAL);
+#endif
}
break;
default:
@@ -3031,10 +3122,10 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
"Truncated 7-Zip file body");
return (ARCHIVE_FATAL);
}
- if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining)
+ if ((uint64_t)bytes_avail > zip->pack_stream_inbytes_remaining)
bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
zip->pack_stream_inbytes_remaining -= bytes_avail;
- if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining)
+ if ((uint64_t)bytes_avail > zip->folder_outbytes_remaining)
bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
zip->folder_outbytes_remaining -= bytes_avail;
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
@@ -3700,6 +3791,116 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
return (bufferPos);
}
+static void
+arm_Init(struct _7zip *zip)
+{
+ zip->bcj_ip = 8;
+}
+
+static size_t
+arm_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
+{
+ // This function was adapted from
+ // static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+ // in https://git.tukaani.org/xz-embedded.git
+
+ /*
+ * Branch/Call/Jump (BCJ) filter decoders
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <https://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+ size_t i;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ if (buf[i + 3] == 0xEB) {
+ // Calculate the transformed addr.
+ addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
+ | ((uint32_t)buf[i + 2] << 16);
+ addr <<= 2;
+ addr -= zip->bcj_ip + (uint32_t)i;
+ addr >>= 2;
+
+ // Store the transformed addr in buf.
+ buf[i] = (uint8_t)addr;
+ buf[i + 1] = (uint8_t)(addr >> 8);
+ buf[i + 2] = (uint8_t)(addr >> 16);
+ }
+ }
+
+ zip->bcj_ip += (uint32_t)i;
+
+ return i;
+}
+
+static size_t
+arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
+{
+ // This function was adapted from
+ // static size_t bcj_arm64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+ // in https://git.tukaani.org/xz-embedded.git
+
+ /*
+ * Branch/Call/Jump (BCJ) filter decoders
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <https://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+ size_t i;
+ uint32_t instr;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ instr = (uint32_t)buf[i]
+ | ((uint32_t)buf[i+1] << 8)
+ | ((uint32_t)buf[i+2] << 16)
+ | ((uint32_t)buf[i+3] << 24);
+
+ if ((instr >> 26) == 0x25) {
+ /* BL instruction */
+ addr = instr - ((zip->bcj_ip + (uint32_t)i) >> 2);
+ instr = 0x94000000 | (addr & 0x03FFFFFF);
+
+ buf[i] = (uint8_t)instr;
+ buf[i+1] = (uint8_t)(instr >> 8);
+ buf[i+2] = (uint8_t)(instr >> 16);
+ buf[i+3] = (uint8_t)(instr >> 24);
+ } else if ((instr & 0x9F000000) == 0x90000000) {
+ /* ADRP instruction */
+ addr = ((instr >> 29) & 3) | ((instr >> 3) & 0x1FFFFC);
+
+ /* Only convert values in the range +/-512 MiB. */
+ if ((addr + 0x020000) & 0x1C0000)
+ continue;
+
+ addr -= (zip->bcj_ip + (uint32_t)i) >> 12;
+
+ instr &= 0x9000001F;
+ instr |= (addr & 3) << 29;
+ instr |= (addr & 0x03FFFC) << 3;
+ instr |= (0U - (addr & 0x020000)) & 0xE00000;
+
+ buf[i] = (uint8_t)instr;
+ buf[i+1] = (uint8_t)(instr >> 8);
+ buf[i+2] = (uint8_t)(instr >> 16);
+ buf[i+3] = (uint8_t)(instr >> 24);
+ }
+ }
+
+ zip->bcj_ip += (uint32_t)i;
+
+ return i;
+}
+
/*
* Brought from LZMA SDK.
*
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c b/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c
index 43738b537..3b552a84d 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_cab.c
@@ -996,7 +996,7 @@ archive_read_format_cab_read_header(struct archive_read *a,
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
/* Set up a more descriptive format name. */
- sprintf(cab->format_name, "CAB %d.%d (%s)",
+ snprintf(cab->format_name, sizeof(cab->format_name), "CAB %d.%d (%s)",
hd->major, hd->minor, cab->entry_cffolder->compname);
a->archive.archive_format_name = cab->format_name;
@@ -1134,7 +1134,7 @@ cab_checksum_update(struct archive_read *a, size_t bytes)
}
if (sumbytes) {
int odd = sumbytes & 3;
- if (sumbytes - odd > 0)
+ if ((int)(sumbytes - odd) > 0)
cfdata->sum_calculated = cab_checksum_cfdata_4(
p, sumbytes - odd, cfdata->sum_calculated);
if (odd)
@@ -1171,12 +1171,14 @@ cab_checksum_finish(struct archive_read *a)
cfdata->sum_calculated = cab_checksum_cfdata(
cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
if (cfdata->sum_calculated != cfdata->sum) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes",
cab->entry_cffolder->cfdata_index -1,
cfdata->sum, cfdata->sum_calculated,
cfdata->compressed_size);
return (ARCHIVE_FAILED);
+#endif
}
return (ARCHIVE_OK);
}
@@ -2110,7 +2112,6 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
if (ds->pos_tbl == NULL)
return (ARCHIVE_FATAL);
- lzx_huffman_free(&(ds->mt));
}
for (footer = 0; footer < 18; footer++)
@@ -2293,10 +2294,10 @@ lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
(br->cache_buffer << 48) |
((uint64_t)strm->next_in[1]) << 40 |
((uint64_t)strm->next_in[0]) << 32 |
- ((uint32_t)strm->next_in[3]) << 24 |
- ((uint32_t)strm->next_in[2]) << 16 |
- ((uint32_t)strm->next_in[5]) << 8 |
- (uint32_t)strm->next_in[4];
+ ((uint64_t)strm->next_in[3]) << 24 |
+ ((uint64_t)strm->next_in[2]) << 16 |
+ ((uint64_t)strm->next_in[5]) << 8 |
+ (uint64_t)strm->next_in[4];
strm->next_in += 6;
strm->avail_in -= 6;
br->cache_avail += 6 * 8;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_cpio.c b/src/libs/3rdparty/libarchive/archive_read_support_format_cpio.c
index 1c96e6ac1..9adcfd335 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_cpio.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_cpio.c
@@ -185,6 +185,8 @@ struct cpio {
struct archive_string_conv *opt_sconv;
struct archive_string_conv *sconv_default;
int init_default_conversion;
+
+ int option_pwb;
};
static int64_t atol16(const char *, unsigned);
@@ -343,6 +345,10 @@ archive_read_format_cpio_options(struct archive_read *a,
ret = ARCHIVE_FATAL;
}
return (ret);
+ } else if (strcmp(key, "pwb") == 0) {
+ if (val != NULL && val[0] != 0)
+ cpio->option_pwb = 1;
+ return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
@@ -435,7 +441,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
- 11) == 0) {
+ 10) == 0) {
/* TODO: Store file location of start of block. */
archive_clear_error(&a->archive);
return (ARCHIVE_EOF);
@@ -891,6 +897,12 @@ header_bin_le(struct archive_read *a, struct cpio *cpio,
archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256);
archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256);
archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256);
+ if (cpio->option_pwb) {
+ /* turn off random bits left over from V6 inode */
+ archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
+ if ((archive_entry_mode(entry) & AE_IFMT) == 0)
+ archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
+ }
archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256);
archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256);
archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256);
@@ -930,6 +942,12 @@ header_bin_be(struct archive_read *a, struct cpio *cpio,
archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
+ if (cpio->option_pwb) {
+ /* turn off random bits left over from V6 inode */
+ archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
+ if ((archive_entry_mode(entry) & AE_IFMT) == 0)
+ archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
+ }
archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
@@ -967,14 +985,14 @@ archive_read_format_cpio_cleanup(struct archive_read *a)
static int64_t
le4(const unsigned char *p)
{
- return ((p[0] << 16) + (((int64_t)p[1]) << 24) + (p[2] << 0) + (p[3] << 8));
+ return ((p[0] << 16) | (((int64_t)p[1]) << 24) | (p[2] << 0) | (p[3] << 8));
}
static int64_t
be4(const unsigned char *p)
{
- return ((((int64_t)p[0]) << 24) + (p[1] << 16) + (p[2] << 8) + (p[3]));
+ return ((((int64_t)p[0]) << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
}
/*
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c b/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c
index db14d41df..f5414be2a 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_iso9660.c
@@ -1007,7 +1007,8 @@ read_children(struct archive_read *a, struct file_info *parent)
p = b;
b += iso9660->logical_block_size;
step -= iso9660->logical_block_size;
- for (; *p != 0 && p < b && p + *p <= b; p += *p) {
+ for (; *p != 0 && p + DR_name_offset < b && p + *p <= b;
+ p += *p) {
struct file_info *child;
/* N.B.: these special directory identifiers
@@ -1756,7 +1757,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
size_t name_len;
const unsigned char *rr_start, *rr_end;
const unsigned char *p;
- size_t dr_len;
+ size_t dr_len = 0;
uint64_t fsize, offset;
int32_t location;
int flags;
@@ -1900,7 +1901,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
* NUMBER of RRIP "PX" extension.
* Note: Old mkisofs did not record that FILE SERIAL NUMBER
* in ISO images.
- * Note2: xorriso set 0 to the location of a symlink file.
+ * Note2: xorriso set 0 to the location of a symlink file.
*/
if (file->size == 0 && location >= 0) {
/* If file->size is zero, its location points wrong place,
@@ -1954,7 +1955,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
* made by makefs is not zero and its location is
* the same as those of next regular file. That is
* the same as hard like file and it causes unexpected
- * error.
+ * error.
*/
if (file->size > 0 &&
(file->mode & AE_IFMT) == AE_IFLNK) {
@@ -2746,7 +2747,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
* If directory entries all which are descendant of
* rr_moved are still remaining, expose their.
*/
- if (iso9660->re_files.first != NULL &&
+ if (iso9660->re_files.first != NULL &&
iso9660->rr_moved != NULL &&
iso9660->rr_moved->rr_moved_has_re_only)
/* Expose "rr_moved" entry. */
@@ -3179,11 +3180,11 @@ isodate17(const unsigned char *v)
static time_t
time_from_tm(struct tm *t)
{
-#if HAVE_TIMEGM
+#if HAVE__MKGMTIME
+ return _mkgmtime(t);
+#elif HAVE_TIMEGM
/* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE__MKGMTIME64
- return (_mkgmtime64(t));
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c b/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c
index bff0f01f4..1c64b2900 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_lha.c
@@ -739,7 +739,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
if (lha->directory || lha->compsize == 0)
lha->end_of_entry = 1;
- sprintf(lha->format_name, "lha -%c%c%c-",
+ snprintf(lha->format_name, sizeof(lha->format_name), "lha -%c%c%c-",
lha->method[0], lha->method[1], lha->method[2]);
a->archive.archive_format_name = lha->format_name;
@@ -1039,9 +1039,11 @@ lha_read_file_header_2(struct archive_read *a, struct lha *lha)
}
if (header_crc != lha->header_crc) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"LHa header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
return (err);
}
@@ -1107,9 +1109,11 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
return (err);
if (header_crc != lha->header_crc) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"LHa header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
return (err);
invalid:
@@ -1814,13 +1818,16 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
/* This if statement expects compiler optimization will
* remove the statement which will not be executed. */
#undef bswap16
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */
# define bswap16(x) _byteswap_ushort(x)
#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
/* GCC 4.8 and later has __builtin_bswap16() */
# define bswap16(x) __builtin_bswap16(x)
-#elif defined(__clang__)
-/* All clang versions have __builtin_bswap16() */
+#elif defined(__clang__) && __has_builtin(__builtin_bswap16)
+/* Newer clang versions have __builtin_bswap16() */
# define bswap16(x) __builtin_bswap16(x)
#else
# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))
@@ -2005,10 +2012,10 @@ lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br)
((uint64_t)strm->next_in[0]) << 48 |
((uint64_t)strm->next_in[1]) << 40 |
((uint64_t)strm->next_in[2]) << 32 |
- ((uint32_t)strm->next_in[3]) << 24 |
- ((uint32_t)strm->next_in[4]) << 16 |
- ((uint32_t)strm->next_in[5]) << 8 |
- (uint32_t)strm->next_in[6];
+ ((uint64_t)strm->next_in[3]) << 24 |
+ ((uint64_t)strm->next_in[4]) << 16 |
+ ((uint64_t)strm->next_in[5]) << 8 |
+ (uint64_t)strm->next_in[6];
strm->next_in += 7;
strm->avail_in -= 7;
br->cache_avail += 7 * 8;
@@ -2018,10 +2025,10 @@ lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br)
(br->cache_buffer << 48) |
((uint64_t)strm->next_in[0]) << 40 |
((uint64_t)strm->next_in[1]) << 32 |
- ((uint32_t)strm->next_in[2]) << 24 |
- ((uint32_t)strm->next_in[3]) << 16 |
- ((uint32_t)strm->next_in[4]) << 8 |
- (uint32_t)strm->next_in[5];
+ ((uint64_t)strm->next_in[2]) << 24 |
+ ((uint64_t)strm->next_in[3]) << 16 |
+ ((uint64_t)strm->next_in[4]) << 8 |
+ (uint64_t)strm->next_in[5];
strm->next_in += 6;
strm->avail_in -= 6;
br->cache_avail += 6 * 8;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c b/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c
index 93ba2959a..a5fa30e3c 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_mtree.c
@@ -408,7 +408,7 @@ next_line(struct archive_read *a,
*ravail = *avail;
*b += diff;
*avail -= diff;
- tested = len;/* Skip some bytes we already determinated. */
+ tested = len;/* Skip some bytes we already determined. */
len = get_line_size(*b + len, *avail - len, nl);
if (len >= 0)
len += tested;
@@ -692,7 +692,7 @@ detect_form(struct archive_read *a, int *is_form_d)
{
const char *p;
ssize_t avail, ravail;
- ssize_t detected_bytes = 0, len, nl;
+ ssize_t len, nl;
int entry_cnt = 0, multiline = 0;
int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
* (In this source we call it `form D') . */
@@ -728,8 +728,6 @@ detect_form(struct archive_read *a, int *is_form_d)
* character of previous line was '\' character. */
if (bid_keyword_list(p, len, 0, 0) <= 0)
break;
- if (multiline == 1)
- detected_bytes += len;
if (p[len-nl-1] != '\\') {
if (multiline == 1 &&
++entry_cnt >= MAX_BID_ENTRY)
@@ -745,7 +743,6 @@ detect_form(struct archive_read *a, int *is_form_d)
keywords = bid_entry(p, len, nl, &last_is_path);
if (keywords >= 0) {
- detected_bytes += len;
if (form_D == 0) {
if (last_is_path)
form_D = 1;
@@ -997,9 +994,11 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_entry *alt;
alt = (struct mtree_entry *)__archive_rb_tree_find_node(
&mtree->rbtree, entry->name);
- while (alt->next_dup)
- alt = alt->next_dup;
- alt->next_dup = entry;
+ if (alt != NULL) {
+ while (alt->next_dup)
+ alt = alt->next_dup;
+ alt->next_dup = entry;
+ }
}
}
@@ -1074,7 +1073,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
continue;
/* Non-printable characters are not allowed */
for (s = p;s < p + len - 1; s++) {
- if (!isprint(*s)) {
+ if (!isprint((unsigned char)*s) && *s != '\t') {
r = ARCHIVE_FATAL;
break;
}
@@ -1253,9 +1252,17 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd);
- if (mtree->fd == -1 &&
- (errno != ENOENT ||
- archive_strlen(&mtree->contents_name) > 0)) {
+ if (mtree->fd == -1 && (
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /*
+ * On Windows, attempting to open a file with an
+ * invalid name result in EINVAL (Error 22)
+ */
+ (errno != ENOENT && errno != EINVAL)
+#else
+ errno != ENOENT
+#endif
+ || archive_strlen(&mtree->contents_name) > 0)) {
archive_set_error(&a->archive, errno,
"Can't open %s", path);
r = ARCHIVE_WARN;
@@ -1273,7 +1280,13 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
mtree->fd = -1;
st = NULL;
}
- } else if (lstat(path, st) == -1) {
+ }
+#ifdef HAVE_LSTAT
+ else if (lstat(path, st) == -1)
+#else
+ else if (la_stat(path, st) == -1)
+#endif
+ {
st = NULL;
}
@@ -1629,11 +1642,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|| strcmp(key, "contents") == 0) {
parse_escapes(val, NULL);
archive_strcpy(&mtree->contents_name, val);
- break;
+ return (ARCHIVE_OK);
}
if (strcmp(key, "cksum") == 0)
- break;
- __LA_FALLTHROUGH;
+ return (ARCHIVE_OK);
+ break;
case 'd':
if (strcmp(key, "device") == 0) {
/* stat(2) st_rdev field, e.g. the major/minor IDs
@@ -1647,65 +1660,64 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_set_rdev(entry, dev);
return r;
}
- __LA_FALLTHROUGH;
+ break;
case 'f':
if (strcmp(key, "flags") == 0) {
*parsed_kws |= MTREE_HAS_FFLAGS;
archive_entry_copy_fflags_text(entry, val);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'g':
if (strcmp(key, "gid") == 0) {
*parsed_kws |= MTREE_HAS_GID;
archive_entry_set_gid(entry, mtree_atol(&val, 10));
- break;
+ return (ARCHIVE_OK);
}
if (strcmp(key, "gname") == 0) {
*parsed_kws |= MTREE_HAS_GNAME;
archive_entry_copy_gname(entry, val);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol(&val, 10));
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'l':
if (strcmp(key, "link") == 0) {
+ parse_escapes(val, NULL);
archive_entry_copy_symlink(entry, val);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'm':
if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) {
return parse_digest(a, entry, val,
ARCHIVE_ENTRY_DIGEST_MD5);
}
if (strcmp(key, "mode") == 0) {
- if (val[0] >= '0' && val[0] <= '7') {
- *parsed_kws |= MTREE_HAS_PERM;
- archive_entry_set_perm(entry,
- (mode_t)mtree_atol(&val, 8));
- } else {
+ if (val[0] < '0' || val[0] > '7') {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Symbolic or non-octal mode \"%s\" unsupported", val);
- return ARCHIVE_WARN;
+ return (ARCHIVE_WARN);
}
- break;
+ *parsed_kws |= MTREE_HAS_PERM;
+ archive_entry_set_perm(entry, (mode_t)mtree_atol(&val, 8));
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'n':
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
archive_entry_set_nlink(entry,
(unsigned int)mtree_atol(&val, 10));
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'r':
if (strcmp(key, "resdevice") == 0) {
/* stat(2) st_dev field, e.g. the device ID where the
@@ -1723,7 +1735,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
return parse_digest(a, entry, val,
ARCHIVE_ENTRY_DIGEST_RMD160);
}
- __LA_FALLTHROUGH;
+ break;
case 's':
if (strcmp(key, "sha1") == 0 ||
strcmp(key, "sha1digest") == 0) {
@@ -1747,9 +1759,9 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
if (strcmp(key, "size") == 0) {
archive_entry_set_size(entry, mtree_atol(&val, 10));
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 't':
if (strcmp(key, "tags") == 0) {
/*
@@ -1757,7 +1769,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
* Ignore the tags for now, but the interface
* should be extended to allow inclusion/exclusion.
*/
- break;
+ return (ARCHIVE_OK);
}
if (strcmp(key, "time") == 0) {
int64_t m;
@@ -1783,79 +1795,85 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
else if (m < my_time_t_min)
m = my_time_t_min;
archive_entry_set_mtime(entry, (time_t)m, ns);
- break;
+ return (ARCHIVE_OK);
}
if (strcmp(key, "type") == 0) {
switch (val[0]) {
case 'b':
if (strcmp(val, "block") == 0) {
- archive_entry_set_filetype(entry, AE_IFBLK);
- break;
+ *parsed_kws |= MTREE_HAS_TYPE;
+ archive_entry_set_filetype(entry,
+ AE_IFBLK);
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'c':
if (strcmp(val, "char") == 0) {
+ *parsed_kws |= MTREE_HAS_TYPE;
archive_entry_set_filetype(entry,
AE_IFCHR);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'd':
if (strcmp(val, "dir") == 0) {
+ *parsed_kws |= MTREE_HAS_TYPE;
archive_entry_set_filetype(entry,
AE_IFDIR);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'f':
if (strcmp(val, "fifo") == 0) {
+ *parsed_kws |= MTREE_HAS_TYPE;
archive_entry_set_filetype(entry,
AE_IFIFO);
- break;
+ return (ARCHIVE_OK);
}
if (strcmp(val, "file") == 0) {
+ *parsed_kws |= MTREE_HAS_TYPE;
archive_entry_set_filetype(entry,
AE_IFREG);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
case 'l':
if (strcmp(val, "link") == 0) {
+ *parsed_kws |= MTREE_HAS_TYPE;
archive_entry_set_filetype(entry,
AE_IFLNK);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
default:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Unrecognized file type \"%s\"; "
- "assuming \"file\"", val);
- archive_entry_set_filetype(entry, AE_IFREG);
- return (ARCHIVE_WARN);
+ break;
}
- *parsed_kws |= MTREE_HAS_TYPE;
- break;
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Unrecognized file type \"%s\"; "
+ "assuming \"file\"", val);
+ archive_entry_set_filetype(entry, AE_IFREG);
+ return (ARCHIVE_WARN);
}
- __LA_FALLTHROUGH;
+ break;
case 'u':
if (strcmp(key, "uid") == 0) {
*parsed_kws |= MTREE_HAS_UID;
archive_entry_set_uid(entry, mtree_atol(&val, 10));
- break;
+ return (ARCHIVE_OK);
}
if (strcmp(key, "uname") == 0) {
*parsed_kws |= MTREE_HAS_UNAME;
archive_entry_copy_uname(entry, val);
- break;
+ return (ARCHIVE_OK);
}
- __LA_FALLTHROUGH;
+ break;
default:
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unrecognized key %s=%s", key, val);
- return (ARCHIVE_WARN);
+ break;
}
- return (ARCHIVE_OK);
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Unrecognized key %s=%s", key, val);
+ return (ARCHIVE_WARN);
}
static int
@@ -2035,13 +2053,13 @@ mtree_atol(char **p, int base)
if (**p == '-') {
limit = INT64_MIN / base;
- last_digit_limit = INT64_MIN % base;
+ last_digit_limit = -(INT64_MIN % base);
++(*p);
l = 0;
digit = parsedigit(**p);
while (digit >= 0 && digit < base) {
- if (l < limit || (l == limit && digit > last_digit_limit))
+ if (l < limit || (l == limit && digit >= last_digit_limit))
return INT64_MIN;
l = (l * base) - digit;
digit = parsedigit(*++(*p));
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c
index 283a96044..16b6e6eed 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c
@@ -135,6 +135,16 @@
#define MAX_SYMBOL_LENGTH 0xF
#define MAX_SYMBOLS 20
+/* Virtual Machine Properties */
+#define VM_MEMORY_SIZE 0x40000
+#define VM_MEMORY_MASK (VM_MEMORY_SIZE - 1)
+#define PROGRAM_WORK_SIZE 0x3C000
+#define PROGRAM_GLOBAL_SIZE 0x2000
+#define PROGRAM_SYSTEM_GLOBAL_ADDRESS PROGRAM_WORK_SIZE
+#define PROGRAM_SYSTEM_GLOBAL_SIZE 0x40
+#define PROGRAM_USER_GLOBAL_ADDRESS (PROGRAM_SYSTEM_GLOBAL_ADDRESS + PROGRAM_SYSTEM_GLOBAL_SIZE)
+#define PROGRAM_USER_GLOBAL_SIZE (PROGRAM_GLOBAL_SIZE - PROGRAM_SYSTEM_GLOBAL_SIZE)
+
/*
* Considering L1,L2 cache miss and a calling of write system-call,
* the best size of the output buffer(uncompressed buffer) is 128K.
@@ -213,6 +223,69 @@ struct data_block_offsets
int64_t end_offset;
};
+struct rar_program_code
+{
+ uint8_t *staticdata;
+ uint32_t staticdatalen;
+ uint8_t *globalbackup;
+ uint32_t globalbackuplen;
+ uint64_t fingerprint;
+ uint32_t usagecount;
+ uint32_t oldfilterlength;
+ struct rar_program_code *next;
+};
+
+struct rar_filter
+{
+ struct rar_program_code *prog;
+ uint32_t initialregisters[8];
+ uint8_t *globaldata;
+ uint32_t globaldatalen;
+ size_t blockstartpos;
+ uint32_t blocklength;
+ uint32_t filteredblockaddress;
+ uint32_t filteredblocklength;
+ struct rar_filter *next;
+};
+
+struct memory_bit_reader
+{
+ const uint8_t *bytes;
+ size_t length;
+ size_t offset;
+ uint64_t bits;
+ int available;
+ int at_eof;
+};
+
+struct rar_virtual_machine
+{
+ uint32_t registers[8];
+ uint8_t memory[VM_MEMORY_SIZE + sizeof(uint32_t)];
+};
+
+struct rar_filters
+{
+ struct rar_virtual_machine *vm;
+ struct rar_program_code *progs;
+ struct rar_filter *stack;
+ int64_t filterstart;
+ uint32_t lastfilternum;
+ int64_t lastend;
+ uint8_t *bytes;
+ size_t bytes_ready;
+};
+
+struct audio_state
+{
+ int8_t weight[5];
+ int16_t delta[4];
+ int8_t lastdelta;
+ int error[11];
+ int count;
+ uint8_t lastbyte;
+};
+
struct rar
{
/* Entries from main RAR header */
@@ -273,15 +346,16 @@ struct rar
struct huffman_code lengthcode;
unsigned char lengthtable[HUFFMAN_TABLE_SIZE];
struct lzss lzss;
- char output_last_match;
unsigned int lastlength;
unsigned int lastoffset;
unsigned int oldoffset[4];
unsigned int lastlowoffset;
unsigned int numlowoffsetrepeats;
- int64_t filterstart;
char start_new_table;
+ /* Filters */
+ struct rar_filters filters;
+
/* PPMd Variant H members */
char ppmd_valid;
char ppmd_eod;
@@ -343,23 +417,43 @@ static int read_symlink_stored(struct archive_read *, struct archive_entry *,
static int read_data_stored(struct archive_read *, const void **, size_t *,
int64_t *);
static int read_data_compressed(struct archive_read *, const void **, size_t *,
- int64_t *, size_t);
+ int64_t *, size_t);
static int rar_br_preparation(struct archive_read *, struct rar_br *);
static int parse_codes(struct archive_read *);
static void free_codes(struct archive_read *);
static int read_next_symbol(struct archive_read *, struct huffman_code *);
static int create_code(struct archive_read *, struct huffman_code *,
- unsigned char *, int, char);
+ unsigned char *, int, char);
static int add_value(struct archive_read *, struct huffman_code *, int, int,
int);
static int new_node(struct huffman_code *);
static int make_table(struct archive_read *, struct huffman_code *);
static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
struct huffman_table_entry *, int, int);
-static int64_t expand(struct archive_read *, int64_t);
-static int copy_from_lzss_window(struct archive_read *, const void **,
- int64_t, int);
+static int expand(struct archive_read *, int64_t *);
+static int copy_from_lzss_window_to_unp(struct archive_read *, const void **,
+ int64_t, int);
static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
+static int parse_filter(struct archive_read *, const uint8_t *, uint16_t,
+ uint8_t);
+static int run_filters(struct archive_read *);
+static void clear_filters(struct rar_filters *);
+static struct rar_filter *create_filter(struct rar_program_code *,
+ const uint8_t *, uint32_t,
+ uint32_t[8], size_t, uint32_t);
+static void delete_filter(struct rar_filter *filter);
+static struct rar_program_code *compile_program(const uint8_t *, size_t);
+static void delete_program_code(struct rar_program_code *prog);
+static uint32_t membr_next_rarvm_number(struct memory_bit_reader *br);
+static inline uint32_t membr_bits(struct memory_bit_reader *br, int bits);
+static int membr_fill(struct memory_bit_reader *br, int bits);
+static int read_filter(struct archive_read *, int64_t *);
+static int rar_decode_byte(struct archive_read*, uint8_t *);
+static int execute_filter(struct archive_read*, struct rar_filter *,
+ struct rar_virtual_machine *, size_t);
+static int copy_from_lzss_window(struct archive_read *, void *, int64_t, int);
+static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
+static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
/*
* Bit stream reader.
@@ -913,9 +1007,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
__archive_read_consume(a, skip);
break;
@@ -958,22 +1054,24 @@ archive_read_format_rar_read_header(struct archive_read *a,
crc32_val = 0;
while (skip > 0) {
size_t to_read = skip;
- ssize_t did_read;
- if (to_read > 32 * 1024) {
+ if (to_read > 32 * 1024)
to_read = 32 * 1024;
- }
- if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
+ if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Bad RAR file");
return (ARCHIVE_FATAL);
}
p = h;
- crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
- __archive_read_consume(a, did_read);
- skip -= did_read;
+ crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned int)to_read);
+ __archive_read_consume(a, to_read);
+ skip -= to_read;
}
if ((crc32_val & 0xffff) != crc32_expected) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
if (head_type == ENDARC_HEAD)
return (ARCHIVE_EOF);
@@ -1244,6 +1342,7 @@ archive_read_format_rar_cleanup(struct archive_read *a)
rar = (struct rar *)(a->format->data);
free_codes(a);
+ clear_filters(&rar->filters);
free(rar->filename);
free(rar->filename_save);
free(rar->dbo);
@@ -1337,9 +1436,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
/* File Header CRC check. */
crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7));
if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
+#endif
}
/* If no CRC error, Go on parsing File Header. */
p = h;
@@ -1662,6 +1763,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->ppmd_valid = rar->ppmd_eod = 0;
+ rar->filters.filterstart = INT64_MAX;
/* Don't set any archive entries for non-file header types */
if (head_type == NEWSUB_HEAD)
@@ -1728,13 +1830,9 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
struct tm *tm;
time_t t;
long nsec;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (p + 2 > endp)
return (-1);
@@ -1766,15 +1864,10 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
p++;
}
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &t) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&t, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = t;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&t);
#endif
@@ -1856,9 +1949,11 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
*size = 0;
*offset = rar->offset;
if (rar->file_crc != rar->crc_calculated) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"File CRC error");
return (ARCHIVE_FATAL);
+#endif
}
rar->entry_eof = 1;
return (ARCHIVE_EOF);
@@ -1886,13 +1981,13 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
static int
read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
- int64_t *offset, size_t looper)
+ int64_t *offset, size_t looper)
{
if (looper++ > MAX_COMPRESS_DEPTH)
return (ARCHIVE_FATAL);
struct rar *rar;
- int64_t start, end, actualend;
+ int64_t start, end;
size_t bs;
int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i;
@@ -1901,6 +1996,33 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
do {
if (!rar->valid)
return (ARCHIVE_FATAL);
+
+ if (rar->filters.bytes_ready > 0)
+ {
+ /* Flush unp_buffer first */
+ if (rar->unp_offset > 0)
+ {
+ *buff = rar->unp_buffer;
+ *size = rar->unp_offset;
+ rar->unp_offset = 0;
+ *offset = rar->offset_outgoing;
+ rar->offset_outgoing += *size;
+ }
+ else
+ {
+ *buff = rar->filters.bytes;
+ *size = rar->filters.bytes_ready;
+
+ rar->offset += *size;
+ *offset = rar->offset_outgoing;
+ rar->offset_outgoing += *size;
+
+ rar->filters.bytes_ready -= *size;
+ rar->filters.bytes += *size;
+ }
+ goto ending_block;
+ }
+
if (rar->ppmd_eod ||
(rar->dictionary_size && rar->offset >= rar->unp_size))
{
@@ -1922,9 +2044,11 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*size = 0;
*offset = rar->offset;
if (rar->file_crc != rar->crc_calculated) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"File CRC error");
return (ARCHIVE_FATAL);
+#endif
}
rar->entry_eof = 1;
return (ARCHIVE_EOF);
@@ -1936,7 +2060,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
bs = rar->unp_buffer_size - rar->unp_offset;
else
bs = (size_t)rar->bytes_uncopied;
- ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
+ ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@@ -1954,6 +2078,13 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
continue;
}
+ if (rar->filters.lastend == rar->filters.filterstart)
+ {
+ if (!run_filters(a))
+ return (ARCHIVE_FATAL);
+ continue;
+ }
+
if (!rar->br.next_in &&
(ret = rar_br_preparation(a, &(rar->br))) < ARCHIVE_WARN)
return (ret);
@@ -2045,13 +2176,17 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
{
start = rar->offset;
end = start + rar->dictionary_size;
- rar->filterstart = INT64_MAX;
+ if (rar->filters.filterstart < end) {
+ end = rar->filters.filterstart;
+ }
- if ((actualend = expand(a, end)) < 0)
- return ((int)actualend);
+ ret = expand(a, &end);
+ if (ret != ARCHIVE_OK)
+ return (ret);
- rar->bytes_uncopied = actualend - start;
- if (rar->bytes_uncopied == 0) {
+ rar->bytes_uncopied = end - start;
+ rar->filters.lastend = end;
+ if (rar->filters.lastend != rar->filters.filterstart && rar->bytes_uncopied == 0) {
/* Broken RAR files cause this case.
* NOTE: If this case were possible on a normal RAR file
* we would find out where it was actually bad and
@@ -2065,7 +2200,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
bs = rar->unp_buffer_size - rar->unp_offset;
else
bs = (size_t)rar->bytes_uncopied;
- ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
+ ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@@ -2080,6 +2215,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*size = rar->unp_buffer_size;
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
+ending_block:
/* Calculate File CRC. */
rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
return ret;
@@ -2691,8 +2827,8 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
return ret;
}
-static int64_t
-expand(struct archive_read *a, int64_t end)
+static int
+expand(struct archive_read *a, int64_t *end)
{
static const unsigned char lengthbases[] =
{ 0, 1, 2, 3, 4, 5, 6,
@@ -2739,25 +2875,22 @@ expand(struct archive_read *a, int64_t end)
struct rar *rar = (struct rar *)(a->format->data);
struct rar_br *br = &(rar->br);
- if (rar->filterstart < end)
- end = rar->filterstart;
+ if (rar->filters.filterstart < *end)
+ *end = rar->filters.filterstart;
while (1)
{
- if (rar->output_last_match &&
- lzss_position(&rar->lzss) + rar->lastlength <= end)
- {
- lzss_emit_match(rar, rar->lastoffset, rar->lastlength);
- rar->output_last_match = 0;
+ if(lzss_position(&rar->lzss) >= *end) {
+ return (ARCHIVE_OK);
}
- if(rar->is_ppmd_block || rar->output_last_match ||
- lzss_position(&rar->lzss) >= end)
- return lzss_position(&rar->lzss);
+ if(rar->is_ppmd_block) {
+ *end = lzss_position(&rar->lzss);
+ return (ARCHIVE_OK);
+ }
if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
return (ARCHIVE_FATAL);
- rar->output_last_match = 0;
if (symbol < 256)
{
@@ -2778,7 +2911,8 @@ expand(struct archive_read *a, int64_t end)
goto truncated_data;
rar->start_new_table = rar_br_bits(br, 1);
rar_br_consume(br, 1);
- return lzss_position(&rar->lzss);
+ *end = lzss_position(&rar->lzss);
+ return (ARCHIVE_OK);
}
else
{
@@ -2789,9 +2923,9 @@ expand(struct archive_read *a, int64_t end)
}
else if(symbol==257)
{
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Parsing filters is unsupported.");
- return (ARCHIVE_FAILED);
+ if (!read_filter(a, end))
+ return (ARCHIVE_FATAL);
+ continue;
}
else if(symbol==258)
{
@@ -2864,7 +2998,7 @@ expand(struct archive_read *a, int64_t end)
goto truncated_data;
offs += rar_br_bits(br, offsetbits[offssymbol] - 4) << 4;
rar_br_consume(br, offsetbits[offssymbol] - 4);
- }
+ }
if(rar->numlowoffsetrepeats > 0)
{
@@ -2908,7 +3042,8 @@ expand(struct archive_read *a, int64_t end)
rar->lastoffset = offs;
rar->lastlength = len;
- rar->output_last_match = 1;
+
+ lzss_emit_match(rar, rar->lastoffset, rar->lastlength);
}
truncated_data:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -2922,8 +3057,31 @@ bad_data:
}
static int
-copy_from_lzss_window(struct archive_read *a, const void **buffer,
- int64_t startpos, int length)
+copy_from_lzss_window(struct archive_read *a, void *buffer,
+ int64_t startpos, int length)
+{
+ int windowoffs, firstpart;
+ struct rar *rar = (struct rar *)(a->format->data);
+
+ windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
+ firstpart = lzss_size(&rar->lzss) - windowoffs;
+ if (firstpart < 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Bad RAR file data");
+ return (ARCHIVE_FATAL);
+ }
+ if (firstpart < length) {
+ memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
+ memcpy(buffer, &rar->lzss.window[0], length - firstpart);
+ } else {
+ memcpy(buffer, &rar->lzss.window[windowoffs], length);
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer,
+ int64_t startpos, int length)
{
int windowoffs, firstpart;
struct rar *rar = (struct rar *)(a->format->data);
@@ -3003,3 +3161,628 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
}
return h;
}
+
+static int
+parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint8_t flags)
+{
+ struct rar *rar = (struct rar *)(a->format->data);
+ struct rar_filters *filters = &rar->filters;
+
+ struct memory_bit_reader br = { 0 };
+ struct rar_program_code *prog;
+ struct rar_filter *filter, **nextfilter;
+
+ uint32_t numprogs, num, blocklength, globaldatalen;
+ uint8_t *globaldata;
+ size_t blockstartpos;
+ uint32_t registers[8] = { 0 };
+ uint32_t i;
+
+ br.bytes = bytes;
+ br.length = length;
+
+ numprogs = 0;
+ for (prog = filters->progs; prog; prog = prog->next)
+ numprogs++;
+
+ if ((flags & 0x80))
+ {
+ num = membr_next_rarvm_number(&br);
+ if (num == 0)
+ {
+ delete_filter(filters->stack);
+ filters->stack = NULL;
+ delete_program_code(filters->progs);
+ filters->progs = NULL;
+ }
+ else
+ num--;
+ if (num > numprogs) {
+ return 0;
+ }
+ filters->lastfilternum = num;
+ }
+ else
+ num = filters->lastfilternum;
+
+ prog = filters->progs;
+ for (i = 0; i < num; i++)
+ prog = prog->next;
+ if (prog)
+ prog->usagecount++;
+
+ blockstartpos = membr_next_rarvm_number(&br) + (size_t)lzss_position(&rar->lzss);
+ if ((flags & 0x40))
+ blockstartpos += 258;
+ if ((flags & 0x20))
+ blocklength = membr_next_rarvm_number(&br);
+ else
+ blocklength = prog ? prog->oldfilterlength : 0;
+
+ registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
+ registers[4] = blocklength;
+ registers[5] = prog ? prog->usagecount : 0;
+ registers[7] = VM_MEMORY_SIZE;
+
+ if ((flags & 0x10))
+ {
+ uint8_t mask = (uint8_t)membr_bits(&br, 7);
+ for (i = 0; i < 7; i++)
+ if ((mask & (1 << i)))
+ registers[i] = membr_next_rarvm_number(&br);
+ }
+
+ if (!prog)
+ {
+ uint32_t len = membr_next_rarvm_number(&br);
+ uint8_t *bytecode;
+ struct rar_program_code **next;
+
+ if (len == 0 || len > 0x10000)
+ return 0;
+ bytecode = malloc(len);
+ if (!bytecode)
+ return 0;
+ for (i = 0; i < len; i++)
+ bytecode[i] = (uint8_t)membr_bits(&br, 8);
+ prog = compile_program(bytecode, len);
+ if (!prog) {
+ free(bytecode);
+ return 0;
+ }
+ free(bytecode);
+ next = &filters->progs;
+ while (*next)
+ next = &(*next)->next;
+ *next = prog;
+ }
+ prog->oldfilterlength = blocklength;
+
+ globaldata = NULL;
+ globaldatalen = 0;
+ if ((flags & 0x08))
+ {
+ globaldatalen = membr_next_rarvm_number(&br);
+ if (globaldatalen > PROGRAM_USER_GLOBAL_SIZE)
+ return 0;
+ globaldata = malloc(globaldatalen + PROGRAM_SYSTEM_GLOBAL_SIZE);
+ if (!globaldata)
+ return 0;
+ for (i = 0; i < globaldatalen; i++)
+ globaldata[i + PROGRAM_SYSTEM_GLOBAL_SIZE] = (uint8_t)membr_bits(&br, 8);
+ }
+
+ if (br.at_eof)
+ {
+ free(globaldata);
+ return 0;
+ }
+
+ filter = create_filter(prog, globaldata, globaldatalen, registers, blockstartpos, blocklength);
+ free(globaldata);
+ if (!filter)
+ return 0;
+
+ for (i = 0; i < 7; i++)
+ archive_le32enc(&filter->globaldata[i * 4], registers[i]);
+ archive_le32enc(&filter->globaldata[0x1C], blocklength);
+ archive_le32enc(&filter->globaldata[0x20], 0);
+ archive_le32enc(&filter->globaldata[0x2C], prog->usagecount);
+
+ nextfilter = &filters->stack;
+ while (*nextfilter)
+ nextfilter = &(*nextfilter)->next;
+ *nextfilter = filter;
+
+ if (!filters->stack->next)
+ filters->filterstart = blockstartpos;
+
+ return 1;
+}
+
+static struct rar_filter *
+create_filter(struct rar_program_code *prog, const uint8_t *globaldata, uint32_t globaldatalen, uint32_t registers[8], size_t startpos, uint32_t length)
+{
+ struct rar_filter *filter;
+
+ filter = calloc(1, sizeof(*filter));
+ if (!filter)
+ return NULL;
+ filter->prog = prog;
+ filter->globaldatalen = globaldatalen > PROGRAM_SYSTEM_GLOBAL_SIZE ? globaldatalen : PROGRAM_SYSTEM_GLOBAL_SIZE;
+ filter->globaldata = calloc(1, filter->globaldatalen);
+ if (!filter->globaldata)
+ return NULL;
+ if (globaldata)
+ memcpy(filter->globaldata, globaldata, globaldatalen);
+ if (registers)
+ memcpy(filter->initialregisters, registers, sizeof(filter->initialregisters));
+ filter->blockstartpos = startpos;
+ filter->blocklength = length;
+
+ return filter;
+}
+
+static int
+run_filters(struct archive_read *a)
+{
+ struct rar *rar = (struct rar *)(a->format->data);
+ struct rar_filters *filters = &rar->filters;
+ struct rar_filter *filter = filters->stack;
+ struct rar_filter *f;
+ size_t start, end;
+ int64_t tend;
+ uint32_t lastfilteraddress;
+ uint32_t lastfilterlength;
+ int ret;
+
+ if (filters == NULL || filter == NULL)
+ return (0);
+
+ start = filters->filterstart;
+ end = start + filter->blocklength;
+
+ filters->filterstart = INT64_MAX;
+ tend = (int64_t)end;
+ ret = expand(a, &tend);
+ if (ret != ARCHIVE_OK)
+ return 0;
+
+ /* Check if filter stack was modified in expand() */
+ ret = ARCHIVE_FATAL;
+ f = filters->stack;
+ while (f)
+ {
+ if (f == filter)
+ {
+ ret = ARCHIVE_OK;
+ break;
+ }
+ f = f->next;
+ }
+ if (ret != ARCHIVE_OK)
+ return 0;
+
+ if (tend < 0)
+ return 0;
+ end = (size_t)tend;
+ if (end != start + filter->blocklength)
+ return 0;
+
+ if (!filters->vm)
+ {
+ filters->vm = calloc(1, sizeof(*filters->vm));
+ if (!filters->vm)
+ return 0;
+ }
+
+ ret = copy_from_lzss_window(a, filters->vm->memory, start, filter->blocklength);
+ if (ret != ARCHIVE_OK)
+ return 0;
+ if (!execute_filter(a, filter, filters->vm, rar->offset))
+ return 0;
+
+ lastfilteraddress = filter->filteredblockaddress;
+ lastfilterlength = filter->filteredblocklength;
+ filters->stack = filter->next;
+ filter->next = NULL;
+ delete_filter(filter);
+
+ while ((filter = filters->stack) != NULL && (int64_t)filter->blockstartpos == filters->filterstart && filter->blocklength == lastfilterlength)
+ {
+ memmove(&filters->vm->memory[0], &filters->vm->memory[lastfilteraddress], lastfilterlength);
+ if (!execute_filter(a, filter, filters->vm, rar->offset))
+ return 0;
+
+ lastfilteraddress = filter->filteredblockaddress;
+ lastfilterlength = filter->filteredblocklength;
+ filters->stack = filter->next;
+ filter->next = NULL;
+ delete_filter(filter);
+ }
+
+ if (filters->stack)
+ {
+ if (filters->stack->blockstartpos < end)
+ return 0;
+ filters->filterstart = filters->stack->blockstartpos;
+ }
+
+ filters->lastend = end;
+ filters->bytes = &filters->vm->memory[lastfilteraddress];
+ filters->bytes_ready = lastfilterlength;
+
+ return 1;
+}
+
+static struct rar_program_code *
+compile_program(const uint8_t *bytes, size_t length)
+{
+ struct memory_bit_reader br = { 0 };
+ struct rar_program_code *prog;
+ // uint32_t instrcount = 0;
+ uint8_t xor;
+ size_t i;
+
+ xor = 0;
+ for (i = 1; i < length; i++)
+ xor ^= bytes[i];
+ if (!length || xor != bytes[0])
+ return NULL;
+
+ br.bytes = bytes;
+ br.length = length;
+ br.offset = 1;
+
+ prog = calloc(1, sizeof(*prog));
+ if (!prog)
+ return NULL;
+ prog->fingerprint = crc32(0, bytes, (unsigned int)length) | ((uint64_t)length << 32);
+
+ if (membr_bits(&br, 1))
+ {
+ prog->staticdatalen = membr_next_rarvm_number(&br) + 1;
+ prog->staticdata = malloc(prog->staticdatalen);
+ if (!prog->staticdata)
+ {
+ delete_program_code(prog);
+ return NULL;
+ }
+ for (i = 0; i < prog->staticdatalen; i++)
+ prog->staticdata[i] = (uint8_t)membr_bits(&br, 8);
+ }
+
+ return prog;
+}
+
+static void
+delete_filter(struct rar_filter *filter)
+{
+ while (filter)
+ {
+ struct rar_filter *next = filter->next;
+ free(filter->globaldata);
+ free(filter);
+ filter = next;
+ }
+}
+
+static void
+clear_filters(struct rar_filters *filters)
+{
+ delete_filter(filters->stack);
+ delete_program_code(filters->progs);
+ free(filters->vm);
+}
+
+static void
+delete_program_code(struct rar_program_code *prog)
+{
+ while (prog)
+ {
+ struct rar_program_code *next = prog->next;
+ free(prog->staticdata);
+ free(prog->globalbackup);
+ free(prog);
+ prog = next;
+ }
+}
+
+static uint32_t
+membr_next_rarvm_number(struct memory_bit_reader *br)
+{
+ uint32_t val;
+ switch (membr_bits(br, 2))
+ {
+ case 0:
+ return membr_bits(br, 4);
+ case 1:
+ val = membr_bits(br, 8);
+ if (val >= 16)
+ return val;
+ return 0xFFFFFF00 | (val << 4) | membr_bits(br, 4);
+ case 2:
+ return membr_bits(br, 16);
+ default:
+ return membr_bits(br, 32);
+ }
+}
+
+static inline uint32_t
+membr_bits(struct memory_bit_reader *br, int bits)
+{
+ if (bits > br->available && (br->at_eof || !membr_fill(br, bits)))
+ return 0;
+ return (uint32_t)((br->bits >> (br->available -= bits)) & (((uint64_t)1 << bits) - 1));
+}
+
+static int
+membr_fill(struct memory_bit_reader *br, int bits)
+{
+ while (br->available < bits && br->offset < br->length)
+ {
+ br->bits = (br->bits << 8) | br->bytes[br->offset++];
+ br->available += 8;
+ }
+ if (bits > br->available)
+ {
+ br->at_eof = 1;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+read_filter(struct archive_read *a, int64_t *end)
+{
+ struct rar *rar = (struct rar *)(a->format->data);
+ uint8_t flags, val, *code;
+ uint16_t length, i;
+
+ if (!rar_decode_byte(a, &flags))
+ return 0;
+ length = (flags & 0x07) + 1;
+ if (length == 7)
+ {
+ if (!rar_decode_byte(a, &val))
+ return 0;
+ length = val + 7;
+ }
+ else if (length == 8)
+ {
+ if (!rar_decode_byte(a, &val))
+ return 0;
+ length = val << 8;
+ if (!rar_decode_byte(a, &val))
+ return 0;
+ length |= val;
+ }
+
+ code = malloc(length);
+ if (!code)
+ return 0;
+ for (i = 0; i < length; i++)
+ {
+ if (!rar_decode_byte(a, &code[i]))
+ {
+ free(code);
+ return 0;
+ }
+ }
+ if (!parse_filter(a, code, length, flags))
+ {
+ free(code);
+ return 0;
+ }
+ free(code);
+
+ if (rar->filters.filterstart < *end)
+ *end = rar->filters.filterstart;
+
+ return 1;
+}
+
+static int
+execute_filter_delta(struct rar_filter *filter, struct rar_virtual_machine *vm)
+{
+ uint32_t length = filter->initialregisters[4];
+ uint32_t numchannels = filter->initialregisters[0];
+ uint8_t *src, *dst;
+ uint32_t i, idx;
+
+ if (length > PROGRAM_WORK_SIZE / 2)
+ return 0;
+
+ src = &vm->memory[0];
+ dst = &vm->memory[length];
+ for (i = 0; i < numchannels; i++)
+ {
+ uint8_t lastbyte = 0;
+ for (idx = i; idx < length; idx += numchannels)
+ lastbyte = dst[idx] = lastbyte - *src++;
+ }
+
+ filter->filteredblockaddress = length;
+ filter->filteredblocklength = length;
+
+ return 1;
+}
+
+static int
+execute_filter_e8(struct rar_filter *filter, struct rar_virtual_machine *vm, size_t pos, int e9also)
+{
+ uint32_t length = filter->initialregisters[4];
+ uint32_t filesize = 0x1000000;
+ uint32_t i;
+
+ if (length > PROGRAM_WORK_SIZE || length < 4)
+ return 0;
+
+ for (i = 0; i <= length - 5; i++)
+ {
+ if (vm->memory[i] == 0xE8 || (e9also && vm->memory[i] == 0xE9))
+ {
+ uint32_t currpos = (uint32_t)pos + i + 1;
+ int32_t address = (int32_t)vm_read_32(vm, i + 1);
+ if (address < 0 && currpos >= (uint32_t)-address)
+ vm_write_32(vm, i + 1, address + filesize);
+ else if (address >= 0 && (uint32_t)address < filesize)
+ vm_write_32(vm, i + 1, address - currpos);
+ i += 4;
+ }
+ }
+
+ filter->filteredblockaddress = 0;
+ filter->filteredblocklength = length;
+
+ return 1;
+}
+
+static int
+execute_filter_rgb(struct rar_filter *filter, struct rar_virtual_machine *vm)
+{
+ uint32_t stride = filter->initialregisters[0];
+ uint32_t byteoffset = filter->initialregisters[1];
+ uint32_t blocklength = filter->initialregisters[4];
+ uint8_t *src, *dst;
+ uint32_t i, j;
+
+ if (blocklength > PROGRAM_WORK_SIZE / 2 || stride > blocklength)
+ return 0;
+
+ src = &vm->memory[0];
+ dst = &vm->memory[blocklength];
+ for (i = 0; i < 3; i++) {
+ uint8_t byte = 0;
+ uint8_t *prev = dst + i - stride;
+ for (j = i; j < blocklength; j += 3)
+ {
+ if (prev >= dst)
+ {
+ uint32_t delta1 = abs(prev[3] - prev[0]);
+ uint32_t delta2 = abs(byte - prev[0]);
+ uint32_t delta3 = abs(prev[3] - prev[0] + byte - prev[0]);
+ if (delta1 > delta2 || delta1 > delta3)
+ byte = delta2 <= delta3 ? prev[3] : prev[0];
+ }
+ byte -= *src++;
+ dst[j] = byte;
+ prev += 3;
+ }
+ }
+ for (i = byteoffset; i < blocklength - 2; i += 3)
+ {
+ dst[i] += dst[i + 1];
+ dst[i + 2] += dst[i + 1];
+ }
+
+ filter->filteredblockaddress = blocklength;
+ filter->filteredblocklength = blocklength;
+
+ return 1;
+}
+
+static int
+execute_filter_audio(struct rar_filter *filter, struct rar_virtual_machine *vm)
+{
+ uint32_t length = filter->initialregisters[4];
+ uint32_t numchannels = filter->initialregisters[0];
+ uint8_t *src, *dst;
+ uint32_t i, j;
+
+ if (length > PROGRAM_WORK_SIZE / 2)
+ return 0;
+
+ src = &vm->memory[0];
+ dst = &vm->memory[length];
+ for (i = 0; i < numchannels; i++)
+ {
+ struct audio_state state;
+ memset(&state, 0, sizeof(state));
+ for (j = i; j < length; j += numchannels)
+ {
+ int8_t delta = (int8_t)*src++;
+ uint8_t predbyte, byte;
+ int prederror;
+ state.delta[2] = state.delta[1];
+ state.delta[1] = state.lastdelta - state.delta[0];
+ state.delta[0] = state.lastdelta;
+ predbyte = ((8 * state.lastbyte + state.weight[0] * state.delta[0] + state.weight[1] * state.delta[1] + state.weight[2] * state.delta[2]) >> 3) & 0xFF;
+ byte = (predbyte - delta) & 0xFF;
+ prederror = delta << 3;
+ state.error[0] += abs(prederror);
+ state.error[1] += abs(prederror - state.delta[0]); state.error[2] += abs(prederror + state.delta[0]);
+ state.error[3] += abs(prederror - state.delta[1]); state.error[4] += abs(prederror + state.delta[1]);
+ state.error[5] += abs(prederror - state.delta[2]); state.error[6] += abs(prederror + state.delta[2]);
+ state.lastdelta = (int8_t)(byte - state.lastbyte);
+ dst[j] = state.lastbyte = byte;
+ if (!(state.count++ & 0x1F))
+ {
+ uint8_t k, idx = 0;
+ for (k = 1; k < 7; k++)
+ {
+ if (state.error[k] < state.error[idx])
+ idx = k;
+ }
+ memset(state.error, 0, sizeof(state.error));
+ switch (idx)
+ {
+ case 1: if (state.weight[0] >= -16) state.weight[0]--; break;
+ case 2: if (state.weight[0] < 16) state.weight[0]++; break;
+ case 3: if (state.weight[1] >= -16) state.weight[1]--; break;
+ case 4: if (state.weight[1] < 16) state.weight[1]++; break;
+ case 5: if (state.weight[2] >= -16) state.weight[2]--; break;
+ case 6: if (state.weight[2] < 16) state.weight[2]++; break;
+ }
+ }
+ }
+ }
+
+ filter->filteredblockaddress = length;
+ filter->filteredblocklength = length;
+
+ return 1;
+}
+
+
+static int
+execute_filter(struct archive_read *a, struct rar_filter *filter, struct rar_virtual_machine *vm, size_t pos)
+{
+ if (filter->prog->fingerprint == 0x1D0E06077D)
+ return execute_filter_delta(filter, vm);
+ if (filter->prog->fingerprint == 0x35AD576887)
+ return execute_filter_e8(filter, vm, pos, 0);
+ if (filter->prog->fingerprint == 0x393CD7E57E)
+ return execute_filter_e8(filter, vm, pos, 1);
+ if (filter->prog->fingerprint == 0x951C2C5DC8)
+ return execute_filter_rgb(filter, vm);
+ if (filter->prog->fingerprint == 0xD8BC85E701)
+ return execute_filter_audio(filter, vm);
+
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "No support for RAR VM program filter");
+ return 0;
+}
+
+static int
+rar_decode_byte(struct archive_read *a, uint8_t *byte)
+{
+ struct rar *rar = (struct rar *)(a->format->data);
+ struct rar_br *br = &(rar->br);
+ if (!rar_br_read_ahead(a, br, 8))
+ return 0;
+ *byte = (uint8_t)rar_br_bits(br, 8);
+ rar_br_consume(br, 8);
+ return 1;
+}
+
+static inline void
+vm_write_32(struct rar_virtual_machine* vm, size_t offset, uint32_t u32)
+{
+ archive_le32enc(vm->memory + offset, u32);
+}
+
+static inline uint32_t
+vm_read_32(struct rar_virtual_machine* vm, size_t offset)
+{
+ return archive_le32dec(vm->memory + offset);
+}
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c b/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c
index 58a61d1bc..1f9099439 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_rar5.c
@@ -632,7 +632,7 @@ static int run_arm_filter(struct rar5* rar, struct filter_info* flt) {
/* 0xEB = ARM's BL (branch + link) instruction. */
offset = read_filter_data(rar,
(rar->cstate.solid_offset + flt->block_start + i) &
- rar->cstate.window_mask) & 0x00ffffff;
+ (uint32_t)rar->cstate.window_mask) & 0x00ffffff;
offset -= (uint32_t) ((i + flt->block_start) / 4);
offset = (offset & 0x00ffffff) | 0xeb000000;
@@ -1012,7 +1012,16 @@ static int read_var_sized(struct archive_read* a, size_t* pvalue,
return ret;
}
-static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
+static int read_bits_32(struct archive_read* a, struct rar5* rar,
+ const uint8_t* p, uint32_t* value)
+{
+ if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_PROGRAMMER,
+ "Premature end of stream during extraction of data (#1)");
+ return ARCHIVE_FATAL;
+ }
+
uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24;
bits |= p[rar->bits.in_addr + 1] << 16;
bits |= p[rar->bits.in_addr + 2] << 8;
@@ -1023,7 +1032,16 @@ static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
return ARCHIVE_OK;
}
-static int read_bits_16(struct rar5* rar, const uint8_t* p, uint16_t* value) {
+static int read_bits_16(struct archive_read* a, struct rar5* rar,
+ const uint8_t* p, uint16_t* value)
+{
+ if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_PROGRAMMER,
+ "Premature end of stream during extraction of data (#2)");
+ return ARCHIVE_FATAL;
+ }
+
int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16;
bits |= (int) p[rar->bits.in_addr + 1] << 8;
bits |= (int) p[rar->bits.in_addr + 2];
@@ -1039,8 +1057,8 @@ static void skip_bits(struct rar5* rar, int bits) {
}
/* n = up to 16 */
-static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
- int* value)
+static int read_consume_bits(struct archive_read* a, struct rar5* rar,
+ const uint8_t* p, int n, int* value)
{
uint16_t v;
int ret, num;
@@ -1051,7 +1069,7 @@ static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
return ARCHIVE_FATAL;
}
- ret = read_bits_16(rar, p, &v);
+ ret = read_bits_16(a, rar, p, &v);
if(ret != ARCHIVE_OK)
return ret;
@@ -1099,6 +1117,44 @@ static int bid_standard(struct archive_read* a) {
return -1;
}
+static int bid_sfx(struct archive_read *a)
+{
+ const char *p;
+
+ if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
+ return -1;
+
+ if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
+ /* This is a PE file */
+ char signature[sizeof(rar5_signature_xor)];
+ ssize_t offset = 0x10000;
+ ssize_t window = 4096;
+ ssize_t bytes_avail;
+
+ rar5_signature(signature);
+
+ while (offset + window <= (1024 * 512)) {
+ const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail);
+ if (buff == NULL) {
+ /* Remaining bytes are less than window. */
+ window >>= 1;
+ if (window < 0x40)
+ return 0;
+ continue;
+ }
+ p = buff + offset;
+ while (p + 8 < buff + bytes_avail) {
+ if (memcmp(p, signature, sizeof(signature)) == 0)
+ return 30;
+ p += 0x10;
+ }
+ offset = p - buff;
+ }
+ }
+
+ return 0;
+}
+
static int rar5_bid(struct archive_read* a, int best_bid) {
int my_bid;
@@ -1109,6 +1165,10 @@ static int rar5_bid(struct archive_read* a, int best_bid) {
if(my_bid > -1) {
return my_bid;
}
+ my_bid = bid_sfx(a);
+ if (my_bid > -1) {
+ return my_bid;
+ }
return -1;
}
@@ -1712,14 +1772,29 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
}
}
- /* If we're currently switching volumes, ignore the new definition of
- * window_size. */
- if(rar->cstate.switch_multivolume == 0) {
- /* Values up to 64M should fit into ssize_t on every
- * architecture. */
- rar->cstate.window_size = (ssize_t) window_size;
+ if(rar->cstate.window_size < (ssize_t) window_size &&
+ rar->cstate.window_buf)
+ {
+ /* If window_buf has been allocated before, reallocate it, so
+ * that its size will match new window_size. */
+
+ uint8_t* new_window_buf =
+ realloc(rar->cstate.window_buf, window_size);
+
+ if(!new_window_buf) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Not enough memory when trying to realloc the window "
+ "buffer.");
+ return ARCHIVE_FATAL;
+ }
+
+ rar->cstate.window_buf = new_window_buf;
}
+ /* Values up to 64M should fit into ssize_t on every
+ * architecture. */
+ rar->cstate.window_size = (ssize_t) window_size;
+
if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
/* Solid files have to have the same window_size across
whole archive. Remember the window_size parameter
@@ -2273,6 +2348,62 @@ static int skip_base_block(struct archive_read* a) {
return ret;
}
+static int try_skip_sfx(struct archive_read *a)
+{
+ const char *p;
+
+ if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
+ return ARCHIVE_EOF;
+
+ if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0)
+ {
+ char signature[sizeof(rar5_signature_xor)];
+ const void *h;
+ const char *q;
+ size_t skip, total = 0;
+ ssize_t bytes, window = 4096;
+
+ rar5_signature(signature);
+
+ while (total + window <= (1024 * 512)) {
+ h = __archive_read_ahead(a, window, &bytes);
+ if (h == NULL) {
+ /* Remaining bytes are less than window. */
+ window >>= 1;
+ if (window < 0x40)
+ goto fatal;
+ continue;
+ }
+ if (bytes < 0x40)
+ goto fatal;
+ p = h;
+ q = p + bytes;
+
+ /*
+ * Scan ahead until we find something that looks
+ * like the RAR header.
+ */
+ while (p + 8 < q) {
+ if (memcmp(p, signature, sizeof(signature)) == 0) {
+ skip = p - (const char *)h;
+ __archive_read_consume(a, skip);
+ return (ARCHIVE_OK);
+ }
+ p += 0x10;
+ }
+ skip = p - (const char *)h;
+ __archive_read_consume(a, skip);
+ total += skip;
+ }
+ }
+
+ return ARCHIVE_OK;
+fatal:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Couldn't find out RAR header");
+ return (ARCHIVE_FATAL);
+}
+
static int rar5_read_header(struct archive_read *a,
struct archive_entry *entry)
{
@@ -2281,6 +2412,8 @@ static int rar5_read_header(struct archive_read *a,
if(rar->header_initialized == 0) {
init_header(a);
+ if ((ret = try_skip_sfx(a)) < ARCHIVE_WARN)
+ return ret;
rar->header_initialized = 1;
}
@@ -2342,7 +2475,7 @@ static void update_crc(struct rar5* rar, const uint8_t* p, size_t to_read) {
* `stored_crc32` info filled in. */
if(rar->file.stored_crc32 > 0) {
rar->file.calculated_crc32 =
- crc32(rar->file.calculated_crc32, p, to_read);
+ crc32(rar->file.calculated_crc32, p, (unsigned int)to_read);
}
/* Check if the file uses an optional BLAKE2sp checksum
@@ -2425,13 +2558,13 @@ static int create_decode_tables(uint8_t* bit_length,
static int decode_number(struct archive_read* a, struct decode_table* table,
const uint8_t* p, uint16_t* num)
{
- int i, bits, dist;
+ int i, bits, dist, ret;
uint16_t bitfield;
uint32_t pos;
struct rar5* rar = get_context(a);
- if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) {
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) {
+ return ret;
}
bitfield &= 0xfffe;
@@ -2537,14 +2670,6 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
for(i = 0; i < HUFF_TABLE_SIZE;) {
uint16_t num;
- if((rar->bits.in_addr + 6) >= rar->cstate.cur_block_size) {
- /* Truncated data, can't continue. */
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Truncated data in huffman tables (#2)");
- return ARCHIVE_FATAL;
- }
-
ret = decode_number(a, &rar->cstate.bd, p, &num);
if(ret != ARCHIVE_OK) {
archive_set_error(&a->archive,
@@ -2561,8 +2686,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
/* 16..17: repeat previous code */
uint16_t n;
- if(ARCHIVE_OK != read_bits_16(rar, p, &n))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
+ return ret;
if(num == 16) {
n >>= 13;
@@ -2590,8 +2715,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
/* other codes: fill with zeroes `n` times */
uint16_t n;
- if(ARCHIVE_OK != read_bits_16(rar, p, &n))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
+ return ret;
if(num == 18) {
n >>= 13;
@@ -2696,33 +2821,35 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
^ (uint8_t) (*block_size >> 16);
if(calculated_cksum != hdr->block_cksum) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Block checksum error: got 0x%x, expected 0x%x",
hdr->block_cksum, calculated_cksum);
return ARCHIVE_FATAL;
+#endif
}
return ARCHIVE_OK;
}
/* Convenience function used during filter processing. */
-static int parse_filter_data(struct rar5* rar, const uint8_t* p,
- uint32_t* filter_data)
+static int parse_filter_data(struct archive_read* a, struct rar5* rar,
+ const uint8_t* p, uint32_t* filter_data)
{
- int i, bytes;
+ int i, bytes, ret;
uint32_t data = 0;
- if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes)))
+ return ret;
bytes++;
for(i = 0; i < bytes; i++) {
uint16_t byte;
- if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) {
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) {
+ return ret;
}
/* Cast to uint32_t will ensure the shift operation will not
@@ -2765,16 +2892,17 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
uint16_t filter_type;
struct filter_info* filt = NULL;
struct rar5* rar = get_context(ar);
+ int ret;
/* Read the parameters from the input stream. */
- if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start)))
+ return ret;
- if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length)))
+ return ret;
- if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type)))
+ return ret;
filter_type >>= 13;
skip_bits(rar, 3);
@@ -2814,8 +2942,8 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
if(filter_type == FILTER_DELTA) {
int channels;
- if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels))
- return ARCHIVE_EOF;
+ if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
+ return ret;
filt->channels = channels + 1;
}
@@ -2823,10 +2951,11 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
return ARCHIVE_OK;
}
-static int decode_code_length(struct rar5* rar, const uint8_t* p,
- uint16_t code)
+static int decode_code_length(struct archive_read* a, struct rar5* rar,
+ const uint8_t* p, uint16_t code)
{
int lbits, length = 2;
+
if(code < 8) {
lbits = 0;
length += code;
@@ -2838,7 +2967,7 @@ static int decode_code_length(struct rar5* rar, const uint8_t* p,
if(lbits > 0) {
int add;
- if(ARCHIVE_OK != read_consume_bits(rar, p, lbits, &add))
+ if(ARCHIVE_OK != read_consume_bits(a, rar, p, lbits, &add))
return -1;
length += add;
@@ -2933,7 +3062,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
continue;
} else if(num >= 262) {
uint16_t dist_slot;
- int len = decode_code_length(rar, p, num - 262),
+ int len = decode_code_length(a, rar, p, num - 262),
dbits,
dist = 1;
@@ -2975,12 +3104,12 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
uint16_t low_dist;
if(dbits > 4) {
- if(ARCHIVE_OK != read_bits_32(
- rar, p, &add)) {
+ if(ARCHIVE_OK != (ret = read_bits_32(
+ a, rar, p, &add))) {
/* Return EOF if we
* can't read more
* data. */
- return ARCHIVE_EOF;
+ return ret;
}
skip_bits(rar, dbits - 4);
@@ -3015,11 +3144,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
/* dbits is one of [0,1,2,3] */
int add;
- if(ARCHIVE_OK != read_consume_bits(rar,
- p, dbits, &add)) {
+ if(ARCHIVE_OK != (ret = read_consume_bits(a, rar,
+ p, dbits, &add))) {
/* Return EOF if we can't read
* more data. */
- return ARCHIVE_EOF;
+ return ret;
}
dist += add;
@@ -3076,7 +3205,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
return ARCHIVE_FATAL;
}
- len = decode_code_length(rar, p, len_slot);
+ len = decode_code_length(a, rar, p, len_slot);
+ if (len == -1) {
+ return ARCHIVE_FATAL;
+ }
+
rar->cstate.last_len = len;
if(ARCHIVE_OK != copy_string(a, len, dist))
@@ -3600,6 +3733,16 @@ static int do_uncompress_file(struct archive_read* a) {
rar->cstate.initialized = 1;
}
+ /* Don't allow extraction if window_size is invalid. */
+ if(rar->cstate.window_size == 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid window size declaration in this file");
+
+ /* This should never happen in valid files. */
+ return ARCHIVE_FATAL;
+ }
+
if(rar->cstate.all_filters_applied == 1) {
/* We use while(1) here, but standard case allows for just 1
* iteration. The loop will iterate if process_block() didn't
@@ -3770,6 +3913,13 @@ static int do_unpack(struct archive_read* a, struct rar5* rar,
case GOOD:
/* fallthrough */
case BEST:
+ /* No data is returned here. But because a sparse-file aware
+ * caller (like archive_read_data_into_fd) may treat zero-size
+ * as a sparse file block, we need to update the offset
+ * accordingly. At this point the decoder doesn't have any
+ * pending uncompressed data blocks, so the current position in
+ * the output file should be last_write_ptr. */
+ if (offset) *offset = rar->cstate.last_write_ptr;
return uncompress_file(a);
default:
archive_set_error(&a->archive,
@@ -4076,6 +4226,7 @@ int archive_read_support_format_rar5(struct archive *_a) {
if(ARCHIVE_OK != rar5_init(rar)) {
archive_set_error(&ar->archive, ENOMEM,
"Can't allocate rar5 filter buffer");
+ free(rar);
return ARCHIVE_FATAL;
}
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c
index 96d810184..93c3fd585 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_tar.c
@@ -407,14 +407,13 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
/*
* Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
*/
- if (bid > 0 && (
- validate_number_field(header->mode, sizeof(header->mode)) == 0
+ if (validate_number_field(header->mode, sizeof(header->mode)) == 0
|| validate_number_field(header->uid, sizeof(header->uid)) == 0
|| validate_number_field(header->gid, sizeof(header->gid)) == 0
|| validate_number_field(header->mtime, sizeof(header->mtime)) == 0
|| validate_number_field(header->size, sizeof(header->size)) == 0
|| validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
- || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
+ || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0) {
bid = 0;
}
@@ -573,11 +572,15 @@ archive_read_format_tar_read_header(struct archive_read *a,
l = wcslen(wp);
if (l > 0 && wp[l - 1] == L'/') {
archive_entry_set_filetype(entry, AE_IFDIR);
+ tar->entry_bytes_remaining = 0;
+ tar->entry_padding = 0;
}
} else if ((p = archive_entry_pathname(entry)) != NULL) {
l = strlen(p);
if (l > 0 && p[l - 1] == '/') {
archive_entry_set_filetype(entry, AE_IFDIR);
+ tar->entry_bytes_remaining = 0;
+ tar->entry_padding = 0;
}
}
}
@@ -1396,6 +1399,7 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
{
int64_t size;
+ size_t msize;
const void *data;
const char *p, *name;
const wchar_t *wp, *wname;
@@ -1434,6 +1438,11 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
/* Read the body as a Mac OS metadata blob. */
size = archive_entry_size(entry);
+ msize = (size_t)size;
+ if (size < 0 || (uintmax_t)msize != (uintmax_t)size) {
+ *unconsumed = 0;
+ return (ARCHIVE_FATAL);
+ }
/*
* TODO: Look beyond the body here to peek at the next header.
@@ -1447,13 +1456,13 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
* Q: Is the above idea really possible? Even
* when there are GNU or pax extension entries?
*/
- data = __archive_read_ahead(a, (size_t)size, NULL);
+ data = __archive_read_ahead(a, msize, NULL);
if (data == NULL) {
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
- archive_entry_copy_mac_metadata(entry, data, (size_t)size);
- *unconsumed = (size_t)((size + 511) & ~ 511);
+ archive_entry_copy_mac_metadata(entry, data, msize);
+ *unconsumed = (msize + 511) & ~ 511;
tar_flush_unconsumed(a, unconsumed);
return (tar_read_header(a, tar, entry, unconsumed));
}
@@ -1906,7 +1915,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
}
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
tar->sparse_numbytes = tar_atol10(value, strlen(value));
- if (tar->sparse_numbytes != -1) {
+ if (tar->sparse_offset != -1) {
if (gnu_add_sparse_entry(a, tar,
tar->sparse_offset, tar->sparse_numbytes)
!= ARCHIVE_OK)
@@ -2098,6 +2107,21 @@ pax_attribute(struct archive_read *a, struct tar *tar,
/* "size" is the size of the data in the entry. */
tar->entry_bytes_remaining
= tar_atol10(value, strlen(value));
+ if (tar->entry_bytes_remaining < 0) {
+ tar->entry_bytes_remaining = 0;
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Tar size attribute is negative");
+ return (ARCHIVE_FATAL);
+ }
+ if (tar->entry_bytes_remaining == INT64_MAX) {
+ /* Note: tar_atol returns INT64_MAX on overflow */
+ tar->entry_bytes_remaining = 0;
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Tar size attribute overflow");
+ return (ARCHIVE_FATAL);
+ }
/*
* The "size" pax header keyword always overrides the
* "size" field in the tar header.
@@ -2643,14 +2667,14 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
maxval = INT64_MIN;
limit = -(INT64_MIN / base);
- last_digit_limit = INT64_MIN % base;
+ last_digit_limit = -(INT64_MIN % base);
}
l = 0;
if (char_cnt != 0) {
digit = *p - '0';
while (digit >= 0 && digit < base && char_cnt != 0) {
- if (l>limit || (l == limit && digit > last_digit_limit)) {
+ if (l>limit || (l == limit && digit >= last_digit_limit)) {
return maxval; /* Truncate on overflow. */
}
l = (l * base) + digit;
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_warc.c b/src/libs/3rdparty/libarchive/archive_read_support_format_warc.c
index 27329962d..61ab29ea1 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_warc.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_warc.c
@@ -530,11 +530,11 @@ strtoi_lim(const char *str, const char **ep, int llim, int ulim)
static time_t
time_from_tm(struct tm *t)
{
-#if HAVE_TIMEGM
+#if HAVE__MKGMTIME
+ return _mkgmtime(t);
+#elif HAVE_TIMEGM
/* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE__MKGMTIME64
- return (_mkgmtime64(t));
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c
index 503ff58b9..ec9cb1981 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_xar.c
@@ -624,7 +624,9 @@ read_toc(struct archive_read *a)
__archive_read_consume(a, xar->toc_chksum_size);
xar->offset += xar->toc_chksum_size;
if (r != ARCHIVE_OK)
+#ifndef DONT_FAIL_ON_CRC_ERROR
return (ARCHIVE_FATAL);
+#endif
}
/*
@@ -827,10 +829,12 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
xattr->a_sum.val, xattr->a_sum.len,
xattr->e_sum.val, xattr->e_sum.len);
if (r != ARCHIVE_OK) {
+#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Xattr checksum error");
r = ARCHIVE_WARN;
break;
+#endif
}
if (xattr->name.s == NULL) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
@@ -1123,7 +1127,7 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
x |= p[1] - '0';
else
return (-1);
-
+
*b++ = x;
bsize--;
p += 2;
@@ -1135,11 +1139,11 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
static time_t
time_from_tm(struct tm *t)
{
-#if HAVE_TIMEGM
+#if HAVE__MKGMTIME
+ return _mkgmtime(t);
+#elif HAVE_TIMEGM
/* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE__MKGMTIME64
- return (_mkgmtime64(t));
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_zip.c b/src/libs/3rdparty/libarchive/archive_read_support_format_zip.c
index a64332c28..c3b9b5755 100644
--- a/src/libs/3rdparty/libarchive/archive_read_support_format_zip.c
+++ b/src/libs/3rdparty/libarchive/archive_read_support_format_zip.c
@@ -58,6 +58,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102
#ifdef HAVE_LZMA_H
#include <lzma.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_digest_private.h"
@@ -142,6 +145,7 @@ struct zip {
/* Structural information about the archive. */
struct archive_string format_name;
int64_t central_directory_offset;
+ int64_t central_directory_offset_adjusted;
size_t central_directory_entries_total;
size_t central_directory_entries_on_this_disk;
int has_encrypted_entries;
@@ -190,6 +194,11 @@ struct zip {
char bzstream_valid;
#endif
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_DStream *zstdstream;
+ char zstdstream_valid;
+#endif
+
IByteIn zipx_ppmd_stream;
ssize_t zipx_ppmd_read_compressed;
CPpmd8 ppmd8;
@@ -246,6 +255,17 @@ struct zip {
/* Many systems define min or MIN, but not all. */
#define zipmin(a,b) ((a) < (b) ? (a) : (b))
+#ifdef HAVE_ZLIB_H
+static int
+zip_read_data_deflate(struct archive_read *a, const void **buff,
+ size_t *size, int64_t *offset);
+#endif
+#if HAVE_LZMA_H && HAVE_LIBLZMA
+static int
+zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
+ size_t *size, int64_t *offset);
+#endif
+
/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
* streams inside ZIP files. It has 2 purposes: one is to fetch the next
* compressed byte from the stream, second one is to increase the counter how
@@ -423,6 +443,7 @@ static const struct {
{17, "reserved"}, /* Reserved by PKWARE */
{18, "ibm-terse-new"}, /* File is compressed using IBM TERSE (new) */
{19, "ibm-lz777"},/* IBM LZ77 z Architecture (PFS) */
+ {93, "zstd"}, /* Zstandard (zstd) Compression */
{95, "xz"}, /* XZ compressed data */
{96, "jpeg"}, /* JPEG compressed data */
{97, "wav-pack"}, /* WavPack compressed data */
@@ -899,81 +920,6 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
return ARCHIVE_OK;
}
-#if HAVE_LZMA_H && HAVE_LIBLZMA
-/*
- * Auxiliary function to uncompress data chunk from zipx archive
- * (zip with lzma compression).
- */
-static int
-zipx_lzma_uncompress_buffer(const char *compressed_buffer,
- size_t compressed_buffer_size,
- char *uncompressed_buffer,
- size_t uncompressed_buffer_size)
-{
- int status = ARCHIVE_FATAL;
- // length of 'lzma properties data' in lzma compressed
- // data segment (stream) inside zip archive
- const size_t lzma_params_length = 5;
- // offset of 'lzma properties data' from the beginning of lzma stream
- const size_t lzma_params_offset = 4;
- // end position of 'lzma properties data' in lzma stream
- const size_t lzma_params_end = lzma_params_offset + lzma_params_length;
- if (compressed_buffer == NULL ||
- compressed_buffer_size < lzma_params_end ||
- uncompressed_buffer == NULL)
- return status;
-
- // prepare header for lzma_alone_decoder to replace zipx header
- // (see comments in 'zipx_lzma_alone_init' for justification)
-#pragma pack(push)
-#pragma pack(1)
- struct _alone_header
- {
- uint8_t bytes[5]; // lzma_params_length
- uint64_t uncompressed_size;
- } alone_header;
-#pragma pack(pop)
- // copy 'lzma properties data' blob
- memcpy(&alone_header.bytes[0], compressed_buffer + lzma_params_offset,
- lzma_params_length);
- alone_header.uncompressed_size = UINT64_MAX;
-
- // prepare new compressed buffer, see 'zipx_lzma_alone_init' for details
- const size_t lzma_alone_buffer_size =
- compressed_buffer_size - lzma_params_end + sizeof(alone_header);
- unsigned char *lzma_alone_compressed_buffer =
- (unsigned char*) malloc(lzma_alone_buffer_size);
- if (lzma_alone_compressed_buffer == NULL)
- return status;
- // copy lzma_alone header into new buffer
- memcpy(lzma_alone_compressed_buffer, (void*) &alone_header,
- sizeof(alone_header));
- // copy compressed data into new buffer
- memcpy(lzma_alone_compressed_buffer + sizeof(alone_header),
- compressed_buffer + lzma_params_end,
- compressed_buffer_size - lzma_params_end);
-
- // create and fill in lzma_alone_decoder stream
- lzma_stream stream = LZMA_STREAM_INIT;
- lzma_ret ret = lzma_alone_decoder(&stream, UINT64_MAX);
- if (ret == LZMA_OK)
- {
- stream.next_in = lzma_alone_compressed_buffer;
- stream.avail_in = lzma_alone_buffer_size;
- stream.total_in = 0;
- stream.next_out = (unsigned char*)uncompressed_buffer;
- stream.avail_out = uncompressed_buffer_size;
- stream.total_out = 0;
- ret = lzma_code(&stream, LZMA_RUN);
- if (ret == LZMA_OK || ret == LZMA_STREAM_END)
- status = ARCHIVE_OK;
- }
- lzma_end(&stream);
- free(lzma_alone_compressed_buffer);
- return status;
-}
-#endif
-
/*
* Assumes file pointer is at beginning of local file header.
*/
@@ -1207,7 +1153,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
(intmax_t)zip_entry->compressed_size);
ret = ARCHIVE_WARN;
}
- if (zip_entry->uncompressed_size == 0) {
+ if (zip_entry->uncompressed_size == 0 ||
+ zip_entry->uncompressed_size == 0xffffffff) {
zip_entry->uncompressed_size
= zip_entry_central_dir.uncompressed_size;
} else if (zip_entry->uncompressed_size
@@ -1242,36 +1189,30 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
linkname_length = (size_t)zip_entry->compressed_size;
archive_entry_set_size(entry, 0);
- p = __archive_read_ahead(a, linkname_length, NULL);
- if (p == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Truncated Zip file");
- return ARCHIVE_FATAL;
- }
+
// take into account link compression if any
size_t linkname_full_length = linkname_length;
if (zip->entry->compression != 0)
{
// symlink target string appeared to be compressed
int status = ARCHIVE_FATAL;
- char *uncompressed_buffer =
- (char*) malloc(zip_entry->uncompressed_size);
- if (uncompressed_buffer == NULL)
- {
- archive_set_error(&a->archive, ENOMEM,
- "No memory for lzma decompression");
- return status;
- }
+ const void *uncompressed_buffer = NULL;
switch (zip->entry->compression)
{
+#if HAVE_ZLIB_H
+ case 8: /* Deflate compression. */
+ zip->entry_bytes_remaining = zip_entry->compressed_size;
+ status = zip_read_data_deflate(a, &uncompressed_buffer,
+ &linkname_full_length, NULL);
+ break;
+#endif
#if HAVE_LZMA_H && HAVE_LIBLZMA
case 14: /* ZIPx LZMA compression. */
/*(see zip file format specification, section 4.4.5)*/
- status = zipx_lzma_uncompress_buffer(p,
- linkname_length,
- uncompressed_buffer,
- (size_t)zip_entry->uncompressed_size);
+ zip->entry_bytes_remaining = zip_entry->compressed_size;
+ status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
+ &linkname_full_length, NULL);
break;
#endif
default: /* Unsupported compression. */
@@ -1280,8 +1221,6 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
if (status == ARCHIVE_OK)
{
p = uncompressed_buffer;
- linkname_full_length =
- (size_t)zip_entry->uncompressed_size;
}
else
{
@@ -1294,6 +1233,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
return ARCHIVE_FAILED;
}
}
+ else
+ {
+ p = __archive_read_ahead(a, linkname_length, NULL);
+ }
+
+ if (p == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Truncated Zip file");
+ return ARCHIVE_FATAL;
+ }
sconv = zip->sconv;
if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
@@ -1663,7 +1612,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
* that is a part of XZ Utils. The stream format stored inside ZIPX
* file is a modified "lzma alone" file format, that was used by the
- * `lzma` utility which was later deprecated in favour of `xz` utility. * Since those formats are nearly the same, we can use a standard
+ * `lzma` utility which was later deprecated in favour of `xz` utility.
+ * Since those formats are nearly the same, we can use a standard
* "lzma alone" decoder from XZ Utils. */
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
@@ -1717,7 +1667,7 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
*/
/* Read magic1,magic2,lzma_params from the ZIPX stream. */
- if((p = __archive_read_ahead(a, 9, NULL)) == NULL) {
+ if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated lzma data");
return (ARCHIVE_FATAL);
@@ -2236,11 +2186,11 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
/* Setup buffer boundaries. */
zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff;
- zip->bzstream.avail_in = in_bytes;
+ zip->bzstream.avail_in = (uint32_t)in_bytes;
zip->bzstream.total_in_hi32 = 0;
zip->bzstream.total_in_lo32 = 0;
zip->bzstream.next_out = (char*) zip->uncompressed_buffer;
- zip->bzstream.avail_out = zip->uncompressed_buffer_size;
+ zip->bzstream.avail_out = (uint32_t)zip->uncompressed_buffer_size;
zip->bzstream.total_out_hi32 = 0;
zip->bzstream.total_out_lo32 = 0;
@@ -2277,7 +2227,7 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
to_consume = zip->bzstream.total_in_lo32;
__archive_read_consume(a, to_consume);
- total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) +
+ total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) |
zip->bzstream.total_out_lo32;
zip->entry_bytes_remaining -= to_consume;
@@ -2298,6 +2248,140 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
#endif
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+static int
+zipx_zstd_init(struct archive_read *a, struct zip *zip)
+{
+ size_t r;
+
+ /* Deallocate already existing Zstd decompression context if it
+ * exists. */
+ if(zip->zstdstream_valid) {
+ ZSTD_freeDStream(zip->zstdstream);
+ zip->zstdstream_valid = 0;
+ }
+
+ /* Allocate a new Zstd decompression context. */
+ zip->zstdstream = ZSTD_createDStream();
+
+ r = ZSTD_initDStream(zip->zstdstream);
+ if (ZSTD_isError(r)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Error initializing zstd decompressor: %s",
+ ZSTD_getErrorName(r));
+
+ return ARCHIVE_FAILED;
+ }
+
+ /* Mark the zstdstream field to be released in cleanup phase. */
+ zip->zstdstream_valid = 1;
+
+ /* (Re)allocate the buffer that will contain decompressed bytes. */
+ free(zip->uncompressed_buffer);
+
+ zip->uncompressed_buffer_size = ZSTD_DStreamOutSize();
+ zip->uncompressed_buffer =
+ (uint8_t*) malloc(zip->uncompressed_buffer_size);
+ if (zip->uncompressed_buffer == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory for Zstd decompression");
+
+ return ARCHIVE_FATAL;
+ }
+
+ /* Initialization done. */
+ zip->decompress_init = 1;
+ return ARCHIVE_OK;
+}
+
+static int
+zip_read_data_zipx_zstd(struct archive_read *a, const void **buff,
+ size_t *size, int64_t *offset)
+{
+ struct zip *zip = (struct zip *)(a->format->data);
+ ssize_t bytes_avail = 0, in_bytes, to_consume;
+ const void *compressed_buff;
+ int r;
+ size_t ret;
+ uint64_t total_out;
+ ZSTD_outBuffer out;
+ ZSTD_inBuffer in;
+
+ (void) offset; /* UNUSED */
+
+ /* Initialize decompression context if we're here for the first time. */
+ if(!zip->decompress_init) {
+ r = zipx_zstd_init(a, zip);
+ if(r != ARCHIVE_OK)
+ return r;
+ }
+
+ /* Fetch more compressed bytes */
+ compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
+ if(bytes_avail < 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated zstd file body");
+ return (ARCHIVE_FATAL);
+ }
+
+ in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
+ if(in_bytes < 1) {
+ /* zstd doesn't complain when caller feeds avail_in == 0.
+ * It will actually return success in this case, which is
+ * undesirable. This is why we need to make this check
+ * manually. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated zstd file body");
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Setup buffer boundaries */
+ in.src = compressed_buff;
+ in.size = in_bytes;
+ in.pos = 0;
+ out = (ZSTD_outBuffer) { zip->uncompressed_buffer, zip->uncompressed_buffer_size, 0 };
+
+ /* Perform the decompression. */
+ ret = ZSTD_decompressStream(zip->zstdstream, &out, &in);
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Error during zstd decompression: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Check end of the stream. */
+ if (ret == 0) {
+ if ((in.pos == in.size) && (out.pos < out.size)) {
+ zip->end_of_entry = 1;
+ ZSTD_freeDStream(zip->zstdstream);
+ zip->zstdstream_valid = 0;
+ }
+ }
+
+ /* Update the pointers so decompressor can continue decoding. */
+ to_consume = in.pos;
+ __archive_read_consume(a, to_consume);
+
+ total_out = out.pos;
+
+ zip->entry_bytes_remaining -= to_consume;
+ zip->entry_compressed_bytes_read += to_consume;
+ zip->entry_uncompressed_bytes_read += total_out;
+
+ /* Give libarchive its due. */
+ *size = total_out;
+ *buff = zip->uncompressed_buffer;
+
+ /* Seek for optional marker, like in other entries. */
+ r = consume_optional_marker(a, zip);
+ if(r != ARCHIVE_OK)
+ return r;
+
+ return ARCHIVE_OK;
+}
+#endif
+
#ifdef HAVE_ZLIB_H
static int
zip_deflate_init(struct archive_read *a, struct zip *zip)
@@ -2918,6 +3002,11 @@ archive_read_format_zip_read_data(struct archive_read *a,
r = zip_read_data_zipx_xz(a, buff, size, offset);
break;
#endif
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ case 93: /* ZIPx Zstd compression. */
+ r = zip_read_data_zipx_zstd(a, buff, size, offset);
+ break;
+#endif
/* PPMd support is built-in, so we don't need any #if guards. */
case 98: /* ZIPx PPMd compression. */
r = zip_read_data_zipx_ppmd(a, buff, size, offset);
@@ -3008,6 +3097,12 @@ archive_read_format_zip_cleanup(struct archive_read *a)
}
#endif
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ if (zip->zstdstream_valid) {
+ ZSTD_freeDStream(zip->zstdstream);
+ }
+#endif
+
free(zip->uncompressed_buffer);
if (zip->ppmd8_valid)
@@ -3415,24 +3510,31 @@ archive_read_support_format_zip_capabilities_seekable(struct archive_read * a)
static int
read_eocd(struct zip *zip, const char *p, int64_t current_offset)
{
+ uint16_t disk_num;
+ uint32_t cd_size, cd_offset;
+
+ disk_num = archive_le16dec(p + 4);
+ cd_size = archive_le32dec(p + 12);
+ cd_offset = archive_le32dec(p + 16);
+
/* Sanity-check the EOCD we've found. */
/* This must be the first volume. */
- if (archive_le16dec(p + 4) != 0)
+ if (disk_num != 0)
return 0;
/* Central directory must be on this volume. */
- if (archive_le16dec(p + 4) != archive_le16dec(p + 6))
+ if (disk_num != archive_le16dec(p + 6))
return 0;
/* All central directory entries must be on this volume. */
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
return 0;
/* Central directory can't extend beyond start of EOCD record. */
- if (archive_le32dec(p + 16) + archive_le32dec(p + 12)
- > current_offset)
+ if (cd_offset + cd_size > current_offset)
return 0;
/* Save the central directory location for later use. */
- zip->central_directory_offset = archive_le32dec(p + 16);
+ zip->central_directory_offset = cd_offset;
+ zip->central_directory_offset_adjusted = current_offset - cd_size;
/* This is just a tiny bit higher than the maximum
returned by the streaming Zip bidder. This ensures
@@ -3484,6 +3586,8 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
/* Save the central directory offset for later use. */
zip->central_directory_offset = archive_le64dec(p + 48);
+ /* TODO: Needs scanning backwards to find the eocd64 instead of assuming */
+ zip->central_directory_offset_adjusted = zip->central_directory_offset;
return 32;
}
@@ -3655,7 +3759,8 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
* know the correction we need to apply to account for leading
* padding.
*/
- if (__archive_read_seek(a, zip->central_directory_offset, SEEK_SET) < 0)
+ if (__archive_read_seek(a, zip->central_directory_offset_adjusted, SEEK_SET)
+ < 0)
return ARCHIVE_FATAL;
found = 0;
diff --git a/src/libs/3rdparty/libarchive/archive_string.c b/src/libs/3rdparty/libarchive/archive_string.c
index 7460ded00..accf52631 100644
--- a/src/libs/3rdparty/libarchive/archive_string.c
+++ b/src/libs/3rdparty/libarchive/archive_string.c
@@ -745,7 +745,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
dp = &defchar_used;
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
as->s + as->length,
- (int)as->buffer_length - as->length - 1, NULL, dp);
+ (int)as->buffer_length - (int)as->length - 1, NULL, dp);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the MBS buffer and retry. */
@@ -1324,6 +1324,10 @@ free_sconv_object(struct archive_string_conv *sc)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define GetOEMCP() CP_OEMCP
+# endif
+
static unsigned
my_atoi(const char *p)
{
@@ -3988,10 +3992,10 @@ int
archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
const char **p, size_t *length, struct archive_string_conv *sc)
{
- int r, ret = 0;
-
- (void)r; /* UNUSED */
+ int ret = 0;
#if defined(_WIN32) && !defined(__CYGWIN__)
+ int r;
+
/*
* Internationalization programming on Windows must use Wide
* characters because Windows platform cannot make locale UTF-8.
diff --git a/src/libs/3rdparty/libarchive/archive_util.c b/src/libs/3rdparty/libarchive/archive_util.c
index b1582edbe..40603c483 100644
--- a/src/libs/3rdparty/libarchive/archive_util.c
+++ b/src/libs/3rdparty/libarchive/archive_util.c
@@ -42,9 +42,20 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#ifdef HAVE_STRING_H
#include <string.h>
#endif
-#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#elif defined(HAVE_WINCRYPT_H)
#include <wincrypt.h>
#endif
+#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
@@ -233,14 +244,16 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
L'm', L'n', L'o', L'p', L'q', L'r', L's', L't',
L'u', L'v', L'w', L'x', L'y', L'z'
};
- HCRYPTPROV hProv;
struct archive_wstring temp_name;
wchar_t *ws;
DWORD attr;
wchar_t *xp, *ep;
int fd;
-
- hProv = (HCRYPTPROV)NULL;
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCRYPT_ALG_HANDLE hAlg = NULL;
+#else
+ HCRYPTPROV hProv = (HCRYPTPROV)NULL;
+#endif
fd = -1;
ws = NULL;
@@ -314,23 +327,42 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
abort();
}
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM,
+ NULL, 0))) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+#else
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
+#endif
for (;;) {
wchar_t *p;
HANDLE h;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
/* Generate a random file name through CryptGenRandom(). */
p = xp;
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p,
+ (DWORD)(ep - p)*sizeof(wchar_t), 0))) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+#else
if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
(BYTE*)p)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
+#endif
for (; p < ep; p++)
*p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
@@ -347,6 +379,17 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
/* mkstemp */
attr = FILE_ATTRIBUTE_NORMAL;
}
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileAttributes = attr & 0xFFFF;
+ createExParams.dwFileFlags = attr & 0xFFF00000;
+ h = CreateFile2(ws,
+ GENERIC_READ | GENERIC_WRITE | DELETE,
+ 0,/* Not share */
+ CREATE_NEW,
+ &createExParams);
+#else
h = CreateFileW(ws,
GENERIC_READ | GENERIC_WRITE | DELETE,
0,/* Not share */
@@ -354,6 +397,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
CREATE_NEW,/* Create a new file only */
attr,
NULL);
+#endif
if (h == INVALID_HANDLE_VALUE) {
/* The same file already exists. retry with
* a new filename. */
@@ -372,8 +416,13 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
break;/* success! */
}
exit_tmpfile:
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (hAlg != NULL)
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+#else
if (hProv != (HCRYPTPROV)NULL)
CryptReleaseContext(hProv, 0);
+#endif
free(ws);
if (template == temp_name.s)
archive_wstring_free(&temp_name);
diff --git a/src/libs/3rdparty/libarchive/archive_windows.c b/src/libs/3rdparty/libarchive/archive_windows.c
index 624e27009..ebc5eefb8 100644
--- a/src/libs/3rdparty/libarchive/archive_windows.c
+++ b/src/libs/3rdparty/libarchive/archive_windows.c
@@ -234,7 +234,11 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
{
wchar_t *wpath;
HANDLE handle;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
+#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
handle = CreateFileA(path, dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
hTemplateFile);
@@ -242,12 +246,25 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
return (handle);
if (GetLastError() != ERROR_PATH_NOT_FOUND)
return (handle);
+#endif
wpath = __la_win_permissive_name(path);
if (wpath == NULL)
- return (handle);
+ return INVALID_HANDLE_VALUE;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF;
+ createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000;
+ createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F00000;
+ createExParams.lpSecurityAttributes = lpSecurityAttributes;
+ createExParams.hTemplateFile = hTemplateFile;
+ handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode,
+ dwCreationDisposition, &createExParams);
+#else /* !WINAPI_PARTITION_DESKTOP */
handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
hTemplateFile);
+#endif /* !WINAPI_PARTITION_DESKTOP */
free(wpath);
return (handle);
}
@@ -305,7 +322,10 @@ __la_open(const char *path, int flags, ...)
* "Permission denied" error.
*/
attr = GetFileAttributesA(path);
- if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND) {
+#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
+ if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND)
+#endif
+ {
ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
@@ -320,7 +340,7 @@ __la_open(const char *path, int flags, ...)
}
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
HANDLE handle;
-
+#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
if (ws != NULL)
handle = CreateFileW(ws, 0, 0, NULL,
OPEN_EXISTING,
@@ -333,6 +353,15 @@ __la_open(const char *path, int flags, ...)
FILE_FLAG_BACKUP_SEMANTICS |
FILE_ATTRIBUTE_READONLY,
NULL);
+#else /* !WINAPI_PARTITION_DESKTOP */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
+ createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
+ handle = CreateFile2(ws, 0, 0,
+ OPEN_EXISTING, &createExParams);
+#endif /* !WINAPI_PARTITION_DESKTOP */
free(ws);
if (handle == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
diff --git a/src/libs/3rdparty/libarchive/archive_write.c b/src/libs/3rdparty/libarchive/archive_write.c
index 8d70f51a6..ec3c95c56 100644
--- a/src/libs/3rdparty/libarchive/archive_write.c
+++ b/src/libs/3rdparty/libarchive/archive_write.c
@@ -60,8 +60,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write.c 201099 2009-12-28 03:03:
#include "archive_private.h"
#include "archive_write_private.h"
-static struct archive_vtable *archive_write_vtable(void);
-
static int _archive_filter_code(struct archive *, int);
static const char *_archive_filter_name(struct archive *, int);
static int64_t _archive_filter_bytes(struct archive *, int);
@@ -79,26 +77,18 @@ struct archive_none {
char *next;
};
-static struct archive_vtable *
-archive_write_vtable(void)
-{
- static struct archive_vtable av;
- static int inited = 0;
-
- if (!inited) {
- av.archive_close = _archive_write_close;
- av.archive_filter_bytes = _archive_filter_bytes;
- av.archive_filter_code = _archive_filter_code;
- av.archive_filter_name = _archive_filter_name;
- av.archive_filter_count = _archive_write_filter_count;
- av.archive_free = _archive_write_free;
- av.archive_write_header = _archive_write_header;
- av.archive_write_finish_entry = _archive_write_finish_entry;
- av.archive_write_data = _archive_write_data;
- inited = 1;
- }
- return (&av);
-}
+static const struct archive_vtable
+archive_write_vtable = {
+ .archive_close = _archive_write_close,
+ .archive_filter_bytes = _archive_filter_bytes,
+ .archive_filter_code = _archive_filter_code,
+ .archive_filter_name = _archive_filter_name,
+ .archive_filter_count = _archive_write_filter_count,
+ .archive_free = _archive_write_free,
+ .archive_write_header = _archive_write_header,
+ .archive_write_finish_entry = _archive_write_finish_entry,
+ .archive_write_data = _archive_write_data,
+};
/*
* Allocate, initialize and return an archive object.
@@ -114,7 +104,7 @@ archive_write_new(void)
return (NULL);
a->archive.magic = ARCHIVE_WRITE_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
- a->archive.vtable = archive_write_vtable();
+ a->archive.vtable = &archive_write_vtable;
/*
* The value 10240 here matches the traditional tar default,
* but is otherwise arbitrary.
@@ -211,6 +201,10 @@ __archive_write_allocate_filter(struct archive *_a)
struct archive_write_filter *f;
f = calloc(1, sizeof(*f));
+
+ if (f == NULL)
+ return (NULL);
+
f->archive = _a;
f->state = ARCHIVE_WRITE_FILTER_STATE_NEW;
if (a->filter_first == NULL)
@@ -316,6 +310,25 @@ __archive_write_output(struct archive_write *a, const void *buff, size_t length)
return (__archive_write_filter(a->filter_first, buff, length));
}
+static int
+__archive_write_filters_flush(struct archive_write *a)
+{
+ struct archive_write_filter *f;
+ int ret, ret1;
+
+ ret = ARCHIVE_OK;
+ for (f = a->filter_first; f != NULL; f = f->next_filter) {
+ if (f->flush != NULL && f->bytes_written > 0) {
+ ret1 = (f->flush)(f);
+ if (ret1 < ret)
+ ret = ret1;
+ if (ret1 < ARCHIVE_WARN)
+ f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL;
+ }
+ }
+ return (ret);
+}
+
int
__archive_write_nulls(struct archive_write *a, size_t length)
{
@@ -482,6 +495,8 @@ archive_write_client_close(struct archive_write_filter *f)
ssize_t block_length;
ssize_t target_block_length;
ssize_t bytes_written;
+ size_t to_write;
+ char *p;
int ret = ARCHIVE_OK;
/* If there's pending data, pad and write the last block */
@@ -504,9 +519,24 @@ archive_write_client_close(struct archive_write_filter *f)
target_block_length - block_length);
block_length = target_block_length;
}
- bytes_written = (a->client_writer)(&a->archive,
- a->client_data, state->buffer, block_length);
- ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
+ p = state->buffer;
+ to_write = block_length;
+ while (to_write > 0) {
+ bytes_written = (a->client_writer)(&a->archive,
+ a->client_data, p, to_write);
+ if (bytes_written <= 0) {
+ ret = ARCHIVE_FATAL;
+ break;
+ }
+ if ((size_t)bytes_written > to_write) {
+ archive_set_error(&(a->archive),
+ -1, "write overrun");
+ ret = ARCHIVE_FATAL;
+ break;
+ }
+ p += bytes_written;
+ to_write -= bytes_written;
+ }
}
if (a->client_closer)
(*a->client_closer)(&a->archive, a->client_data);
@@ -541,6 +571,10 @@ archive_write_open2(struct archive *_a, void *client_data,
a->client_data = client_data;
client_filter = __archive_write_allocate_filter(_a);
+
+ if (client_filter == NULL)
+ return (ARCHIVE_FATAL);
+
client_filter->open = archive_write_client_open;
client_filter->write = archive_write_client_write;
client_filter->close = archive_write_client_close;
@@ -725,6 +759,18 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
return (ARCHIVE_FAILED);
}
+ /* Flush filters at boundary. */
+ r2 = __archive_write_filters_flush(a);
+ if (r2 == ARCHIVE_FAILED) {
+ return (ARCHIVE_FAILED);
+ }
+ if (r2 == ARCHIVE_FATAL) {
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ if (r2 < ret)
+ ret = r2;
+
/* Format and write header. */
r2 = ((a->format_write_header)(a, entry));
if (r2 == ARCHIVE_FAILED) {
diff --git a/src/libs/3rdparty/libarchive/archive_write_add_filter_bzip2.c b/src/libs/3rdparty/libarchive/archive_write_add_filter_bzip2.c
index 7001e9c6b..3e5c0891a 100644
--- a/src/libs/3rdparty/libarchive/archive_write_add_filter_bzip2.c
+++ b/src/libs/3rdparty/libarchive/archive_write_add_filter_bzip2.c
@@ -190,7 +190,7 @@ archive_compressor_bzip2_open(struct archive_write_filter *f)
memset(&data->stream, 0, sizeof(data->stream));
data->stream.next_out = data->compressed;
- data->stream.avail_out = data->compressed_buffer_size;
+ data->stream.avail_out = (uint32_t)data->compressed_buffer_size;
f->write = archive_compressor_bzip2_write;
/* Initialize compression library */
@@ -244,7 +244,7 @@ archive_compressor_bzip2_write(struct archive_write_filter *f,
/* Compress input data to output buffer */
SET_NEXT_IN(data, buff);
- data->stream.avail_in = length;
+ data->stream.avail_in = (uint32_t)length;
if (drive_compressor(f, data, 0))
return (ARCHIVE_FATAL);
return (ARCHIVE_OK);
@@ -313,7 +313,7 @@ drive_compressor(struct archive_write_filter *f,
return (ARCHIVE_FATAL);
}
data->stream.next_out = data->compressed;
- data->stream.avail_out = data->compressed_buffer_size;
+ data->stream.avail_out = (uint32_t)data->compressed_buffer_size;
}
/* If there's nothing to do, we're done. */
diff --git a/src/libs/3rdparty/libarchive/archive_write_add_filter_compress.c b/src/libs/3rdparty/libarchive/archive_write_add_filter_compress.c
index d404fae7d..3ed269fce 100644
--- a/src/libs/3rdparty/libarchive/archive_write_add_filter_compress.c
+++ b/src/libs/3rdparty/libarchive/archive_write_add_filter_compress.c
@@ -352,7 +352,7 @@ archive_compressor_compress_write(struct archive_write_filter *f,
while (length--) {
c = *bp++;
state->in_count++;
- state->cur_fcode = (c << 16) + state->cur_code;
+ state->cur_fcode = (c << 16) | state->cur_code;
i = ((c << HSHIFT) ^ state->cur_code); /* Xor hashing. */
if (state->hashtab[i] == state->cur_fcode) {
diff --git a/src/libs/3rdparty/libarchive/archive_write_add_filter_lz4.c b/src/libs/3rdparty/libarchive/archive_write_add_filter_lz4.c
index cf19fadd5..6ac450357 100644
--- a/src/libs/3rdparty/libarchive/archive_write_add_filter_lz4.c
+++ b/src/libs/3rdparty/libarchive/archive_write_add_filter_lz4.c
@@ -518,10 +518,10 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p,
} else {
/* The buffer is not compressed. The compressed size was
* bigger than its uncompressed size. */
- archive_le32enc(data->out, length | 0x80000000);
+ archive_le32enc(data->out, (uint32_t)(length | 0x80000000));
data->out += 4;
memcpy(data->out, p, length);
- outsize = length;
+ outsize = (uint32_t)length;
}
data->out += outsize;
if (data->block_checksum) {
@@ -603,10 +603,10 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
} else {
/* The buffer is not compressed. The compressed size was
* bigger than its uncompressed size. */
- archive_le32enc(data->out, length | 0x80000000);
+ archive_le32enc(data->out, (uint32_t)(length | 0x80000000));
data->out += 4;
memcpy(data->out, p, length);
- outsize = length;
+ outsize = (uint32_t)length;
}
data->out += outsize;
if (data->block_checksum) {
diff --git a/src/libs/3rdparty/libarchive/archive_write_add_filter_xz.c b/src/libs/3rdparty/libarchive/archive_write_add_filter_xz.c
index 9dd2c30e5..04bee90ef 100644
--- a/src/libs/3rdparty/libarchive/archive_write_add_filter_xz.c
+++ b/src/libs/3rdparty/libarchive/archive_write_add_filter_xz.c
@@ -251,13 +251,13 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
int ds, log2dic, wedges;
/* Calculate a coded dictionary size */
- if (dict_size < (1 << 12) || dict_size > (1 << 27)) {
+ if (dict_size < (1 << 12) || dict_size > (1 << 29)) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"Unacceptable dictionary size for lzip: %d",
dict_size);
return (ARCHIVE_FATAL);
}
- for (log2dic = 27; log2dic >= 12; log2dic--) {
+ for (log2dic = 29; log2dic >= 12; log2dic--) {
if (dict_size & (1 << log2dic))
break;
}
diff --git a/src/libs/3rdparty/libarchive/archive_write_add_filter_zstd.c b/src/libs/3rdparty/libarchive/archive_write_add_filter_zstd.c
index c74a35cde..584cfb668 100644
--- a/src/libs/3rdparty/libarchive/archive_write_add_filter_zstd.c
+++ b/src/libs/3rdparty/libarchive/archive_write_add_filter_zstd.c
@@ -31,6 +31,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -50,9 +53,21 @@ __FBSDID("$FreeBSD$");
struct private_data {
int compression_level;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ int threads;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ enum {
+ running,
+ finishing,
+ resetting,
+ } state;
+ int frame_per_file;
+ size_t min_frame_size;
+ size_t max_frame_size;
+ size_t cur_frame;
+ size_t cur_frame_in;
+ size_t cur_frame_out;
+ size_t total_in;
ZSTD_CStream *cstream;
- int64_t total_in;
ZSTD_outBuffer out;
#else
struct archive_write_program_data *pdata;
@@ -74,9 +89,10 @@ static int archive_compressor_zstd_options(struct archive_write_filter *,
static int archive_compressor_zstd_open(struct archive_write_filter *);
static int archive_compressor_zstd_write(struct archive_write_filter *,
const void *, size_t);
+static int archive_compressor_zstd_flush(struct archive_write_filter *);
static int archive_compressor_zstd_close(struct archive_write_filter *);
static int archive_compressor_zstd_free(struct archive_write_filter *);
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
static int drive_compressor(struct archive_write_filter *,
struct private_data *, int, const void *, size_t);
#endif
@@ -102,12 +118,19 @@ archive_write_add_filter_zstd(struct archive *_a)
f->data = data;
f->open = &archive_compressor_zstd_open;
f->options = &archive_compressor_zstd_options;
+ f->flush = &archive_compressor_zstd_flush;
f->close = &archive_compressor_zstd_close;
f->free = &archive_compressor_zstd_free;
f->code = ARCHIVE_FILTER_ZSTD;
f->name = "zstd";
data->compression_level = CLEVEL_DEFAULT;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ data->threads = 0;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ data->frame_per_file = 0;
+ data->min_frame_size = 0;
+ data->max_frame_size = SIZE_MAX;
+ data->cur_frame_in = 0;
+ data->cur_frame_out = 0;
data->cstream = ZSTD_createCStream();
if (data->cstream == NULL) {
free(data);
@@ -134,7 +157,7 @@ static int
archive_compressor_zstd_free(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
ZSTD_freeCStream(data->cstream);
free(data->out.dst);
#else
@@ -145,29 +168,18 @@ archive_compressor_zstd_free(struct archive_write_filter *f)
return (ARCHIVE_OK);
}
-static int string_is_numeric (const char* value)
+static int string_to_number(const char *string, intmax_t *numberp)
{
- size_t len = strlen(value);
- size_t i;
-
- if (len == 0) {
- return (ARCHIVE_WARN);
- }
- else if (len == 1 && !(value[0] >= '0' && value[0] <= '9')) {
- return (ARCHIVE_WARN);
- }
- else if (!(value[0] >= '0' && value[0] <= '9') &&
- value[0] != '-' && value[0] != '+') {
- return (ARCHIVE_WARN);
- }
-
- for (i = 1; i < len; i++) {
- if (!(value[i] >= '0' && value[i] <= '9')) {
- return (ARCHIVE_WARN);
- }
- }
-
- return (ARCHIVE_OK);
+ char *end;
+
+ if (string == NULL || *string == '\0')
+ return (ARCHIVE_WARN);
+ *numberp = strtoimax(string, &end, 10);
+ if (end == string || *end != '\0' || errno == EOVERFLOW) {
+ *numberp = 0;
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
}
/*
@@ -180,14 +192,14 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
struct private_data *data = (struct private_data *)f->data;
if (strcmp(key, "compression-level") == 0) {
- int level = atoi(value);
+ intmax_t level;
+ if (string_to_number(value, &level) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
/* If we don't have the library, hard-code the max level */
int minimum = CLEVEL_MIN;
int maximum = CLEVEL_MAX;
- if (string_is_numeric(value) != ARCHIVE_OK) {
- return (ARCHIVE_WARN);
- }
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
maximum = ZSTD_maxCLevel();
#if ZSTD_VERSION_NUMBER >= MINVER_MINCLEVEL
if (ZSTD_versionNumber() >= MINVER_MINCLEVEL) {
@@ -202,8 +214,43 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
if (level < minimum || level > maximum) {
return (ARCHIVE_WARN);
}
- data->compression_level = level;
+ data->compression_level = (int)level;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "threads") == 0) {
+ intmax_t threads;
+ if (string_to_number(value, &threads) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
+ if (threads < 0) {
+ return (ARCHIVE_WARN);
+ }
+ data->threads = (int)threads;
return (ARCHIVE_OK);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ } else if (strcmp(key, "frame-per-file") == 0) {
+ data->frame_per_file = 1;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "min-frame-size") == 0) {
+ intmax_t min_frame_size;
+ if (string_to_number(value, &min_frame_size) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
+ if (min_frame_size < 0) {
+ return (ARCHIVE_WARN);
+ }
+ data->min_frame_size = min_frame_size;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "max-frame-size") == 0) {
+ intmax_t max_frame_size;
+ if (string_to_number(value, &max_frame_size) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
+ if (max_frame_size < 1024) {
+ return (ARCHIVE_WARN);
+ }
+ data->max_frame_size = max_frame_size;
+ return (ARCHIVE_OK);
+#endif
}
/* Note: The "warn" return is just to inform the options
@@ -212,7 +259,7 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
return (ARCHIVE_WARN);
}
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
/*
* Setup callback.
*/
@@ -252,6 +299,8 @@ archive_compressor_zstd_open(struct archive_write_filter *f)
return (ARCHIVE_FATAL);
}
+ ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_nbWorkers, data->threads);
+
return (ARCHIVE_OK);
}
@@ -263,15 +312,22 @@ archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
size_t length)
{
struct private_data *data = (struct private_data *)f->data;
- int ret;
- /* Update statistics */
- data->total_in += length;
+ return (drive_compressor(f, data, 0, buff, length));
+}
- if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK)
- return (ret);
+/*
+ * Flush the compressed stream.
+ */
+static int
+archive_compressor_zstd_flush(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
- return (ARCHIVE_OK);
+ if (data->frame_per_file && data->state == running &&
+ data->cur_frame_out > data->min_frame_size)
+ data->state = finishing;
+ return (drive_compressor(f, data, 1, NULL, 0));
}
/*
@@ -282,60 +338,75 @@ archive_compressor_zstd_close(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
- /* Finish zstd frame */
- return drive_compressor(f, data, 1, NULL, 0);
+ if (data->state == running)
+ data->state = finishing;
+ return (drive_compressor(f, data, 1, NULL, 0));
}
/*
* Utility function to push input data through compressor,
* writing full output blocks as necessary.
- *
- * Note that this handles both the regular write case (finishing ==
- * false) and the end-of-archive case (finishing == true).
*/
static int
drive_compressor(struct archive_write_filter *f,
- struct private_data *data, int finishing, const void *src, size_t length)
+ struct private_data *data, int flush, const void *src, size_t length)
{
- ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 };
+ ZSTD_inBuffer in = { .src = src, .size = length, .pos = 0 };
+ size_t ipos, opos, zstdret = 0;
+ int ret;
for (;;) {
- if (data->out.pos == data->out.size) {
- const int ret = __archive_write_filter(f->next_filter,
- data->out.dst, data->out.size);
+ ipos = in.pos;
+ opos = data->out.pos;
+ switch (data->state) {
+ case running:
+ if (in.pos == in.size)
+ return (ARCHIVE_OK);
+ zstdret = ZSTD_compressStream(data->cstream,
+ &data->out, &in);
+ if (ZSTD_isError(zstdret))
+ goto zstd_fatal;
+ break;
+ case finishing:
+ zstdret = ZSTD_endStream(data->cstream, &data->out);
+ if (ZSTD_isError(zstdret))
+ goto zstd_fatal;
+ if (zstdret == 0)
+ data->state = resetting;
+ break;
+ case resetting:
+ ZSTD_CCtx_reset(data->cstream, ZSTD_reset_session_only);
+ data->cur_frame++;
+ data->cur_frame_in = 0;
+ data->cur_frame_out = 0;
+ data->state = running;
+ break;
+ }
+ data->total_in += in.pos - ipos;
+ data->cur_frame_in += in.pos - ipos;
+ data->cur_frame_out += data->out.pos - opos;
+ if (data->state == running &&
+ data->cur_frame_in >= data->max_frame_size) {
+ data->state = finishing;
+ }
+ if (data->out.pos == data->out.size ||
+ (flush && data->out.pos > 0)) {
+ ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.pos);
if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ goto fatal;
data->out.pos = 0;
}
-
- /* If there's nothing to do, we're done. */
- if (!finishing && in.pos == in.size)
- return (ARCHIVE_OK);
-
- {
- const size_t zstdret = !finishing ?
- ZSTD_compressStream(data->cstream, &data->out, &in)
- : ZSTD_endStream(data->cstream, &data->out);
-
- if (ZSTD_isError(zstdret)) {
- archive_set_error(f->archive,
- ARCHIVE_ERRNO_MISC,
- "Zstd compression failed: %s",
- ZSTD_getErrorName(zstdret));
- return (ARCHIVE_FATAL);
- }
-
- /* If we're finishing, 0 means nothing left to flush */
- if (finishing && zstdret == 0) {
- const int ret = __archive_write_filter(f->next_filter,
- data->out.dst, data->out.pos);
- return (ret);
- }
- }
}
+zstd_fatal:
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Zstd compression failed: %s",
+ ZSTD_getErrorName(zstdret));
+fatal:
+ return (ARCHIVE_FATAL);
}
-#else /* HAVE_ZSTD_H && HAVE_LIBZSTD */
+#else /* HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR */
static int
archive_compressor_zstd_open(struct archive_write_filter *f)
@@ -349,23 +420,19 @@ archive_compressor_zstd_open(struct archive_write_filter *f)
archive_strcpy(&as, "zstd --no-check");
if (data->compression_level < CLEVEL_STD_MIN) {
- struct archive_string as2;
- archive_string_init(&as2);
- archive_string_sprintf(&as2, " --fast=%d", -data->compression_level);
- archive_string_concat(&as, &as2);
- archive_string_free(&as2);
+ archive_string_sprintf(&as, " --fast=%d", -data->compression_level);
} else {
- struct archive_string as2;
- archive_string_init(&as2);
- archive_string_sprintf(&as2, " -%d", data->compression_level);
- archive_string_concat(&as, &as2);
- archive_string_free(&as2);
+ archive_string_sprintf(&as, " -%d", data->compression_level);
}
if (data->compression_level > CLEVEL_STD_MAX) {
archive_strcat(&as, " --ultra");
}
+ if (data->threads != 0) {
+ archive_string_sprintf(&as, " --threads=%d", data->threads);
+ }
+
f->write = archive_compressor_zstd_write;
r = __archive_write_program_open(f, data->pdata, as.s);
archive_string_free(&as);
@@ -382,6 +449,14 @@ archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
}
static int
+archive_compressor_zstd_flush(struct archive_write_filter *f)
+{
+ (void)f; /* UNUSED */
+
+ return (ARCHIVE_OK);
+}
+
+static int
archive_compressor_zstd_close(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
@@ -389,4 +464,4 @@ archive_compressor_zstd_close(struct archive_write_filter *f)
return __archive_write_program_close(f, data->pdata);
}
-#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD */
+#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR */
diff --git a/src/libs/3rdparty/libarchive/archive_write_disk_posix.c b/src/libs/3rdparty/libarchive/archive_write_disk_posix.c
index 7e32fca92..c8c2e1058 100644
--- a/src/libs/3rdparty/libarchive/archive_write_disk_posix.c
+++ b/src/libs/3rdparty/libarchive/archive_write_disk_posix.c
@@ -173,6 +173,7 @@ struct fixup_entry {
struct fixup_entry *next;
struct archive_acl acl;
mode_t mode;
+ __LA_MODE_T filetype;
int64_t atime;
int64_t birthtime;
int64_t mtime;
@@ -357,10 +358,11 @@ struct archive_write_disk {
static int la_opendirat(int, const char *);
static int la_mktemp(struct archive_write_disk *);
+static int la_verify_filetype(mode_t, __LA_MODE_T);
static void fsobj_error(int *, struct archive_string *, int, const char *,
const char *);
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
- int);
+ int, int);
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
static struct fixup_entry *current_fixup(struct archive_write_disk *,
@@ -395,8 +397,7 @@ static int set_times_from_entry(struct archive_write_disk *);
static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
static ssize_t write_data_block(struct archive_write_disk *,
const char *, size_t);
-
-static struct archive_vtable *archive_write_disk_vtable(void);
+static void close_file_descriptor(struct archive_write_disk *);
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
@@ -465,6 +466,39 @@ la_opendirat(int fd, const char *path) {
}
static int
+la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
+ int ret = 0;
+
+ switch (filetype) {
+ case AE_IFREG:
+ ret = (S_ISREG(mode));
+ break;
+ case AE_IFDIR:
+ ret = (S_ISDIR(mode));
+ break;
+ case AE_IFLNK:
+ ret = (S_ISLNK(mode));
+ break;
+ case AE_IFSOCK:
+ ret = (S_ISSOCK(mode));
+ break;
+ case AE_IFCHR:
+ ret = (S_ISCHR(mode));
+ break;
+ case AE_IFBLK:
+ ret = (S_ISBLK(mode));
+ break;
+ case AE_IFIFO:
+ ret = (S_ISFIFO(mode));
+ break;
+ default:
+ break;
+ }
+
+ return (ret);
+}
+
+static int
lazy_stat(struct archive_write_disk *a)
{
if (a->pst != NULL) {
@@ -481,7 +515,12 @@ lazy_stat(struct archive_write_disk *a)
* XXX At this point, symlinks should not be hit, otherwise
* XXX a race occurred. Do we want to check explicitly for that?
*/
- if (lstat(a->name, &a->st) == 0) {
+#ifdef HAVE_LSTAT
+ if (lstat(a->name, &a->st) == 0)
+#else
+ if (la_stat(a->name, &a->st) == 0)
+#endif
+ {
a->pst = &a->st;
return (ARCHIVE_OK);
}
@@ -489,25 +528,16 @@ lazy_stat(struct archive_write_disk *a)
return (ARCHIVE_WARN);
}
-static struct archive_vtable *
-archive_write_disk_vtable(void)
-{
- static struct archive_vtable av;
- static int inited = 0;
-
- if (!inited) {
- av.archive_close = _archive_write_disk_close;
- av.archive_filter_bytes = _archive_write_disk_filter_bytes;
- av.archive_free = _archive_write_disk_free;
- av.archive_write_header = _archive_write_disk_header;
- av.archive_write_finish_entry
- = _archive_write_disk_finish_entry;
- av.archive_write_data = _archive_write_disk_data;
- av.archive_write_data_block = _archive_write_disk_data_block;
- inited = 1;
- }
- return (&av);
-}
+static const struct archive_vtable
+archive_write_disk_vtable = {
+ .archive_close = _archive_write_disk_close,
+ .archive_filter_bytes = _archive_write_disk_filter_bytes,
+ .archive_free = _archive_write_disk_free,
+ .archive_write_header = _archive_write_disk_header,
+ .archive_write_finish_entry = _archive_write_disk_finish_entry,
+ .archive_write_data = _archive_write_disk_data,
+ .archive_write_data_block = _archive_write_disk_data_block,
+};
static int64_t
_archive_write_disk_filter_bytes(struct archive *_a, int n)
@@ -822,6 +852,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->fixup |= TODO_MODE_BASE;
fe->mode = a->mode;
}
@@ -832,6 +863,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->mode = a->mode;
fe->fixup |= TODO_TIMES;
if (archive_entry_atime_is_set(entry)) {
@@ -865,6 +897,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->fixup |= TODO_ACLS;
archive_acl_copy(&fe->acl, archive_entry_acl(entry));
}
@@ -877,6 +910,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->mac_metadata = malloc(metadata_size);
if (fe->mac_metadata != NULL) {
memcpy(fe->mac_metadata, metadata,
@@ -891,6 +925,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
fe = current_fixup(a, archive_entry_pathname(entry));
if (fe == NULL)
return (ARCHIVE_FATAL);
+ fe->filetype = archive_entry_filetype(entry);
fe->fixup |= TODO_FFLAGS;
/* TODO: Complete this.. defer fflags from below. */
}
@@ -1576,12 +1611,12 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
"Seek failed");
return (ARCHIVE_FATAL);
} else if (a->offset > a->fd_offset) {
- int64_t skip = a->offset - a->fd_offset;
+ uint64_t skip = a->offset - a->fd_offset;
char nullblock[1024];
memset(nullblock, 0, sizeof(nullblock));
while (skip > 0) {
- if (skip > (int64_t)sizeof(nullblock))
+ if (skip > sizeof(nullblock))
bytes_written = hfs_write_decmpfs_block(
a, nullblock, sizeof(nullblock));
else
@@ -1696,8 +1731,10 @@ _archive_write_disk_finish_entry(struct archive *_a)
else
r = hfs_write_data_block(
a, null_d, a->file_remaining_bytes);
- if (r < 0)
+ if (r < 0) {
+ close_file_descriptor(a);
return ((int)r);
+ }
}
#endif
} else {
@@ -1706,6 +1743,7 @@ _archive_write_disk_finish_entry(struct archive *_a)
a->filesize == 0) {
archive_set_error(&a->archive, errno,
"File size could not be restored");
+ close_file_descriptor(a);
return (ARCHIVE_FAILED);
}
#endif
@@ -1715,8 +1753,10 @@ _archive_write_disk_finish_entry(struct archive *_a)
* to see what happened.
*/
a->pst = NULL;
- if ((ret = lazy_stat(a)) != ARCHIVE_OK)
- return (ret);
+ if ((ret = lazy_stat(a)) != ARCHIVE_OK) {
+ close_file_descriptor(a);
+ return (ret);
+ }
/* We can use lseek()/write() to extend the file if
* ftruncate didn't work or isn't available. */
if (a->st.st_size < a->filesize) {
@@ -1724,11 +1764,13 @@ _archive_write_disk_finish_entry(struct archive *_a)
if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
archive_set_error(&a->archive, errno,
"Seek failed");
+ close_file_descriptor(a);
return (ARCHIVE_FATAL);
}
if (write(a->fd, &nul, 1) < 0) {
archive_set_error(&a->archive, errno,
"Write to restore size failed");
+ close_file_descriptor(a);
return (ARCHIVE_FATAL);
}
a->pst = NULL;
@@ -1956,7 +1998,7 @@ archive_write_disk_new(void)
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
/* We're ready to write a header immediately. */
a->archive.state = ARCHIVE_STATE_HEADER;
- a->archive.vtable = archive_write_disk_vtable();
+ a->archive.vtable = &archive_write_disk_vtable;
a->start_time = time(NULL);
/* Query and restore the umask. */
umask(a->user_umask = umask(0));
@@ -1967,6 +2009,8 @@ archive_write_disk_new(void)
free(a);
return (NULL);
}
+ a->path_safe.s[0] = 0;
+
#ifdef HAVE_ZLIB_H
a->decmpfs_compression_level = 5;
#endif
@@ -2123,7 +2167,11 @@ restore_entry(struct archive_write_disk *a)
* then don't follow it.
*/
if (r != 0 || !S_ISDIR(a->mode))
+#ifdef HAVE_LSTAT
r = lstat(a->name, &a->st);
+#else
+ r = la_stat(a->name, &a->st);
+#endif
if (r != 0) {
archive_set_error(&a->archive, errno,
"Can't stat existing object");
@@ -2263,7 +2311,7 @@ create_filesystem_object(struct archive_write_disk *a)
return (EPERM);
}
r = check_symlinks_fsobj(linkname_copy, &error_number,
- &error_string, a->flags);
+ &error_string, a->flags, 1);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, error_number, "%s",
error_string.s);
@@ -2284,7 +2332,12 @@ create_filesystem_object(struct archive_write_disk *a)
*/
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
unlink(a->name);
+#ifdef HAVE_LINKAT
+ r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name,
+ 0) ? errno : 0;
+#else
r = link(linkname, a->name) ? errno : 0;
+#endif
/*
* New cpio and pax formats allow hardlink entries
* to carry data, so we may have to open the file
@@ -2456,7 +2509,9 @@ _archive_write_disk_close(struct archive *_a)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
struct fixup_entry *next, *p;
- int fd, ret;
+ struct stat st;
+ char *c;
+ int fd, ret, openflags;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
@@ -2469,10 +2524,80 @@ _archive_write_disk_close(struct archive *_a)
while (p != NULL) {
fd = -1;
a->pst = NULL; /* Mark stat cache as out-of-date. */
- if (p->fixup &
- (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
- fd = open(p->name,
- O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
+
+ /* We must strip trailing slashes from the path to avoid
+ dereferencing symbolic links to directories */
+ c = p->name;
+ while (*c != '\0')
+ c++;
+ while (c != p->name && *(c - 1) == '/') {
+ c--;
+ *c = '\0';
+ }
+
+ if (p->fixup == 0)
+ goto skip_fixup_entry;
+ else {
+ /*
+ * We need to verify if the type of the file
+ * we are going to open matches the file type
+ * of the fixup entry.
+ */
+ openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
+ | O_CLOEXEC;
+#if defined(O_DIRECTORY)
+ if (p->filetype == AE_IFDIR)
+ openflags |= O_DIRECTORY;
+#endif
+ fd = open(p->name, openflags);
+
+#if defined(O_DIRECTORY)
+ /*
+ * If we support O_DIRECTORY and open was
+ * successful we can skip the file type check
+ * for directories. For other file types
+ * we need to verify via fstat() or lstat()
+ */
+ if (fd == -1 || p->filetype != AE_IFDIR) {
+#if HAVE_FSTAT
+ if (fd > 0 && (
+ fstat(fd, &st) != 0 ||
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0)) {
+ goto skip_fixup_entry;
+ } else
+#endif
+ if (
+#ifdef HAVE_LSTAT
+ lstat(p->name, &st) != 0 ||
+#else
+ la_stat(p->name, &st) != 0 ||
+#endif
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0) {
+ goto skip_fixup_entry;
+ }
+ }
+#else
+#if HAVE_FSTAT
+ if (fd > 0 && (
+ fstat(fd, &st) != 0 ||
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0)) {
+ goto skip_fixup_entry;
+ } else
+#endif
+ if (
+#ifdef HAVE_LSTAT
+ lstat(p->name, &st) != 0 ||
+#else
+ la_stat(p->name, &st) != 0 ||
+#endif
+ la_verify_filetype(st.st_mode,
+ p->filetype) == 0) {
+ goto skip_fixup_entry;
+ }
+#endif
}
if (p->fixup & TODO_TIMES) {
set_times(a, fd, p->mode, p->name,
@@ -2484,10 +2609,14 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE) {
#ifdef HAVE_FCHMOD
if (fd >= 0)
- fchmod(fd, p->mode);
+ fchmod(fd, p->mode & 07777);
else
#endif
- chmod(p->name, p->mode);
+#ifdef HAVE_LCHMOD
+ lchmod(p->name, p->mode & 07777);
+#else
+ chmod(p->name, p->mode & 07777);
+#endif
}
if (p->fixup & TODO_ACLS)
archive_write_disk_set_acls(&a->archive, fd,
@@ -2498,6 +2627,7 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MAC_METADATA)
set_mac_metadata(a, p->name, p->mac_metadata,
p->mac_metadata_size);
+skip_fixup_entry:
next = p->next;
archive_acl_clear(&p->acl);
free(p->mac_metadata);
@@ -2638,6 +2768,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
fe->next = a->fixup_list;
a->fixup_list = fe;
fe->fixup = 0;
+ fe->filetype = 0;
fe->name = strdup(pathname);
return (fe);
}
@@ -2675,22 +2806,23 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
*/
static int
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
- int flags)
+ int flags, int checking_linkname)
{
#if !defined(HAVE_LSTAT) && \
!(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
/* Platform doesn't have lstat, so we can't look for symlinks. */
(void)path; /* UNUSED */
- (void)error_number; /* UNUSED */
- (void)error_string; /* UNUSED */
+ (void)a_eno; /* UNUSED */
+ (void)a_estr; /* UNUSED */
(void)flags; /* UNUSED */
+ (void)checking_linkname; /* UNUSED */
return (ARCHIVE_OK);
#else
int res = ARCHIVE_OK;
char *tail;
char *head;
int last;
- char c;
+ char c = '\0';
int r;
struct stat st;
int chdir_fd;
@@ -2754,8 +2886,10 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
/* Check that we haven't hit a symlink. */
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW);
-#else
+#elif defined(HAVE_LSTAT)
r = lstat(head, &st);
+#else
+ r = la_stat(head, &st);
#endif
if (r != 0) {
tail[0] = c;
@@ -2805,6 +2939,28 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
head = tail + 1;
}
} else if (S_ISLNK(st.st_mode)) {
+ if (last && checking_linkname) {
+#ifdef HAVE_LINKAT
+ /*
+ * Hardlinks to symlinks are safe to write
+ * if linkat() is supported as it does not
+ * follow symlinks.
+ */
+ res = ARCHIVE_OK;
+#else
+ /*
+ * We return ARCHIVE_FAILED here as we are
+ * not able to safely write hardlinks
+ * to symlinks.
+ */
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
+ "Cannot write hardlink to symlink ",
+ path);
+ res = ARCHIVE_FAILED;
+#endif
+ break;
+ } else
if (last) {
/*
* Last element is symlink; remove it
@@ -2971,7 +3127,7 @@ check_symlinks(struct archive_write_disk *a)
int rc;
archive_string_init(&error_string);
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
- a->flags);
+ a->flags, 0);
if (rc != ARCHIVE_OK) {
archive_set_error(&a->archive, error_number, "%s",
error_string.s);
@@ -3431,7 +3587,9 @@ set_time(int fd, int mode, const char *name,
(void)fd; /* UNUSED */
(void)mode; /* UNUSED */
(void)name; /* UNUSED */
+ (void)atime; /* UNUSED */
(void)atime_nsec; /* UNUSED */
+ (void)mtime; /* UNUSED */
(void)mtime_nsec; /* UNUSED */
return (ARCHIVE_WARN);
#endif
@@ -3737,6 +3895,7 @@ set_fflags(struct archive_write_disk *a)
le = current_fixup(a, a->name);
if (le == NULL)
return (ARCHIVE_FATAL);
+ le->filetype = archive_entry_filetype(a->entry);
le->fixup |= TODO_FFLAGS;
le->fflags_set = set;
/* Store the mode if it's not already there. */
@@ -3899,7 +4058,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
/* If we weren't given an fd, open it ourselves. */
if (myfd < 0) {
- myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC);
+ myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY |
+ O_CLOEXEC | O_NOFOLLOW);
__archive_ensure_cloexec_flag(myfd);
}
if (myfd < 0)
@@ -4262,7 +4422,12 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname)
*/
archive_strncpy(&datafork, pathname, p - pathname);
archive_strcat(&datafork, p + 2);
- if (lstat(datafork.s, &st) == -1 ||
+ if (
+#ifdef HAVE_LSTAT
+ lstat(datafork.s, &st) == -1 ||
+#else
+ la_stat(datafork.s, &st) == -1 ||
+#endif
(st.st_mode & AE_IFMT) != AE_IFREG)
goto skip_appledouble;
@@ -4578,5 +4743,17 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
}
#endif
+/*
+ * Close the file descriptor if one is open.
+ */
+static void close_file_descriptor(struct archive_write_disk* a)
+{
+ if (a->fd >= 0) {
+ close(a->fd);
+ a->fd = -1;
+ }
+}
+
+
#endif /* !_WIN32 || __CYGWIN__ */
diff --git a/src/libs/3rdparty/libarchive/archive_write_disk_windows.c b/src/libs/3rdparty/libarchive/archive_write_disk_windows.c
index 0c600176c..7b9ea7493 100644
--- a/src/libs/3rdparty/libarchive/archive_write_disk_windows.c
+++ b/src/libs/3rdparty/libarchive/archive_write_disk_windows.c
@@ -213,7 +213,7 @@ static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
static struct fixup_entry *current_fixup(struct archive_write_disk *,
const wchar_t *pathname);
-static int cleanup_pathname(struct archive_write_disk *);
+static int cleanup_pathname(struct archive_write_disk *, wchar_t *);
static int create_dir(struct archive_write_disk *, wchar_t *);
static int create_parent_dir(struct archive_write_disk *, wchar_t *);
static int la_chmod(const wchar_t *, mode_t);
@@ -238,8 +238,6 @@ static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
static ssize_t write_data_block(struct archive_write_disk *,
const char *, size_t);
-static struct archive_vtable *archive_write_disk_vtable(void);
-
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
static int _archive_write_disk_header(struct archive *,
@@ -256,9 +254,9 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
* which is high-16-bits of nFileIndexHigh. */
#define bhfi_ino(bhfi) \
((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \
- + (bhfi)->nFileIndexLow)
+ | (bhfi)->nFileIndexLow)
#define bhfi_size(bhfi) \
- ((((int64_t)(bhfi)->nFileSizeHigh) << 32) + (bhfi)->nFileSizeLow)
+ ((((int64_t)(bhfi)->nFileSizeHigh) << 32) | (bhfi)->nFileSizeLow)
static int
file_information(struct archive_write_disk *a, wchar_t *path,
@@ -268,6 +266,9 @@ file_information(struct archive_write_disk *a, wchar_t *path,
int r;
DWORD flag = FILE_FLAG_BACKUP_SEMANTICS;
WIN32_FIND_DATAW findData;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
if (sim_lstat || mode != NULL) {
h = FindFirstFileW(path, &findData);
@@ -292,14 +293,27 @@ file_information(struct archive_write_disk *a, wchar_t *path,
(findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)))
flag |= FILE_FLAG_OPEN_REPARSE_POINT;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = flag;
+ h = CreateFile2(a->name, 0, 0,
+ OPEN_EXISTING, &createExParams);
+#else
h = CreateFileW(a->name, 0, 0, NULL,
OPEN_EXISTING, flag, NULL);
+#endif
if (h == INVALID_HANDLE_VALUE &&
GetLastError() == ERROR_INVALID_NAME) {
wchar_t *full;
full = __la_win_permissive_name_w(path);
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ h = CreateFile2(full, 0, 0,
+ OPEN_EXISTING, &createExParams);
+#else
h = CreateFileW(full, 0, 0, NULL,
OPEN_EXISTING, flag, NULL);
+#endif
free(full);
}
if (h == INVALID_HANDLE_VALUE) {
@@ -561,6 +575,7 @@ la_mktemp(struct archive_write_disk *a)
return (fd);
}
+#if _WIN32_WINNT < _WIN32_WINNT_VISTA
static void *
la_GetFunctionKernel32(const char *name)
{
@@ -576,18 +591,24 @@ la_GetFunctionKernel32(const char *name)
}
return (void *)GetProcAddress(lib, name);
}
+#endif
static int
la_CreateHardLinkW(wchar_t *linkname, wchar_t *target)
{
- static BOOLEAN (WINAPI *f)(LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES);
- static int set;
+ static BOOL (WINAPI *f)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
BOOL ret;
+#if _WIN32_WINNT < _WIN32_WINNT_XP
+ static int set;
+/* CreateHardLinkW is available since XP and always loaded */
if (!set) {
set = 1;
f = la_GetFunctionKernel32("CreateHardLinkW");
}
+#else
+ f = CreateHardLinkW;
+#endif
if (!f) {
errno = ENOTSUP;
return (0);
@@ -626,18 +647,27 @@ static int
la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target,
int linktype) {
static BOOLEAN (WINAPI *f)(LPCWSTR, LPCWSTR, DWORD);
- static int set;
wchar_t *ttarget, *p;
- int len;
+ size_t len;
DWORD attrs = 0;
DWORD flags = 0;
DWORD newflags = 0;
BOOL ret = 0;
+#if _WIN32_WINNT < _WIN32_WINNT_VISTA
+/* CreateSymbolicLinkW is available since Vista and always loaded */
+ static int set;
if (!set) {
set = 1;
f = la_GetFunctionKernel32("CreateSymbolicLinkW");
}
+#else
+# if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+ f = CreateSymbolicLinkW;
+# else
+ f = NULL;
+# endif
+#endif
if (!f)
return (0);
@@ -759,25 +789,16 @@ lazy_stat(struct archive_write_disk *a)
return (ARCHIVE_WARN);
}
-static struct archive_vtable *
-archive_write_disk_vtable(void)
-{
- static struct archive_vtable av;
- static int inited = 0;
-
- if (!inited) {
- av.archive_close = _archive_write_disk_close;
- av.archive_filter_bytes = _archive_write_disk_filter_bytes;
- av.archive_free = _archive_write_disk_free;
- av.archive_write_header = _archive_write_disk_header;
- av.archive_write_finish_entry
- = _archive_write_disk_finish_entry;
- av.archive_write_data = _archive_write_disk_data;
- av.archive_write_data_block = _archive_write_disk_data_block;
- inited = 1;
- }
- return (&av);
-}
+static const struct archive_vtable
+archive_write_disk_vtable = {
+ .archive_close = _archive_write_disk_close,
+ .archive_filter_bytes = _archive_write_disk_filter_bytes,
+ .archive_free = _archive_write_disk_free,
+ .archive_write_header = _archive_write_disk_header,
+ .archive_write_finish_entry = _archive_write_disk_finish_entry,
+ .archive_write_data = _archive_write_disk_data,
+ .archive_write_data_block = _archive_write_disk_data_block,
+};
static int64_t
_archive_write_disk_filter_bytes(struct archive *_a, int n)
@@ -854,7 +875,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
* dir restores; the dir restore logic otherwise gets messed
* up by nonsense like "dir/.".
*/
- ret = cleanup_pathname(a);
+ ret = cleanup_pathname(a, a->name);
if (ret != ARCHIVE_OK)
return (ret);
@@ -1196,6 +1217,8 @@ _archive_write_disk_finish_entry(struct archive *_a)
if (la_ftruncate(a->fh, a->filesize) == -1) {
archive_set_error(&a->archive, errno,
"File size could not be restored");
+ CloseHandle(a->fh);
+ a->fh = INVALID_HANDLE_VALUE;
return (ARCHIVE_FAILED);
}
}
@@ -1373,7 +1396,7 @@ archive_write_disk_new(void)
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
/* We're ready to write a header immediately. */
a->archive.state = ARCHIVE_STATE_HEADER;
- a->archive.vtable = archive_write_disk_vtable();
+ a->archive.vtable = &archive_write_disk_vtable;
a->start_time = time(NULL);
/* Query and restore the umask. */
umask(a->user_umask = umask(0));
@@ -1381,6 +1404,7 @@ archive_write_disk_new(void)
free(a);
return (NULL);
}
+ a->path_safe.s[0] = 0;
return (&a->archive);
}
@@ -1666,14 +1690,30 @@ create_filesystem_object(struct archive_write_disk *a)
mode_t final_mode, mode;
int r;
DWORD attrs = 0;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
/* We identify hard/symlinks according to the link names. */
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
linkname = archive_entry_hardlink_w(a->entry);
if (linkname != NULL) {
- wchar_t *linkfull, *namefull;
-
- linkfull = __la_win_permissive_name_w(linkname);
+ wchar_t *linksanitized, *linkfull, *namefull;
+ size_t l = (wcslen(linkname) + 1) * sizeof(wchar_t);
+ linksanitized = malloc(l);
+ if (linksanitized == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for hardlink target");
+ return (-1);
+ }
+ memcpy(linksanitized, linkname, l);
+ r = cleanup_pathname(a, linksanitized);
+ if (r != ARCHIVE_OK) {
+ free(linksanitized);
+ return (r);
+ }
+ linkfull = __la_win_permissive_name_w(linksanitized);
+ free(linksanitized);
namefull = __la_win_permissive_name_w(a->name);
if (linkfull == NULL || namefull == NULL) {
errno = EINVAL;
@@ -1716,8 +1756,16 @@ create_filesystem_object(struct archive_write_disk *a)
a->todo = 0;
a->deferred = 0;
} else if (r == 0 && a->filesize > 0) {
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ a->fh = CreateFile2(namefull, GENERIC_WRITE, 0,
+ TRUNCATE_EXISTING, &createExParams);
+#else
a->fh = CreateFileW(namefull, GENERIC_WRITE, 0, NULL,
TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
if (a->fh == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
r = errno;
@@ -1780,14 +1828,27 @@ create_filesystem_object(struct archive_write_disk *a)
a->tmpname = NULL;
fullname = a->name;
/* O_WRONLY | O_CREAT | O_EXCL */
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ a->fh = CreateFile2(fullname, GENERIC_WRITE, 0,
+ CREATE_NEW, &createExParams);
+#else
a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
if (a->fh == INVALID_HANDLE_VALUE &&
GetLastError() == ERROR_INVALID_NAME &&
fullname == a->name) {
fullname = __la_win_permissive_name_w(a->name);
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ a->fh = CreateFile2(fullname, GENERIC_WRITE, 0,
+ CREATE_NEW, &createExParams);
+#else
a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif
}
if (a->fh == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_ACCESS_DENIED) {
@@ -2152,6 +2213,8 @@ check_symlinks(struct archive_write_disk *a)
return (ARCHIVE_FAILED);
}
}
+ if (!c)
+ break;
pn[0] = c;
pn++;
}
@@ -2184,12 +2247,12 @@ guidword(wchar_t *p, int n)
* set) any '..' in the path.
*/
static int
-cleanup_pathname(struct archive_write_disk *a)
+cleanup_pathname(struct archive_write_disk *a, wchar_t *name)
{
wchar_t *dest, *src, *p, *top;
wchar_t separator = L'\0';
- p = a->name;
+ p = name;
if (*p == L'\0') {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid empty pathname");
@@ -2201,7 +2264,7 @@ cleanup_pathname(struct archive_write_disk *a)
if (*p == L'/')
*p = L'\\';
}
- p = a->name;
+ p = name;
/* Skip leading "\\.\" or "\\?\" or "\\?\UNC\" or
* "\\?\Volume{GUID}\"
@@ -2256,6 +2319,9 @@ cleanup_pathname(struct archive_write_disk *a)
return (ARCHIVE_FAILED);
} else
p += 4;
+ /* Network drive path like "\\<server-name>\<share-name>\file" */
+ } else if (p[0] == L'\\' && p[1] == L'\\') {
+ p += 2;
}
/* Skip leading drive letter from archives created
@@ -2543,14 +2609,25 @@ set_times(struct archive_write_disk *a,
hw = NULL;
} else {
wchar_t *ws;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
if (S_ISLNK(mode))
return (ARCHIVE_OK);
ws = __la_win_permissive_name_w(name);
if (ws == NULL)
goto settimes_failed;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
+ hw = CreateFile2(ws, FILE_WRITE_ATTRIBUTES, 0,
+ OPEN_EXISTING, &createExParams);
+#else
hw = CreateFileW(ws, FILE_WRITE_ATTRIBUTES,
0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+#endif
free(ws);
if (hw == INVALID_HANDLE_VALUE)
goto settimes_failed;
diff --git a/src/libs/3rdparty/libarchive/archive_write_private.h b/src/libs/3rdparty/libarchive/archive_write_private.h
index 155fdd734..6522e6521 100644
--- a/src/libs/3rdparty/libarchive/archive_write_private.h
+++ b/src/libs/3rdparty/libarchive/archive_write_private.h
@@ -53,6 +53,7 @@ struct archive_write_filter {
const char *key, const char *value);
int (*open)(struct archive_write_filter *);
int (*write)(struct archive_write_filter *, const void *, size_t);
+ int (*flush)(struct archive_write_filter *);
int (*close)(struct archive_write_filter *);
int (*free)(struct archive_write_filter *);
void *data;
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format.c b/src/libs/3rdparty/libarchive/archive_write_set_format.c
index 7dbe7b9a2..1f65fa4a7 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format.c
@@ -44,7 +44,9 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
{ ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio },
- { ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio },
+ { ARCHIVE_FORMAT_CPIO_BIN_LE, archive_write_set_format_cpio_bin },
+ { ARCHIVE_FORMAT_CPIO_PWB, archive_write_set_format_cpio_pwb },
+ { ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio_odc },
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_7zip.c b/src/libs/3rdparty/libarchive/archive_write_set_format_7zip.c
index f3a7446a0..1e40601c4 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_7zip.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_7zip.c
@@ -165,7 +165,7 @@ struct file {
mode_t mode;
uint32_t crc32;
- signed int dir:1;
+ unsigned dir:1;
};
struct _7zip {
@@ -755,6 +755,10 @@ _7z_close(struct archive_write *a)
*/
#if HAVE_LZMA_H
header_compression = _7Z_LZMA1;
+ if(zip->opt_compression == _7Z_LZMA2 ||
+ zip->opt_compression == _7Z_COPY)
+ header_compression = zip->opt_compression;
+
/* If the stored file is only one, do not encode the header.
* This is the same way 7z command does. */
if (zip->total_number_entry == 1)
@@ -762,7 +766,8 @@ _7z_close(struct archive_write *a)
#else
header_compression = _7Z_COPY;
#endif
- r = _7z_compression_init_encoder(a, header_compression, 6);
+ r = _7z_compression_init_encoder(a, header_compression,
+ zip->opt_compression_level);
if (r < 0)
return (r);
zip->crc32flg = PRECODE_CRC32;
@@ -1804,11 +1809,11 @@ compression_init_encoder_bzip2(struct archive *a,
* of ugly hackery to convert a const * pointer to
* a non-const pointer. */
strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
- strm->avail_in = lastrm->avail_in;
+ strm->avail_in = (uint32_t)lastrm->avail_in;
strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
strm->next_out = (char *)lastrm->next_out;
- strm->avail_out = lastrm->avail_out;
+ strm->avail_out = (uint32_t)lastrm->avail_out;
strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
@@ -1837,11 +1842,11 @@ compression_code_bzip2(struct archive *a,
* of ugly hackery to convert a const * pointer to
* a non-const pointer. */
strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
- strm->avail_in = lastrm->avail_in;
+ strm->avail_in = (uint32_t)lastrm->avail_in;
strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
strm->next_out = (char *)lastrm->next_out;
- strm->avail_out = lastrm->avail_out;
+ strm->avail_out = (uint32_t)lastrm->avail_out;
strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
r = BZ2_bzCompress(strm,
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_by_name.c b/src/libs/3rdparty/libarchive/archive_write_set_format_by_name.c
index 86e8621ef..bfb4b3545 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_by_name.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_by_name.c
@@ -49,6 +49,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "arbsd", archive_write_set_format_ar_bsd },
{ "argnu", archive_write_set_format_ar_svr4 },
{ "arsvr4", archive_write_set_format_ar_svr4 },
+ { "bin", archive_write_set_format_cpio_bin },
{ "bsdtar", archive_write_set_format_pax_restricted },
{ "cd9660", archive_write_set_format_iso9660 },
{ "cpio", archive_write_set_format_cpio },
@@ -58,11 +59,12 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "mtree", archive_write_set_format_mtree },
{ "mtree-classic", archive_write_set_format_mtree_classic },
{ "newc", archive_write_set_format_cpio_newc },
- { "odc", archive_write_set_format_cpio },
+ { "odc", archive_write_set_format_cpio_odc },
{ "oldtar", archive_write_set_format_v7tar },
{ "pax", archive_write_set_format_pax },
{ "paxr", archive_write_set_format_pax_restricted },
{ "posix", archive_write_set_format_pax },
+ { "pwb", archive_write_set_format_cpio_pwb },
{ "raw", archive_write_set_format_raw },
{ "rpax", archive_write_set_format_pax_restricted },
{ "shar", archive_write_set_format_shar },
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_cpio.c b/src/libs/3rdparty/libarchive/archive_write_set_format_cpio.c
index e06673352..47152cc6a 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_cpio.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_cpio.c
@@ -1,500 +1,11 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011-2012 Michihiro NAKAJIMA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
#include "archive_platform.h"
-__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
#include "archive.h"
-#include "archive_entry.h"
-#include "archive_entry_locale.h"
-#include "archive_private.h"
-#include "archive_write_private.h"
-#include "archive_write_set_format_private.h"
-
-static ssize_t archive_write_cpio_data(struct archive_write *,
- const void *buff, size_t s);
-static int archive_write_cpio_close(struct archive_write *);
-static int archive_write_cpio_free(struct archive_write *);
-static int archive_write_cpio_finish_entry(struct archive_write *);
-static int archive_write_cpio_header(struct archive_write *,
- struct archive_entry *);
-static int archive_write_cpio_options(struct archive_write *,
- const char *, const char *);
-static int format_octal(int64_t, void *, int);
-static int64_t format_octal_recursive(int64_t, char *, int);
-static int write_header(struct archive_write *, struct archive_entry *);
-
-struct cpio {
- uint64_t entry_bytes_remaining;
-
- int64_t ino_next;
-
- struct { int64_t old; int new;} *ino_list;
- size_t ino_list_size;
- size_t ino_list_next;
-
- struct archive_string_conv *opt_sconv;
- struct archive_string_conv *sconv_default;
- int init_default_conversion;
-};
-
-#define c_magic_offset 0
-#define c_magic_size 6
-#define c_dev_offset 6
-#define c_dev_size 6
-#define c_ino_offset 12
-#define c_ino_size 6
-#define c_mode_offset 18
-#define c_mode_size 6
-#define c_uid_offset 24
-#define c_uid_size 6
-#define c_gid_offset 30
-#define c_gid_size 6
-#define c_nlink_offset 36
-#define c_nlink_size 6
-#define c_rdev_offset 42
-#define c_rdev_size 6
-#define c_mtime_offset 48
-#define c_mtime_size 11
-#define c_namesize_offset 59
-#define c_namesize_size 6
-#define c_filesize_offset 65
-#define c_filesize_size 11
/*
- * Set output format to 'cpio' format.
+ * Set output format to the default 'cpio' format.
*/
int
archive_write_set_format_cpio(struct archive *_a)
{
- struct archive_write *a = (struct archive_write *)_a;
- struct cpio *cpio;
-
- archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
- ARCHIVE_STATE_NEW, "archive_write_set_format_cpio");
-
- /* If someone else was already registered, unregister them. */
- if (a->format_free != NULL)
- (a->format_free)(a);
-
- cpio = (struct cpio *)calloc(1, sizeof(*cpio));
- if (cpio == NULL) {
- archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
- return (ARCHIVE_FATAL);
- }
- a->format_data = cpio;
- a->format_name = "cpio";
- a->format_options = archive_write_cpio_options;
- a->format_write_header = archive_write_cpio_header;
- a->format_write_data = archive_write_cpio_data;
- a->format_finish_entry = archive_write_cpio_finish_entry;
- a->format_close = archive_write_cpio_close;
- a->format_free = archive_write_cpio_free;
- a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
- a->archive.archive_format_name = "POSIX cpio";
- return (ARCHIVE_OK);
-}
-
-static int
-archive_write_cpio_options(struct archive_write *a, const char *key,
- const char *val)
-{
- struct cpio *cpio = (struct cpio *)a->format_data;
- int ret = ARCHIVE_FAILED;
-
- if (strcmp(key, "hdrcharset") == 0) {
- if (val == NULL || val[0] == 0)
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "%s: hdrcharset option needs a character-set name",
- a->format_name);
- else {
- cpio->opt_sconv = archive_string_conversion_to_charset(
- &a->archive, val, 0);
- if (cpio->opt_sconv != NULL)
- ret = ARCHIVE_OK;
- else
- ret = ARCHIVE_FATAL;
- }
- return (ret);
- }
-
- /* Note: The "warn" return is just to inform the options
- * supervisor that we didn't handle it. It will generate
- * a suitable error if no one used this option. */
- return (ARCHIVE_WARN);
-}
-
-/*
- * Ino values are as long as 64 bits on some systems; cpio format
- * only allows 18 bits and relies on the ino values to identify hardlinked
- * files. So, we can't merely "hash" the ino numbers since collisions
- * would corrupt the archive. Instead, we generate synthetic ino values
- * to store in the archive and maintain a map of original ino values to
- * synthetic ones so we can preserve hardlink information.
- *
- * TODO: Make this more efficient. It's not as bad as it looks (most
- * files don't have any hardlinks and we don't do any work here for those),
- * but it wouldn't be hard to do better.
- *
- * TODO: Work with dev/ino pairs here instead of just ino values.
- */
-static int
-synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
-{
- int64_t ino = archive_entry_ino64(entry);
- int ino_new;
- size_t i;
-
- /*
- * If no index number was given, don't assign one. In
- * particular, this handles the end-of-archive marker
- * correctly by giving it a zero index value. (This is also
- * why we start our synthetic index numbers with one below.)
- */
- if (ino == 0)
- return (0);
-
- /* Don't store a mapping if we don't need to. */
- if (archive_entry_nlink(entry) < 2) {
- return (int)(++cpio->ino_next);
- }
-
- /* Look up old ino; if we have it, this is a hardlink
- * and we reuse the same value. */
- for (i = 0; i < cpio->ino_list_next; ++i) {
- if (cpio->ino_list[i].old == ino)
- return (cpio->ino_list[i].new);
- }
-
- /* Assign a new index number. */
- ino_new = (int)(++cpio->ino_next);
-
- /* Ensure space for the new mapping. */
- if (cpio->ino_list_size <= cpio->ino_list_next) {
- size_t newsize = cpio->ino_list_size < 512
- ? 512 : cpio->ino_list_size * 2;
- void *newlist = realloc(cpio->ino_list,
- sizeof(cpio->ino_list[0]) * newsize);
- if (newlist == NULL)
- return (-1);
-
- cpio->ino_list_size = newsize;
- cpio->ino_list = newlist;
- }
-
- /* Record and return the new value. */
- cpio->ino_list[cpio->ino_list_next].old = ino;
- cpio->ino_list[cpio->ino_list_next].new = ino_new;
- ++cpio->ino_list_next;
- return (ino_new);
-}
-
-
-static struct archive_string_conv *
-get_sconv(struct archive_write *a)
-{
- struct cpio *cpio;
- struct archive_string_conv *sconv;
-
- cpio = (struct cpio *)a->format_data;
- sconv = cpio->opt_sconv;
- if (sconv == NULL) {
- if (!cpio->init_default_conversion) {
- cpio->sconv_default =
- archive_string_default_conversion_for_write(
- &(a->archive));
- cpio->init_default_conversion = 1;
- }
- sconv = cpio->sconv_default;
- }
- return (sconv);
-}
-
-static int
-archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
-{
- const char *path;
- size_t len;
-
- if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
- archive_set_error(&a->archive, -1, "Filetype required");
- return (ARCHIVE_FAILED);
- }
-
- if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
- && errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for Pathname");
- return (ARCHIVE_FATAL);
- }
- if (len == 0 || path == NULL || path[0] == '\0') {
- archive_set_error(&a->archive, -1, "Pathname required");
- return (ARCHIVE_FAILED);
- }
-
- if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
- archive_set_error(&a->archive, -1, "Size required");
- return (ARCHIVE_FAILED);
- }
- return write_header(a, entry);
-}
-
-static int
-write_header(struct archive_write *a, struct archive_entry *entry)
-{
- struct cpio *cpio;
- const char *p, *path;
- int pathlength, ret, ret_final;
- int64_t ino;
- char h[76];
- struct archive_string_conv *sconv;
- struct archive_entry *entry_main;
- size_t len;
-
- cpio = (struct cpio *)a->format_data;
- ret_final = ARCHIVE_OK;
- sconv = get_sconv(a);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pathname, hardlink and symlink
- * are all slash '/', not the Windows path separator '\'. */
- entry_main = __la_win_entry_in_posix_pathseparator(entry);
- if (entry_main == NULL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate ustar data");
- return(ARCHIVE_FATAL);
- }
- if (entry != entry_main)
- entry = entry_main;
- else
- entry_main = NULL;
-#else
- entry_main = NULL;
-#endif
-
- ret = archive_entry_pathname_l(entry, &path, &len, sconv);
- if (ret != 0) {
- if (errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for Pathname");
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- }
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate pathname '%s' to %s",
- archive_entry_pathname(entry),
- archive_string_conversion_charset_name(sconv));
- ret_final = ARCHIVE_WARN;
- }
- /* Include trailing null. */
- pathlength = (int)len + 1;
-
- memset(h, 0, sizeof(h));
- format_octal(070707, h + c_magic_offset, c_magic_size);
- format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
-
- ino = synthesize_ino_value(cpio, entry);
- if (ino < 0) {
- archive_set_error(&a->archive, ENOMEM,
- "No memory for ino translation table");
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- } else if (ino > 0777777) {
- archive_set_error(&a->archive, ERANGE,
- "Too many files for this cpio format");
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- }
- format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
-
- /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
- format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
- format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
- format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
- format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
- if (archive_entry_filetype(entry) == AE_IFBLK
- || archive_entry_filetype(entry) == AE_IFCHR)
- format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
- else
- format_octal(0, h + c_rdev_offset, c_rdev_size);
- format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
- format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
-
- /* Non-regular files don't store bodies. */
- if (archive_entry_filetype(entry) != AE_IFREG)
- archive_entry_set_size(entry, 0);
-
- /* Symlinks get the link written as the body of the entry. */
- ret = archive_entry_symlink_l(entry, &p, &len, sconv);
- if (ret != 0) {
- if (errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for Linkname");
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- }
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate linkname '%s' to %s",
- archive_entry_symlink(entry),
- archive_string_conversion_charset_name(sconv));
- ret_final = ARCHIVE_WARN;
- }
- if (len > 0 && p != NULL && *p != '\0')
- ret = format_octal(strlen(p), h + c_filesize_offset,
- c_filesize_size);
- else
- ret = format_octal(archive_entry_size(entry),
- h + c_filesize_offset, c_filesize_size);
- if (ret) {
- archive_set_error(&a->archive, ERANGE,
- "File is too large for cpio format.");
- ret_final = ARCHIVE_FAILED;
- goto exit_write_header;
- }
-
- ret = __archive_write_output(a, h, sizeof(h));
- if (ret != ARCHIVE_OK) {
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- }
-
- ret = __archive_write_output(a, path, pathlength);
- if (ret != ARCHIVE_OK) {
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- }
-
- cpio->entry_bytes_remaining = archive_entry_size(entry);
-
- /* Write the symlink now. */
- if (p != NULL && *p != '\0') {
- ret = __archive_write_output(a, p, strlen(p));
- if (ret != ARCHIVE_OK) {
- ret_final = ARCHIVE_FATAL;
- goto exit_write_header;
- }
- }
-exit_write_header:
- archive_entry_free(entry_main);
- return (ret_final);
-}
-
-static ssize_t
-archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s)
-{
- struct cpio *cpio;
- int ret;
-
- cpio = (struct cpio *)a->format_data;
- if (s > cpio->entry_bytes_remaining)
- s = (size_t)cpio->entry_bytes_remaining;
-
- ret = __archive_write_output(a, buff, s);
- cpio->entry_bytes_remaining -= s;
- if (ret >= 0)
- return (s);
- else
- return (ret);
-}
-
-/*
- * Format a number into the specified field.
- */
-static int
-format_octal(int64_t v, void *p, int digits)
-{
- int64_t max;
- int ret;
-
- max = (((int64_t)1) << (digits * 3)) - 1;
- if (v >= 0 && v <= max) {
- format_octal_recursive(v, (char *)p, digits);
- ret = 0;
- } else {
- format_octal_recursive(max, (char *)p, digits);
- ret = -1;
- }
- return (ret);
-}
-
-static int64_t
-format_octal_recursive(int64_t v, char *p, int s)
-{
- if (s == 0)
- return (v);
- v = format_octal_recursive(v, p+1, s-1);
- *p = '0' + ((char)v & 7);
- return (v >> 3);
-}
-
-static int
-archive_write_cpio_close(struct archive_write *a)
-{
- int er;
- struct archive_entry *trailer;
-
- trailer = archive_entry_new2(NULL);
- /* nlink = 1 here for GNU cpio compat. */
- archive_entry_set_nlink(trailer, 1);
- archive_entry_set_size(trailer, 0);
- archive_entry_set_pathname(trailer, "TRAILER!!!");
- er = write_header(a, trailer);
- archive_entry_free(trailer);
- return (er);
-}
-
-static int
-archive_write_cpio_free(struct archive_write *a)
-{
- struct cpio *cpio;
-
- cpio = (struct cpio *)a->format_data;
- free(cpio->ino_list);
- free(cpio);
- a->format_data = NULL;
- return (ARCHIVE_OK);
-}
-
-static int
-archive_write_cpio_finish_entry(struct archive_write *a)
-{
- struct cpio *cpio;
-
- cpio = (struct cpio *)a->format_data;
- return (__archive_write_nulls(a,
- (size_t)cpio->entry_bytes_remaining));
+ return archive_write_set_format_cpio_odc(_a);
}
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_cpio_binary.c b/src/libs/3rdparty/libarchive/archive_write_set_format_cpio_binary.c
new file mode 100644
index 000000000..d6ce35a7b
--- /dev/null
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_cpio_binary.c
@@ -0,0 +1,610 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_entry_locale.h"
+#include "archive_private.h"
+#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
+
+static ssize_t archive_write_binary_data(struct archive_write *,
+ const void *buff, size_t s);
+static int archive_write_binary_close(struct archive_write *);
+static int archive_write_binary_free(struct archive_write *);
+static int archive_write_binary_finish_entry(struct archive_write *);
+static int archive_write_binary_header(struct archive_write *,
+ struct archive_entry *);
+static int archive_write_binary_options(struct archive_write *,
+ const char *, const char *);
+static int write_header(struct archive_write *, struct archive_entry *);
+
+struct cpio {
+ uint64_t entry_bytes_remaining;
+
+ int64_t ino_next;
+
+ struct { int64_t old; int new;} *ino_list;
+ size_t ino_list_size;
+ size_t ino_list_next;
+
+ struct archive_string_conv *opt_sconv;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
+};
+
+/* This struct needs to be packed to get the header right */
+
+#if defined(__GNUC__)
+#define PACKED(x) x __attribute__((packed))
+#elif defined(_MSC_VER)
+#define PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
+#else
+#define PACKED(x) x
+#endif
+
+#define HSIZE 26
+
+PACKED(struct cpio_binary_header {
+ uint16_t h_magic;
+ uint16_t h_dev;
+ uint16_t h_ino;
+ uint16_t h_mode;
+ uint16_t h_uid;
+ uint16_t h_gid;
+ uint16_t h_nlink;
+ uint16_t h_majmin;
+ uint32_t h_mtime;
+ uint16_t h_namesize;
+ uint32_t h_filesize;
+});
+
+/* Back in the day, the 7th Edition cpio.c had this, to
+ * adapt to, as the comment said, "VAX, Interdata, ...":
+ *
+ * union { long l; short s[2]; char c[4]; } U;
+ * #define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];}
+ * long mklong(v)
+ * short v[];
+ * {
+ * U.l = 1;
+ * if(U.c[0])
+ * U.s[0] = v[1], U.s[1] = v[0];
+ * else
+ * U.s[0] = v[0], U.s[1] = v[1];
+ * return U.l;
+ * }
+ *
+ * Of course, that assumes that all machines have little-endian shorts,
+ * and just adapts the others to the special endianness of the PDP-11.
+ *
+ * Now, we could do this:
+ *
+ * union { uint32_t l; uint16_t s[2]; uint8_t c[4]; } U;
+ * #define PUTI16(v,sv) {U.s[0]=1;if(U.c[0]) v=sv; else U.s[0]=sv,U.c[2]=U.c[1],U.c[3]=U.c[0],v=U.s[1];}
+ * #define PUTI32(v,lv) {char_t Ut;U.l=1;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,Ut=U.c[0],U.c[0]=U.c[1],U.c[1]=Ut,Ut=U.c[2],U.c[2]=U.c[3],U.c[3]=Ut,v[0]=U.s[0],v[1]=U.s[1];}
+ *
+ * ...but it feels a little better to do it like this:
+ */
+
+static uint16_t la_swap16(uint16_t in) {
+ union {
+ uint16_t s[2];
+ uint8_t c[4];
+ } U;
+ U.s[0] = 1;
+ if (U.c[0])
+ return in;
+ else {
+ U.s[0] = in;
+ U.c[2] = U.c[1];
+ U.c[3] = U.c[0];
+ return U.s[1];
+ }
+ /* NOTREACHED */
+}
+
+static uint32_t la_swap32(uint32_t in) {
+ union {
+ uint32_t l;
+ uint16_t s[2];
+ uint8_t c[4];
+ } U;
+ U.l = 1;
+ if (U.c[0]) { /* Little-endian */
+ uint16_t t;
+ U.l = in;
+ t = U.s[0];
+ U.s[0] = U.s[1];
+ U.s[1] = t;
+ } else if (U.c[3]) { /* Big-endian */
+ U.l = in;
+ U.s[0] = la_swap16(U.s[0]);
+ U.s[1] = la_swap16(U.s[1]);
+ } else { /* PDP-endian */
+ U.l = in;
+ }
+ return U.l;
+}
+
+/*
+ * Set output format to the selected binary variant
+ */
+static int
+archive_write_set_format_cpio_binary(struct archive *_a, int format)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct cpio *cpio;
+
+ if (sizeof(struct cpio_binary_header) != HSIZE) {
+ archive_set_error(&a->archive, EINVAL,
+ "Binary cpio format not supported on this platform");
+ return (ARCHIVE_FATAL);
+ }
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_binary");
+
+ /* If someone else was already registered, unregister them. */
+ if (a->format_free != NULL)
+ (a->format_free)(a);
+
+ cpio = (struct cpio *)calloc(1, sizeof(*cpio));
+ if (cpio == NULL) {
+ archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
+ return (ARCHIVE_FATAL);
+ }
+ a->format_data = cpio;
+ a->format_name = "cpio";
+ a->format_options = archive_write_binary_options;
+ a->format_write_header = archive_write_binary_header;
+ a->format_write_data = archive_write_binary_data;
+ a->format_finish_entry = archive_write_binary_finish_entry;
+ a->format_close = archive_write_binary_close;
+ a->format_free = archive_write_binary_free;
+ a->archive.archive_format = format;
+ switch (format) {
+ case ARCHIVE_FORMAT_CPIO_PWB:
+ a->archive.archive_format_name = "PWB cpio";
+ break;
+ case ARCHIVE_FORMAT_CPIO_BIN_LE:
+ a->archive.archive_format_name = "7th Edition cpio";
+ break;
+ default:
+ archive_set_error(&a->archive, EINVAL, "binary format must be 'pwb' or 'bin'");
+ return (ARCHIVE_FATAL);
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set output format to PWB (6th Edition) binary format
+ */
+int
+archive_write_set_format_cpio_pwb(struct archive *_a)
+{
+ return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_PWB);
+}
+
+/*
+ * Set output format to 7th Edition binary format
+ */
+int
+archive_write_set_format_cpio_bin(struct archive *_a)
+{
+ return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_BIN_LE);
+}
+
+static int
+archive_write_binary_options(struct archive_write *a, const char *key,
+ const char *val)
+{
+ struct cpio *cpio = (struct cpio *)a->format_data;
+ int ret = ARCHIVE_FAILED;
+
+ if (strcmp(key, "hdrcharset") == 0) {
+ if (val == NULL || val[0] == 0)
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "%s: hdrcharset option needs a character-set name",
+ a->format_name);
+ else {
+ cpio->opt_sconv = archive_string_conversion_to_charset(
+ &a->archive, val, 0);
+ if (cpio->opt_sconv != NULL)
+ ret = ARCHIVE_OK;
+ else
+ ret = ARCHIVE_FATAL;
+ }
+ return (ret);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Ino values are as long as 64 bits on some systems; cpio format
+ * only allows 16 bits and relies on the ino values to identify hardlinked
+ * files. So, we can't merely "hash" the ino numbers since collisions
+ * would corrupt the archive. Instead, we generate synthetic ino values
+ * to store in the archive and maintain a map of original ino values to
+ * synthetic ones so we can preserve hardlink information.
+ *
+ * TODO: Make this more efficient. It's not as bad as it looks (most
+ * files don't have any hardlinks and we don't do any work here for those),
+ * but it wouldn't be hard to do better.
+ *
+ * TODO: Work with dev/ino pairs here instead of just ino values.
+ */
+static int
+synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
+{
+ int64_t ino = archive_entry_ino64(entry);
+ int ino_new;
+ size_t i;
+
+ /*
+ * If no index number was given, don't assign one. In
+ * particular, this handles the end-of-archive marker
+ * correctly by giving it a zero index value. (This is also
+ * why we start our synthetic index numbers with one below.)
+ */
+ if (ino == 0)
+ return (0);
+
+ /* Don't store a mapping if we don't need to. */
+ if (archive_entry_nlink(entry) < 2) {
+ return (int)(++cpio->ino_next);
+ }
+
+ /* Look up old ino; if we have it, this is a hardlink
+ * and we reuse the same value. */
+ for (i = 0; i < cpio->ino_list_next; ++i) {
+ if (cpio->ino_list[i].old == ino)
+ return (cpio->ino_list[i].new);
+ }
+
+ /* Assign a new index number. */
+ ino_new = (int)(++cpio->ino_next);
+
+ /* Ensure space for the new mapping. */
+ if (cpio->ino_list_size <= cpio->ino_list_next) {
+ size_t newsize = cpio->ino_list_size < 512
+ ? 512 : cpio->ino_list_size * 2;
+ void *newlist = realloc(cpio->ino_list,
+ sizeof(cpio->ino_list[0]) * newsize);
+ if (newlist == NULL)
+ return (-1);
+
+ cpio->ino_list_size = newsize;
+ cpio->ino_list = newlist;
+ }
+
+ /* Record and return the new value. */
+ cpio->ino_list[cpio->ino_list_next].old = ino;
+ cpio->ino_list[cpio->ino_list_next].new = ino_new;
+ ++cpio->ino_list_next;
+ return (ino_new);
+}
+
+
+static struct archive_string_conv *
+get_sconv(struct archive_write *a)
+{
+ struct cpio *cpio;
+ struct archive_string_conv *sconv;
+
+ cpio = (struct cpio *)a->format_data;
+ sconv = cpio->opt_sconv;
+ if (sconv == NULL) {
+ if (!cpio->init_default_conversion) {
+ cpio->sconv_default =
+ archive_string_default_conversion_for_write(
+ &(a->archive));
+ cpio->init_default_conversion = 1;
+ }
+ sconv = cpio->sconv_default;
+ }
+ return (sconv);
+}
+
+static int
+archive_write_binary_header(struct archive_write *a, struct archive_entry *entry)
+{
+ const char *path;
+ size_t len;
+
+ if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
+ archive_set_error(&a->archive, -1, "Filetype required");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
+ && errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Pathname");
+ return (ARCHIVE_FATAL);
+ }
+ if (len == 0 || path == NULL || path[0] == '\0') {
+ archive_set_error(&a->archive, -1, "Pathname required");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
+ archive_set_error(&a->archive, -1, "Size required");
+ return (ARCHIVE_FAILED);
+ }
+ return write_header(a, entry);
+}
+
+static int
+write_header(struct archive_write *a, struct archive_entry *entry)
+{
+ struct cpio *cpio;
+ const char *p, *path;
+ int pathlength, ret, ret_final;
+ int64_t ino;
+ struct cpio_binary_header h;
+ struct archive_string_conv *sconv;
+ struct archive_entry *entry_main;
+ size_t len;
+
+ cpio = (struct cpio *)a->format_data;
+ ret_final = ARCHIVE_OK;
+ sconv = get_sconv(a);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pathname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
+
+ ret = archive_entry_pathname_l(entry, &path, &len, sconv);
+ if (ret != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Pathname");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate pathname '%s' to %s",
+ archive_entry_pathname(entry),
+ archive_string_conversion_charset_name(sconv));
+ ret_final = ARCHIVE_WARN;
+ }
+ /* Include trailing null */
+ pathlength = (int)len + 1;
+
+ h.h_magic = la_swap16(070707);
+ h.h_dev = la_swap16(archive_entry_dev(entry));
+
+ ino = synthesize_ino_value(cpio, entry);
+ if (ino < 0) {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory for ino translation table");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ } else if (ino > 077777) {
+ archive_set_error(&a->archive, ERANGE,
+ "Too many files for this cpio format");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ h.h_ino = la_swap16((uint16_t)ino);
+
+ h.h_mode = archive_entry_mode(entry);
+ if (((h.h_mode & AE_IFMT) == AE_IFSOCK) || ((h.h_mode & AE_IFMT) == AE_IFIFO)) {
+ archive_set_error(&a->archive, EINVAL,
+ "sockets and fifos cannot be represented in the binary cpio formats");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
+ if ((h.h_mode & AE_IFMT) == AE_IFLNK) {
+ archive_set_error(&a->archive, EINVAL,
+ "symbolic links cannot be represented in the PWB cpio format");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ /* we could turn off AE_IFREG here, but it does no harm, */
+ /* and allows v7 cpio to read the entry without confusion */
+ }
+ h.h_mode = la_swap16(h.h_mode);
+
+ h.h_uid = la_swap16((uint16_t)archive_entry_uid(entry));
+ h.h_gid = la_swap16((uint16_t)archive_entry_gid(entry));
+ h.h_nlink = la_swap16((uint16_t)archive_entry_nlink(entry));
+
+ if (archive_entry_filetype(entry) == AE_IFBLK
+ || archive_entry_filetype(entry) == AE_IFCHR)
+ h.h_majmin = la_swap16(archive_entry_rdev(entry));
+ else
+ h.h_majmin = 0;
+
+ h.h_mtime = la_swap32((uint32_t)archive_entry_mtime(entry));
+ h.h_namesize = la_swap16(pathlength);
+
+ /* Non-regular files don't store bodies. */
+ if (archive_entry_filetype(entry) != AE_IFREG)
+ archive_entry_set_size(entry, 0);
+
+ /* Symlinks get the link written as the body of the entry. */
+ ret = archive_entry_symlink_l(entry, &p, &len, sconv);
+ if (ret != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Linkname");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate linkname '%s' to %s",
+ archive_entry_symlink(entry),
+ archive_string_conversion_charset_name(sconv));
+ ret_final = ARCHIVE_WARN;
+ }
+
+ if (len > 0 && p != NULL && *p != '\0') {
+ if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
+ archive_set_error(&a->archive, EINVAL,
+ "symlinks are not supported by UNIX V6 or by PWB cpio");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ h.h_filesize = la_swap32((uint32_t)strlen(p)); /* symlink */
+ } else {
+ if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) &&
+ (archive_entry_size(entry) > 256*256*256-1)) {
+ archive_set_error(&a->archive, ERANGE,
+ "File is too large for PWB binary cpio format.");
+ ret_final = ARCHIVE_FAILED;
+ goto exit_write_header;
+ } else if (archive_entry_size(entry) > INT32_MAX) {
+ archive_set_error(&a->archive, ERANGE,
+ "File is too large for binary cpio format.");
+ ret_final = ARCHIVE_FAILED;
+ goto exit_write_header;
+ }
+ h.h_filesize = la_swap32((uint32_t)archive_entry_size(entry)); /* file */
+ }
+
+ ret = __archive_write_output(a, &h, HSIZE);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+
+ ret = __archive_write_output(a, path, pathlength);
+ if ((ret == ARCHIVE_OK) && ((pathlength % 2) != 0))
+ ret = __archive_write_nulls(a, 1);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+
+ cpio->entry_bytes_remaining = archive_entry_size(entry);
+ if ((cpio->entry_bytes_remaining % 2) != 0)
+ cpio->entry_bytes_remaining++;
+
+ /* Write the symlink now. */
+ if (p != NULL && *p != '\0') {
+ ret = __archive_write_output(a, p, strlen(p));
+ if ((ret == ARCHIVE_OK) && ((strlen(p) % 2) != 0))
+ ret = __archive_write_nulls(a, 1);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ }
+
+exit_write_header:
+ archive_entry_free(entry_main);
+ return (ret_final);
+}
+
+static ssize_t
+archive_write_binary_data(struct archive_write *a, const void *buff, size_t s)
+{
+ struct cpio *cpio;
+ int ret;
+
+ cpio = (struct cpio *)a->format_data;
+ if (s > cpio->entry_bytes_remaining)
+ s = (size_t)cpio->entry_bytes_remaining;
+
+ ret = __archive_write_output(a, buff, s);
+ cpio->entry_bytes_remaining -= s;
+ if (ret >= 0)
+ return (s);
+ else
+ return (ret);
+}
+
+static int
+archive_write_binary_close(struct archive_write *a)
+{
+ int er;
+ struct archive_entry *trailer;
+
+ trailer = archive_entry_new2(NULL);
+ /* nlink = 1 here for GNU cpio compat. */
+ archive_entry_set_nlink(trailer, 1);
+ archive_entry_set_size(trailer, 0);
+ archive_entry_set_pathname(trailer, "TRAILER!!!");
+ er = write_header(a, trailer);
+ archive_entry_free(trailer);
+ return (er);
+}
+
+static int
+archive_write_binary_free(struct archive_write *a)
+{
+ struct cpio *cpio;
+
+ cpio = (struct cpio *)a->format_data;
+ free(cpio->ino_list);
+ free(cpio);
+ a->format_data = NULL;
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_binary_finish_entry(struct archive_write *a)
+{
+ struct cpio *cpio;
+
+ cpio = (struct cpio *)a->format_data;
+ return (__archive_write_nulls(a,
+ (size_t)cpio->entry_bytes_remaining));
+}
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_cpio_odc.c b/src/libs/3rdparty/libarchive/archive_write_set_format_cpio_odc.c
new file mode 100644
index 000000000..091925a2f
--- /dev/null
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_cpio_odc.c
@@ -0,0 +1,500 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_entry_locale.h"
+#include "archive_private.h"
+#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
+
+static ssize_t archive_write_odc_data(struct archive_write *,
+ const void *buff, size_t s);
+static int archive_write_odc_close(struct archive_write *);
+static int archive_write_odc_free(struct archive_write *);
+static int archive_write_odc_finish_entry(struct archive_write *);
+static int archive_write_odc_header(struct archive_write *,
+ struct archive_entry *);
+static int archive_write_odc_options(struct archive_write *,
+ const char *, const char *);
+static int format_octal(int64_t, void *, int);
+static int64_t format_octal_recursive(int64_t, char *, int);
+static int write_header(struct archive_write *, struct archive_entry *);
+
+struct cpio {
+ uint64_t entry_bytes_remaining;
+
+ int64_t ino_next;
+
+ struct { int64_t old; int new;} *ino_list;
+ size_t ino_list_size;
+ size_t ino_list_next;
+
+ struct archive_string_conv *opt_sconv;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
+};
+
+#define c_magic_offset 0
+#define c_magic_size 6
+#define c_dev_offset 6
+#define c_dev_size 6
+#define c_ino_offset 12
+#define c_ino_size 6
+#define c_mode_offset 18
+#define c_mode_size 6
+#define c_uid_offset 24
+#define c_uid_size 6
+#define c_gid_offset 30
+#define c_gid_size 6
+#define c_nlink_offset 36
+#define c_nlink_size 6
+#define c_rdev_offset 42
+#define c_rdev_size 6
+#define c_mtime_offset 48
+#define c_mtime_size 11
+#define c_namesize_offset 59
+#define c_namesize_size 6
+#define c_filesize_offset 65
+#define c_filesize_size 11
+
+/*
+ * Set output format to 'cpio' format.
+ */
+int
+archive_write_set_format_cpio_odc(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct cpio *cpio;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_odc");
+
+ /* If someone else was already registered, unregister them. */
+ if (a->format_free != NULL)
+ (a->format_free)(a);
+
+ cpio = (struct cpio *)calloc(1, sizeof(*cpio));
+ if (cpio == NULL) {
+ archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
+ return (ARCHIVE_FATAL);
+ }
+ a->format_data = cpio;
+ a->format_name = "cpio";
+ a->format_options = archive_write_odc_options;
+ a->format_write_header = archive_write_odc_header;
+ a->format_write_data = archive_write_odc_data;
+ a->format_finish_entry = archive_write_odc_finish_entry;
+ a->format_close = archive_write_odc_close;
+ a->format_free = archive_write_odc_free;
+ a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
+ a->archive.archive_format_name = "POSIX cpio";
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_odc_options(struct archive_write *a, const char *key,
+ const char *val)
+{
+ struct cpio *cpio = (struct cpio *)a->format_data;
+ int ret = ARCHIVE_FAILED;
+
+ if (strcmp(key, "hdrcharset") == 0) {
+ if (val == NULL || val[0] == 0)
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "%s: hdrcharset option needs a character-set name",
+ a->format_name);
+ else {
+ cpio->opt_sconv = archive_string_conversion_to_charset(
+ &a->archive, val, 0);
+ if (cpio->opt_sconv != NULL)
+ ret = ARCHIVE_OK;
+ else
+ ret = ARCHIVE_FATAL;
+ }
+ return (ret);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Ino values are as long as 64 bits on some systems; cpio format
+ * only allows 18 bits and relies on the ino values to identify hardlinked
+ * files. So, we can't merely "hash" the ino numbers since collisions
+ * would corrupt the archive. Instead, we generate synthetic ino values
+ * to store in the archive and maintain a map of original ino values to
+ * synthetic ones so we can preserve hardlink information.
+ *
+ * TODO: Make this more efficient. It's not as bad as it looks (most
+ * files don't have any hardlinks and we don't do any work here for those),
+ * but it wouldn't be hard to do better.
+ *
+ * TODO: Work with dev/ino pairs here instead of just ino values.
+ */
+static int
+synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
+{
+ int64_t ino = archive_entry_ino64(entry);
+ int ino_new;
+ size_t i;
+
+ /*
+ * If no index number was given, don't assign one. In
+ * particular, this handles the end-of-archive marker
+ * correctly by giving it a zero index value. (This is also
+ * why we start our synthetic index numbers with one below.)
+ */
+ if (ino == 0)
+ return (0);
+
+ /* Don't store a mapping if we don't need to. */
+ if (archive_entry_nlink(entry) < 2) {
+ return (int)(++cpio->ino_next);
+ }
+
+ /* Look up old ino; if we have it, this is a hardlink
+ * and we reuse the same value. */
+ for (i = 0; i < cpio->ino_list_next; ++i) {
+ if (cpio->ino_list[i].old == ino)
+ return (cpio->ino_list[i].new);
+ }
+
+ /* Assign a new index number. */
+ ino_new = (int)(++cpio->ino_next);
+
+ /* Ensure space for the new mapping. */
+ if (cpio->ino_list_size <= cpio->ino_list_next) {
+ size_t newsize = cpio->ino_list_size < 512
+ ? 512 : cpio->ino_list_size * 2;
+ void *newlist = realloc(cpio->ino_list,
+ sizeof(cpio->ino_list[0]) * newsize);
+ if (newlist == NULL)
+ return (-1);
+
+ cpio->ino_list_size = newsize;
+ cpio->ino_list = newlist;
+ }
+
+ /* Record and return the new value. */
+ cpio->ino_list[cpio->ino_list_next].old = ino;
+ cpio->ino_list[cpio->ino_list_next].new = ino_new;
+ ++cpio->ino_list_next;
+ return (ino_new);
+}
+
+
+static struct archive_string_conv *
+get_sconv(struct archive_write *a)
+{
+ struct cpio *cpio;
+ struct archive_string_conv *sconv;
+
+ cpio = (struct cpio *)a->format_data;
+ sconv = cpio->opt_sconv;
+ if (sconv == NULL) {
+ if (!cpio->init_default_conversion) {
+ cpio->sconv_default =
+ archive_string_default_conversion_for_write(
+ &(a->archive));
+ cpio->init_default_conversion = 1;
+ }
+ sconv = cpio->sconv_default;
+ }
+ return (sconv);
+}
+
+static int
+archive_write_odc_header(struct archive_write *a, struct archive_entry *entry)
+{
+ const char *path;
+ size_t len;
+
+ if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
+ archive_set_error(&a->archive, -1, "Filetype required");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
+ && errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Pathname");
+ return (ARCHIVE_FATAL);
+ }
+ if (len == 0 || path == NULL || path[0] == '\0') {
+ archive_set_error(&a->archive, -1, "Pathname required");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
+ archive_set_error(&a->archive, -1, "Size required");
+ return (ARCHIVE_FAILED);
+ }
+ return write_header(a, entry);
+}
+
+static int
+write_header(struct archive_write *a, struct archive_entry *entry)
+{
+ struct cpio *cpio;
+ const char *p, *path;
+ int pathlength, ret, ret_final;
+ int64_t ino;
+ char h[76];
+ struct archive_string_conv *sconv;
+ struct archive_entry *entry_main;
+ size_t len;
+
+ cpio = (struct cpio *)a->format_data;
+ ret_final = ARCHIVE_OK;
+ sconv = get_sconv(a);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pathname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
+
+ ret = archive_entry_pathname_l(entry, &path, &len, sconv);
+ if (ret != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Pathname");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate pathname '%s' to %s",
+ archive_entry_pathname(entry),
+ archive_string_conversion_charset_name(sconv));
+ ret_final = ARCHIVE_WARN;
+ }
+ /* Include trailing null. */
+ pathlength = (int)len + 1;
+
+ memset(h, 0, sizeof(h));
+ format_octal(070707, h + c_magic_offset, c_magic_size);
+ format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
+
+ ino = synthesize_ino_value(cpio, entry);
+ if (ino < 0) {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory for ino translation table");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ } else if (ino > 0777777) {
+ archive_set_error(&a->archive, ERANGE,
+ "Too many files for this cpio format");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
+
+ /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
+ format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
+ format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
+ format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
+ format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
+ if (archive_entry_filetype(entry) == AE_IFBLK
+ || archive_entry_filetype(entry) == AE_IFCHR)
+ format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
+ else
+ format_octal(0, h + c_rdev_offset, c_rdev_size);
+ format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
+ format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
+
+ /* Non-regular files don't store bodies. */
+ if (archive_entry_filetype(entry) != AE_IFREG)
+ archive_entry_set_size(entry, 0);
+
+ /* Symlinks get the link written as the body of the entry. */
+ ret = archive_entry_symlink_l(entry, &p, &len, sconv);
+ if (ret != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Linkname");
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate linkname '%s' to %s",
+ archive_entry_symlink(entry),
+ archive_string_conversion_charset_name(sconv));
+ ret_final = ARCHIVE_WARN;
+ }
+ if (len > 0 && p != NULL && *p != '\0')
+ ret = format_octal(strlen(p), h + c_filesize_offset,
+ c_filesize_size);
+ else
+ ret = format_octal(archive_entry_size(entry),
+ h + c_filesize_offset, c_filesize_size);
+ if (ret) {
+ archive_set_error(&a->archive, ERANGE,
+ "File is too large for cpio format.");
+ ret_final = ARCHIVE_FAILED;
+ goto exit_write_header;
+ }
+
+ ret = __archive_write_output(a, h, sizeof(h));
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+
+ ret = __archive_write_output(a, path, pathlength);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+
+ cpio->entry_bytes_remaining = archive_entry_size(entry);
+
+ /* Write the symlink now. */
+ if (p != NULL && *p != '\0') {
+ ret = __archive_write_output(a, p, strlen(p));
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
+ }
+exit_write_header:
+ archive_entry_free(entry_main);
+ return (ret_final);
+}
+
+static ssize_t
+archive_write_odc_data(struct archive_write *a, const void *buff, size_t s)
+{
+ struct cpio *cpio;
+ int ret;
+
+ cpio = (struct cpio *)a->format_data;
+ if (s > cpio->entry_bytes_remaining)
+ s = (size_t)cpio->entry_bytes_remaining;
+
+ ret = __archive_write_output(a, buff, s);
+ cpio->entry_bytes_remaining -= s;
+ if (ret >= 0)
+ return (s);
+ else
+ return (ret);
+}
+
+/*
+ * Format a number into the specified field.
+ */
+static int
+format_octal(int64_t v, void *p, int digits)
+{
+ int64_t max;
+ int ret;
+
+ max = (((int64_t)1) << (digits * 3)) - 1;
+ if (v >= 0 && v <= max) {
+ format_octal_recursive(v, (char *)p, digits);
+ ret = 0;
+ } else {
+ format_octal_recursive(max, (char *)p, digits);
+ ret = -1;
+ }
+ return (ret);
+}
+
+static int64_t
+format_octal_recursive(int64_t v, char *p, int s)
+{
+ if (s == 0)
+ return (v);
+ v = format_octal_recursive(v, p+1, s-1);
+ *p = '0' + ((char)v & 7);
+ return (v >> 3);
+}
+
+static int
+archive_write_odc_close(struct archive_write *a)
+{
+ int er;
+ struct archive_entry *trailer;
+
+ trailer = archive_entry_new2(NULL);
+ /* nlink = 1 here for GNU cpio compat. */
+ archive_entry_set_nlink(trailer, 1);
+ archive_entry_set_size(trailer, 0);
+ archive_entry_set_pathname(trailer, "TRAILER!!!");
+ er = write_header(a, trailer);
+ archive_entry_free(trailer);
+ return (er);
+}
+
+static int
+archive_write_odc_free(struct archive_write *a)
+{
+ struct cpio *cpio;
+
+ cpio = (struct cpio *)a->format_data;
+ free(cpio->ino_list);
+ free(cpio);
+ a->format_data = NULL;
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_odc_finish_entry(struct archive_write *a)
+{
+ struct cpio *cpio;
+
+ cpio = (struct cpio *)a->format_data;
+ return (__archive_write_nulls(a,
+ (size_t)cpio->entry_bytes_remaining));
+}
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_iso9660.c b/src/libs/3rdparty/libarchive/archive_write_set_format_iso9660.c
index faabd28ea..2a3ae07fa 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_iso9660.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_iso9660.c
@@ -289,12 +289,12 @@ struct isoent {
struct extr_rec *current;
} extr_rec_list;
- signed int virtual:1;
+ unsigned int virtual:1;
/* If set to one, this file type is a directory.
* A convenience flag to be used as
* "archive_entry_filetype(isoent->file->entry) == AE_IFDIR".
*/
- signed int dir:1;
+ unsigned int dir:1;
};
struct hardlink {
@@ -652,7 +652,7 @@ struct iso_option {
#define VOLUME_IDENTIFIER_SIZE 32
/*
- * Usage : !zisofs [DEFAULT]
+ * Usage : !zisofs [DEFAULT]
* : Disable to generate RRIP 'ZF' extension.
* : zisofs
* : Make files zisofs file and generate RRIP 'ZF'
@@ -689,7 +689,7 @@ struct iso9660 {
uint64_t bytes_remaining;
int need_multi_extent;
- /* Temporary string buffer for Joliet extension. */
+ /* Temporary string buffer for Joliet extension. */
struct archive_string utf16be;
struct archive_string mbs;
@@ -755,9 +755,9 @@ struct iso9660 {
/* Used for making zisofs. */
struct {
- signed int detect_magic:1;
- signed int making:1;
- signed int allzero:1;
+ unsigned int detect_magic:1;
+ unsigned int making:1;
+ unsigned int allzero:1;
unsigned char magic_buffer[64];
int magic_cnt;
@@ -2521,12 +2521,11 @@ get_gmoffset(struct tm *tm)
static void
get_tmfromtime(struct tm *tm, time_t *t)
{
-#if HAVE_LOCALTIME_R
+#if HAVE_LOCALTIME_S
+ localtime_s(tm, t);
+#elif HAVE_LOCALTIME_R
tzset();
localtime_r(t, tm);
-#elif HAVE__LOCALTIME64_S
- __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
- _localtime64_s(tm, &tmp_t);
#else
memcpy(tm, localtime(t), sizeof(*tm));
#endif
@@ -4074,11 +4073,8 @@ write_information_block(struct archive_write *a)
}
memset(info.s, 0, info_size);
opt = 0;
-#if defined(HAVE__CTIME64_S)
- {
- __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
- _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
- }
+#if defined(HAVE_CTIME_S)
+ ctime_s(buf, sizeof(buf), &(iso9660->birth_time));
#elif defined(HAVE_CTIME_R)
ctime_r(&(iso9660->birth_time), buf);
#else
@@ -6802,6 +6798,7 @@ isoent_rr_move(struct archive_write *a)
* This comparing rule is according to ISO9660 Standard 6.9.1
*/
static int
+__LA_LIBC_CC
_compare_path_table(const void *v1, const void *v2)
{
const struct isoent *p1, *p2;
@@ -6844,6 +6841,7 @@ _compare_path_table(const void *v1, const void *v2)
}
static int
+__LA_LIBC_CC
_compare_path_table_joliet(const void *v1, const void *v2)
{
const struct isoent *p1, *p2;
@@ -7800,8 +7798,8 @@ struct zisofs_extract {
uint64_t pz_uncompressed_size;
size_t uncompressed_buffer_size;
- signed int initialized:1;
- signed int header_passed:1;
+ unsigned int initialized:1;
+ unsigned int header_passed:1;
uint32_t pz_offset;
unsigned char *block_pointers;
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c b/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c
index a2b271071..c9c159164 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_pax.c
@@ -100,6 +100,7 @@ static int has_non_ASCII(const char *);
static void sparse_list_clear(struct pax *);
static int sparse_list_add(struct pax *, int64_t, int64_t);
static char *url_encode(const char *in);
+static time_t get_ustar_max_mtime(void);
/*
* Set output format to 'restricted pax' format.
@@ -595,6 +596,8 @@ archive_write_pax_header(struct archive_write *a,
need_extension = 0;
pax = (struct pax *)a->format_data;
+ const time_t ustar_max_mtime = get_ustar_max_mtime();
+
/* Sanity check. */
if (archive_entry_pathname(entry_original) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -1028,10 +1031,8 @@ archive_write_pax_header(struct archive_write *a,
archive_string_init(&entry_name);
archive_strcpy(&entry_name, archive_entry_pathname(entry_main));
- /* If file size is too large, add 'size' to pax extended attrs. */
+ /* If file size is too large, we need pax extended attrs. */
if (archive_entry_size(entry_main) >= (((int64_t)1) << 33)) {
- add_pax_attr_int(&(pax->pax_header), "size",
- archive_entry_size(entry_main));
need_extension = 1;
}
@@ -1118,16 +1119,13 @@ archive_write_pax_header(struct archive_write *a,
}
/*
- * Technically, the mtime field in the ustar header can
- * support 33 bits, but many platforms use signed 32-bit time
- * values. The cutoff of 0x7fffffff here is a compromise.
* Yes, this check is duplicated just below; this helps to
* avoid writing an mtime attribute just to handle a
* high-resolution timestamp in "restricted pax" mode.
*/
if (!need_extension &&
((archive_entry_mtime(entry_main) < 0)
- || (archive_entry_mtime(entry_main) >= 0x7fffffff)))
+ || (archive_entry_mtime(entry_main) >= ustar_max_mtime)))
need_extension = 1;
/* I use a star-compatible file flag attribute. */
@@ -1192,7 +1190,7 @@ archive_write_pax_header(struct archive_write *a,
if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
need_extension) {
if (archive_entry_mtime(entry_main) < 0 ||
- archive_entry_mtime(entry_main) >= 0x7fffffff ||
+ archive_entry_mtime(entry_main) >= ustar_max_mtime ||
archive_entry_mtime_nsec(entry_main) != 0)
add_pax_attr_time(&(pax->pax_header), "mtime",
archive_entry_mtime(entry_main),
@@ -1347,6 +1345,12 @@ archive_write_pax_header(struct archive_write *a,
mapsize + pax->sparse_map_padding + sparse_total);
}
+ /* If file size is too large, add 'size' to pax extended attrs. */
+ if (archive_entry_size(entry_main) >= (((int64_t)1) << 33)) {
+ add_pax_attr_int(&(pax->pax_header), "size",
+ archive_entry_size(entry_main));
+ }
+
/* Format 'ustar' header for main entry.
*
* The trouble with file size: If the reader can't understand
@@ -1424,7 +1428,7 @@ archive_write_pax_header(struct archive_write *a,
/* Copy mtime, but clip to ustar limits. */
s = archive_entry_mtime(entry_main);
if (s < 0) { s = 0; }
- if (s >= 0x7fffffff) { s = 0x7fffffff; }
+ if (s > ustar_max_mtime) { s = ustar_max_mtime; }
archive_entry_set_mtime(pax_attr_entry, s, 0);
/* Standard ustar doesn't support atime. */
@@ -1713,7 +1717,7 @@ build_pax_attribute_name(char *dest, const char *src)
* to having clients override it.
*/
#if HAVE_GETPID && 0 /* Disable this for now; see above comment. */
- sprintf(buff, "PaxHeader.%d", getpid());
+ snprintf(buff, sizeof(buff), "PaxHeader.%d", getpid());
#else
/* If the platform can't fetch the pid, don't include it. */
strcpy(buff, "PaxHeader");
@@ -2042,3 +2046,18 @@ sparse_list_add(struct pax *pax, int64_t offset, int64_t length)
return (_sparse_list_add_block(pax, offset, length, 0));
}
+static time_t
+get_ustar_max_mtime(void)
+{
+ /*
+ * Technically, the mtime field in the ustar header can
+ * support 33 bits. We are using all of them to keep
+ * tar/test/test_option_C_mtree.c simple and passing after 2038.
+ * For platforms that use signed 32-bit time values we
+ * use the 32-bit maximum.
+ */
+ if (sizeof(time_t) > sizeof(int32_t))
+ return (time_t)0x1ffffffff;
+ else
+ return (time_t)0x7fffffff;
+}
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_warc.c b/src/libs/3rdparty/libarchive/archive_write_set_format_warc.c
index 46b057341..0ef003e2f 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_warc.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_warc.c
@@ -329,30 +329,21 @@ xstrftime(struct archive_string *as, const char *fmt, time_t t)
{
/** like strftime(3) but for time_t objects */
struct tm *rt;
-#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
+#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
struct tm timeHere;
#endif
-#if defined(HAVE__GMTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
char strtime[100];
size_t len;
-#ifdef HAVE_GMTIME_R
- if ((rt = gmtime_r(&t, &timeHere)) == NULL)
- return;
-#elif defined(HAVE__GMTIME64_S)
- tmptime = t;
- terr = _gmtime64_s(&timeHere, &tmptime);
- if (terr)
- rt = NULL;
- else
- rt = &timeHere;
+#if defined(HAVE_GMTIME_S)
+ rt = gmtime_s(&timeHere, &t) ? NULL : &timeHere;
+#elif defined(HAVE_GMTIME_R)
+ rt = gmtime_r(&t, &timeHere);
#else
- if ((rt = gmtime(&t)) == NULL)
- return;
+ rt = gmtime(&t);
#endif
+ if (!rt)
+ return;
/* leave the hard yacker to our role model strftime() */
len = strftime(strtime, sizeof(strtime)-1, fmt, rt);
archive_strncat(as, strtime, len);
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_xar.c b/src/libs/3rdparty/libarchive/archive_write_set_format_xar.c
index d885f5c25..7307757d3 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_xar.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_xar.c
@@ -212,8 +212,8 @@ struct file {
struct heap_data data;
struct archive_string script;
- signed int virtual:1;
- signed int dir:1;
+ unsigned int virtual:1;
+ unsigned int dir:1;
};
struct hardlink {
@@ -906,15 +906,11 @@ xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
{
char timestr[100];
struct tm tm;
-#if defined(HAVE__GMTIME64_S)
- __time64_t tmptime;
-#endif
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ gmtime_s(&tm, &t);
+#elif defined(HAVE_GMTIME_R)
gmtime_r(&t, &tm);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = t;
- _gmtime64_s(&tm, &tmptime);
#else
memcpy(&tm, gmtime(&t), sizeof(tm));
#endif
diff --git a/src/libs/3rdparty/libarchive/archive_write_set_format_zip.c b/src/libs/3rdparty/libarchive/archive_write_set_format_zip.c
index f4352d5a9..6821049c9 100644
--- a/src/libs/3rdparty/libarchive/archive_write_set_format_zip.c
+++ b/src/libs/3rdparty/libarchive/archive_write_set_format_zip.c
@@ -740,12 +740,16 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
/* We may know the size, but never the CRC. */
zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END;
} else {
- /* We don't know the size. In this case, we prefer
- * deflate (it has a clear end-of-data marker which
- * makes length-at-end more reliable) and will
- * enable Zip64 extensions unless we're told not to.
+ /* We don't know the size. Use the default
+ * compression unless specified otherwise.
+ * We enable Zip64 extensions unless we're told not to.
*/
- zip->entry_compression = COMPRESSION_DEFAULT;
+
+ zip->entry_compression = zip->requested_compression;
+ if(zip->entry_compression == COMPRESSION_UNSPECIFIED){
+ zip->entry_compression = COMPRESSION_DEFAULT;
+ }
+
zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END;
if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) {
zip->entry_uses_zip64 = 1;
@@ -1378,25 +1382,14 @@ dos_time(const time_t unix_time)
{
struct tm *t;
unsigned int dt;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
- /* This will not preserve time when creating/extracting the archive
- * on two systems with different time zones. */
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ t = localtime_s(&tmbuf, &unix_time) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
t = localtime_r(&unix_time, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = unix_time;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- t = NULL;
- else
- t = &tmbuf;
#else
t = localtime(&unix_time);
#endif
diff --git a/src/libs/3rdparty/libarchive/config/mac/config.h b/src/libs/3rdparty/libarchive/config/mac/config.h
index 80866d915..d20c30769 100644
--- a/src/libs/3rdparty/libarchive/config/mac/config.h
+++ b/src/libs/3rdparty/libarchive/config/mac/config.h
@@ -205,7 +205,7 @@ typedef uint64_t uintmax_t;
/* #undef ARCHIVE_CRYPTO_MD5_LIBC */
/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1
+/* #undef ARCHIVE_CRYPTO_MD5_LIBSYSTEM */
/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */
/* #undef ARCHIVE_CRYPTO_MD5_NETTLE */
@@ -229,7 +229,7 @@ typedef uint64_t uintmax_t;
/* #undef ARCHIVE_CRYPTO_SHA1_LIBC */
/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1
+/* #undef ARCHIVE_CRYPTO_SHA1_LIBSYSTEM */
/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */
/* #undef ARCHIVE_CRYPTO_SHA1_NETTLE */
@@ -250,7 +250,7 @@ typedef uint64_t uintmax_t;
/* #undef ARCHIVE_CRYPTO_SHA256_LIBC3 */
/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1
+/* #undef ARCHIVE_CRYPTO_SHA256_LIBSYSTEM */
/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */
/* #undef ARCHIVE_CRYPTO_SHA256_NETTLE */
@@ -271,7 +271,7 @@ typedef uint64_t uintmax_t;
/* #undef ARCHIVE_CRYPTO_SHA384_LIBC3 */
/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1
+/* #undef ARCHIVE_CRYPTO_SHA384_LIBSYSTEM */
/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */
/* #undef ARCHIVE_CRYPTO_SHA384_NETTLE */
@@ -292,7 +292,7 @@ typedef uint64_t uintmax_t;
/* #undef ARCHIVE_CRYPTO_SHA512_LIBC3 */
/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */
-#define ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1
+/* #undef ARCHIVE_CRYPTO_SHA512_LIBSYSTEM */
/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */
/* #undef ARCHIVE_CRYPTO_SHA512_NETTLE */
diff --git a/src/libs/3rdparty/libarchive/config_freebsd.h b/src/libs/3rdparty/libarchive/config_freebsd.h
index a484618b4..669f27246 100644
--- a/src/libs/3rdparty/libarchive/config_freebsd.h
+++ b/src/libs/3rdparty/libarchive/config_freebsd.h
@@ -111,6 +111,8 @@
#define HAVE_FCNTL 1
#define HAVE_FCNTL_H 1
#define HAVE_FDOPENDIR 1
+#define HAVE_FNMATCH 1
+#define HAVE_FNMATCH_H 1
#define HAVE_FORK 1
#define HAVE_FSEEKO 1
#define HAVE_FSTAT 1
@@ -123,6 +125,8 @@
#define HAVE_GETEUID 1
#define HAVE_GETGRGID_R 1
#define HAVE_GETGRNAM_R 1
+#define HAVE_GETLINE 1
+#define HAVE_GETOPT_OPTRESET 1
#define HAVE_GETPID 1
#define HAVE_GETPWNAM_R 1
#define HAVE_GETPWUID_R 1
@@ -138,6 +142,7 @@
#define HAVE_LIBZ 1
#define HAVE_LIMITS_H 1
#define HAVE_LINK 1
+#define HAVE_LINKAT 1
#define HAVE_LOCALE_H 1
#define HAVE_LOCALTIME_R 1
#define HAVE_LONG_LONG_INT 1
@@ -200,6 +205,7 @@
#define HAVE_SYS_MOUNT_H 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_POLL_H 1
+#define HAVE_SYS_QUEUE_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_STATVFS_H 1
#define HAVE_SYS_STAT_H 1
@@ -233,7 +239,15 @@
#define HAVE_WMEMCPY 1
#define HAVE_WMEMMOVE 1
#define HAVE_ZLIB_H 1
-#define TIME_WITH_SYS_TIME 1
+#define HAVE_SYS_TIME_H 1
+
+#if __FreeBSD_version >= 800505
+#define HAVE_LIBLZMA 1
+#define HAVE_LZMA_H 1
+#if __FreeBSD_version >= 1002504
+#define HAVE_LZMA_STREAM_ENCODER_MT 1
+#endif
+#endif
#if __FreeBSD_version >= 1100056
#define HAVE_FUTIMENS 1
diff --git a/src/libs/3rdparty/libarchive/filter_fork_posix.c b/src/libs/3rdparty/libarchive/filter_fork_posix.c
index ac255c4f8..62085a709 100644
--- a/src/libs/3rdparty/libarchive/filter_fork_posix.c
+++ b/src/libs/3rdparty/libarchive/filter_fork_posix.c
@@ -76,7 +76,7 @@ int
__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
pid_t *out_child)
{
- pid_t child;
+ pid_t child = -1;
int stdin_pipe[2], stdout_pipe[2], tmp;
#if HAVE_POSIX_SPAWNP
posix_spawn_file_actions_t actions;
diff --git a/src/libs/3rdparty/libarchive/filter_fork_windows.c b/src/libs/3rdparty/libarchive/filter_fork_windows.c
index 8d11179f3..9e49c5655 100644
--- a/src/libs/3rdparty/libarchive/filter_fork_windows.c
+++ b/src/libs/3rdparty/libarchive/filter_fork_windows.c
@@ -31,6 +31,44 @@
#include "filter_fork.h"
+#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+/* There are some editions of Windows ("nano server," for example) that
+ * do not host user32.dll. If we want to keep running on those editions,
+ * we need to delay-load WaitForInputIdle. */
+static void *
+la_GetFunctionUser32(const char *name)
+{
+ static HINSTANCE lib;
+ static int set;
+ if (!set) {
+ set = 1;
+ lib = LoadLibrary(TEXT("user32.dll"));
+ }
+ if (lib == NULL) {
+ return NULL;
+ }
+ return (void *)GetProcAddress(lib, name);
+}
+
+static int
+la_WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds)
+{
+ static DWORD (WINAPI *f)(HANDLE, DWORD);
+ static int set;
+
+ if (!set) {
+ set = 1;
+ f = la_GetFunctionUser32("WaitForInputIdle");
+ }
+
+ if (!f) {
+ /* An inability to wait for input idle is
+ * not _good_, but it is not catastrophic. */
+ return WAIT_FAILED;
+ }
+ return (*f)(hProcess, dwMilliseconds);
+}
+
int
__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
HANDLE *out_child)
@@ -149,7 +187,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
if (CreateProcessA(fullpath.s, cmdline.s, NULL, NULL, TRUE, 0,
NULL, NULL, &staInfo, &childInfo) == 0)
goto fail;
- WaitForInputIdle(childInfo.hProcess, INFINITE);
+ la_WaitForInputIdle(childInfo.hProcess, INFINITE);
CloseHandle(childInfo.hProcess);
CloseHandle(childInfo.hThread);
@@ -187,6 +225,14 @@ fail:
__archive_cmdline_free(acmd);
return ARCHIVE_FAILED;
}
+#else /* !WINAPI_PARTITION_DESKTOP */
+int
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, HANDLE *out_child)
+{
+ (void)cmd; (void)child_stdin; (void) child_stdout; (void) out_child;
+ return ARCHIVE_FAILED;
+}
+#endif /* !WINAPI_PARTITION_DESKTOP */
void
__archive_check_child(int in, int out)
diff --git a/src/libs/3rdparty/libarchive/libarchive.pro b/src/libs/3rdparty/libarchive/libarchive.pro
index accaf3af7..0cf6f3097 100644
--- a/src/libs/3rdparty/libarchive/libarchive.pro
+++ b/src/libs/3rdparty/libarchive/libarchive.pro
@@ -146,7 +146,9 @@ SOURCES += $$PWD/archive_acl.c \
$$PWD/archive_write_set_format_ar.c \
$$PWD/archive_write_set_format_by_name.c \
$$PWD/archive_write_set_format_cpio.c \
+ $$PWD/archive_write_set_format_cpio_binary.c \
$$PWD/archive_write_set_format_cpio_newc.c \
+ $$PWD/archive_write_set_format_cpio_odc.c \
$$PWD/archive_write_set_format_filter_by_ext.c \
$$PWD/archive_write_set_format_gnutar.c \
$$PWD/archive_write_set_format_iso9660.c \
@@ -164,6 +166,10 @@ SOURCES += $$PWD/archive_acl.c \
$$PWD/filter_fork_posix.c \
$$PWD/xxhash.c
+if (isEmpty(IFW_ZLIB_LIBRARY):contains(QT_MODULES, zlib)) {
+ INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtZlib
+}
+
linux {
INCLUDEPATH += ./config/linux
HEADERS += $$PWD/config/linux/config.h
diff --git a/src/libs/3rdparty/libarchive/qt_attribution.json b/src/libs/3rdparty/libarchive/qt_attribution.json
index 86beb162c..76db5e26a 100644
--- a/src/libs/3rdparty/libarchive/qt_attribution.json
+++ b/src/libs/3rdparty/libarchive/qt_attribution.json
@@ -5,7 +5,7 @@
"Description": "Multi-format archive and compression library.",
"QtUsage": "Used for reading and writing archive files in Qt Installer Framework",
"Homepage": "https://www.libarchive.org",
- "Version": "3.5.1",
+ "Version": "3.7.1",
"License": "BSD 2-clause \"Simplified\" License",
"LicenseId": "BSD-2-Clause",
"LicenseFile": "COPYING",
diff --git a/src/libs/3rdparty/libarchive/xxhash.c b/src/libs/3rdparty/libarchive/xxhash.c
index 70750bae0..beacd2391 100644
--- a/src/libs/3rdparty/libarchive/xxhash.c
+++ b/src/libs/3rdparty/libarchive/xxhash.c
@@ -149,8 +149,16 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
#if GCC_VERSION >= 409
__attribute__((__no_sanitize_undefined__))
+#else
+# if defined(__clang__)
+__attribute__((no_sanitize("undefined")))
+# endif
+#endif
+#if defined(_MSC_VER)
+static __inline U32 A32(const void * x)
+#else
+static inline U32 A32(const void* x)
#endif
-static inline U32 A32(const void * x)
{
return (((const U32_S *)(x))->v);
}
diff --git a/src/libs/7zip/patches/0001-Adjust-7z-and-p7z.patch b/src/libs/7zip/patches/0001-Adjust-7z-and-p7z.patch
deleted file mode 100644
index 822deb07f..000000000
--- a/src/libs/7zip/patches/0001-Adjust-7z-and-p7z.patch
+++ /dev/null
@@ -1,517 +0,0 @@
-From f643c01e4e8534f26a5a2d260caa566d23cdcb13 Mon Sep 17 00:00:00 2001
-From: Karsten Heimrich <karsten.heimrich@theqtcompany.com>
-Date: Thu, 4 Jun 2015 15:41:51 +0200
-Subject: [PATCH 1/1] Adjust 7z and p7z.
-
-Change-Id: I3b96d2b02e5a0908fb4cf5b4262cb33516a10098
----
- src/libs/7zip/7zip.pri | 11 ++++-
- src/libs/7zip/7zip.pro | 14 +-----
- src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp | 2 -
- src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h | 32 ++++++++++---
- src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h | 29 ++++++++---
- src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp | 2 -
- .../unix/CPP/include_windows/include_windows.pri | 3 ++
- .../unix/CPP/myWindows/myCommandLineParser.cpp | 56 ++++++++++++++++++++++
- src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp | 42 ++++++++--------
- src/libs/7zip/unix/CPP/myWindows/myWindows.pri | 7 +++
- src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp | 2 -
- src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h | 32 ++++++++++---
- src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h | 29 ++++++++---
- src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp | 2 -
- 14 files changed, 194 insertions(+), 69 deletions(-)
- create mode 100644 src/libs/7zip/unix/CPP/include_windows/include_windows.pri
- create mode 100644 src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
- create mode 100644 src/libs/7zip/unix/CPP/myWindows/myWindows.pri
-
-diff --git a/src/libs/7zip/7zip.pri b/src/libs/7zip/7zip.pri
-index 823e3ab..85574ce 100644
---- a/src/libs/7zip/7zip.pri
-+++ b/src/libs/7zip/7zip.pri
-@@ -1,7 +1,11 @@
-+DEFINES += _UNICODE _NO_CRYPTO
-+
- win32 {
- 7ZIP_BASE=$$PWD/win
- INCLUDEPATH += $$7ZIP_BASE/C $$7ZIP_BASE/CPP
-- DEFINES += WIN_LONG_PATH _UNICODE _NO_CRYPTO
-+ DEFINES += WIN_LONG_PATH _CRT_SECURE_NO_WARNINGS
-+ win32-g++*:QMAKE_CXXFLAGS += -w -fvisibility=hidden
-+
- QMAKE_CXXFLAGS_RELEASE -= -Zc:strictStrings
- QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO -= -Zc:strictStrings
- }
-@@ -14,6 +18,9 @@ unix {
- $$7ZIP_BASE/CPP/myWindows \
- $$7ZIP_BASE/CPP/include_windows
-
-+ QMAKE_CFLAGS += -w
-+ QMAKE_CXXFLAGS += -fvisibility=hidden -w
-+
- macx:DEFINES += ENV_MACOSX
-- DEFINES += _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE NDEBUG _REENTRANT ENV_UNIX UNICODE _UNICODE _NO_CRYPTO
-+ DEFINES += _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE NDEBUG _REENTRANT ENV_UNIX UNICODE
- }
-diff --git a/src/libs/7zip/7zip.pro b/src/libs/7zip/7zip.pro
-index 01b69da..70a51c0 100644
---- a/src/libs/7zip/7zip.pro
-+++ b/src/libs/7zip/7zip.pro
-@@ -7,15 +7,5 @@ CONFIG += staticlib
- DESTDIR = $$IFW_LIB_PATH
-
- include(7zip.pri)
--win32 {
-- DEFINES += _CRT_SECURE_NO_WARNINGS
-- win32-g++*:QMAKE_CXXFLAGS += -w -fvisibility=hidden
-- CONFIG += no_batch # this is needed because we have a same named *.c and *.cpp file -> 7in
-- include($$7ZIP_BASE/win.pri) #this is 7zip
--}
--
--unix {
-- QMAKE_CFLAGS += -w
-- QMAKE_CXXFLAGS += -fvisibility=hidden -w
-- include($$7ZIP_BASE/unix.pri) #this is p7zip
--}
-+win32:include($$7ZIP_BASE/win.pri) #7zip
-+unix:include($$7ZIP_BASE/unix.pri) #p7zip
-diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp
-index 8af28b9..e20858e 100644
---- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp
-+++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp
-@@ -4,8 +4,6 @@
-
- #include "../../../../C/7zCrc.h"
-
--#include "../../../Common/AutoPtr.h"
--
- #include "../../Common/StreamObjects.h"
-
- #include "7zOut.h"
-diff --git a/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h b/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h
-index 1e9bf14..82bd096 100644
---- a/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h
-+++ b/src/libs/7zip/unix/CPP/7zip/Common/RegisterArc.h
-@@ -5,6 +5,8 @@
-
- #include "../Archive/IArchive.h"
-
-+#include <mutex>
-+
- struct CArcInfo
- {
- const char *Name;
-@@ -24,19 +26,35 @@ struct CArcInfo
- Func_IsArc IsArc;
-
- bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }
-+
-+ std::once_flag once;
- };
-
- void RegisterArc(const CArcInfo *arcInfo) throw();
-
- #define REGISTER_ARC_NAME(x) CRegister ## x
-
--#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \
-- REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \
-- static REGISTER_ARC_NAME(x) g_RegisterArc;
--
--#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \
-- REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \
-- static REGISTER_ARC_NAME(x) g_RegisterArc;
-+#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) \
-+ { \
-+ REGISTER_ARC_NAME(x)() \
-+ { \
-+ std::call_once(g_ArcInfo.once, [] { RegisterArc(&g_ArcInfo); }); \
-+ } \
-+ }; \
-+ static REGISTER_ARC_NAME(x) g_RegisterArc; \
-+ void registerArc##x() { static REGISTER_ARC_NAME(x) g_RegisterArc; }
-+
-+#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) \
-+ { \
-+ REGISTER_ARC_NAME(x)() { \
-+ std::call_once(g_ArcInfo.once, [] { \
-+ g_ArcInfo.Signature[0]--; \
-+ RegisterArc(&g_ArcInfo); \
-+ }); \
-+ } \
-+ }; \
-+ static REGISTER_ARC_NAME(x) g_RegisterArc; \
-+ void registerArcDec##x() { static REGISTER_ARC_NAME(x) g_RegisterArc; }
-
-
- #define IMP_CreateArcIn_2(c) \
-diff --git a/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h b/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h
-index 4222a30..0c6662a 100644
---- a/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h
-+++ b/src/libs/7zip/unix/CPP/7zip/Common/RegisterCodec.h
-@@ -6,6 +6,8 @@
- #include "../Common/MethodId.h"
- #include "../ICoder.h"
-
-+#include <mutex>
-+
- typedef void * (*CreateCodecP)();
- struct CCodecInfo
- {
-@@ -15,21 +17,34 @@ struct CCodecInfo
- const wchar_t *Name;
- UInt32 NumInStreams;
- bool IsFilter;
-+ std::once_flag once;
- };
-
- void RegisterCodec(const CCodecInfo *codecInfo) throw();
-
- #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x
-
--#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
-- REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
-- static REGISTER_CODEC_NAME(x) g_RegisterCodec;
-+#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) \
-+ { \
-+ REGISTER_CODEC_NAME(x)() \
-+ { \
-+ std::call_once(g_CodecInfo.once, [] { RegisterCodec(&g_CodecInfo); }); \
-+ } \
-+ }; \
-+ static REGISTER_CODEC_NAME(x) g_RegisterCodec; \
-+ void registerCodec##x() { static REGISTER_CODEC_NAME(x) g_RegisterCodecs; }
-
- #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x
--#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
-- REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
-- RegisterCodec(&g_CodecsInfo[i]); }}; \
-- static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
-+#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) \
-+ { \
-+ REGISTER_CODECS_NAME(x)() \
-+ { \
-+ for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
-+ std::call_once(g_CodecsInfo[i].once, [&i] { RegisterCodec(&g_CodecsInfo[i]); }); \
-+ } \
-+ }; \
-+ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; \
-+ void registerCodec##x() { static REGISTER_CODECS_NAME(x) g_RegisterCodecs; }
-
-
- struct CHasherInfo
-diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
-index 03f31fa..5f94254 100644
---- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
-+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
-@@ -2,8 +2,6 @@
-
- #include "StdAfx.h"
-
--#include "../../../../C/Sort.h"
--
- #include "../../../Common/StringConvert.h"
-
- #include "../../../Windows/FileDir.h"
-diff --git a/src/libs/7zip/unix/CPP/include_windows/include_windows.pri b/src/libs/7zip/unix/CPP/include_windows/include_windows.pri
-new file mode 100644
-index 0000000..5ef72fd
---- /dev/null
-+++ b/src/libs/7zip/unix/CPP/include_windows/include_windows.pri
-@@ -0,0 +1,3 @@
-+HEADERS += $$7ZIP_BASE/CPP/include_windows/basetyps.h \
-+ $$7ZIP_BASE/CPP/include_windows/tchar.h \
-+ $$7ZIP_BASE/CPP/include_windows/windows.h
-diff --git a/src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp b/src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
-new file mode 100644
-index 0000000..5d7f6fd
---- /dev/null
-+++ b/src/libs/7zip/unix/CPP/myWindows/myCommandLineParser.cpp
-@@ -0,0 +1,56 @@
-+/**************************************************************************
-+**
-+** Copyright (C) 2015 The Qt Company Ltd.
-+** Contact: http://www.qt.io/licensing/
-+**
-+** This file is part of the Qt Installer Framework.
-+**
-+** $QT_BEGIN_LICENSE:LGPL$
-+** Commercial License Usage
-+** Licensees holding valid commercial Qt licenses may use this file in
-+** accordance with the commercial license agreement provided with the
-+** Software or, alternatively, in accordance with the terms contained in
-+** a written agreement between you and The Qt Company. For licensing terms
-+** and conditions see http://qt.io/terms-conditions. For further
-+** information use the contact form at http://www.qt.io/contact-us.
-+**
-+** GNU Lesser General Public License Usage
-+** Alternatively, this file may be used under the terms of the GNU Lesser
-+** General Public License version 2.1 or version 3 as published by the Free
-+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-+** following information to ensure the GNU Lesser General Public License
-+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-+**
-+** As a special exception, The Qt Company gives you certain additional
-+** rights. These rights are described in The Qt Company LGPL Exception
-+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-+**
-+**
-+** $QT_END_LICENSE$
-+**
-+**************************************************************************/
-+
-+#include "../CPP/Common/MyString.h"
-+
-+#include <QStringList>
-+
-+namespace NCommandLineParser {
-+
-+void SplitCommandLine(const UString &s, UStringVector &parts)
-+{
-+ parts.Clear();
-+
-+ const QString cmdLine = QString::fromStdWString(static_cast<const wchar_t*>(s));
-+ const QStringList args = cmdLine.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
-+ foreach (QString arg, args) {
-+ if (arg.startsWith(QLatin1Char('\"')))
-+ arg = arg.mid(1);
-+ if (arg.endsWith(QLatin1Char('\"')))
-+ arg = arg.mid(1);
-+ parts.Add(arg.toStdWString().c_str());
-+ }
-+}
-+
-+} // namespace NCommandLineParser
-diff --git a/src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp b/src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp
-index 96554c9..9ebfe37 100644
---- a/src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp
-+++ b/src/libs/7zip/unix/CPP/myWindows/myDateAndTime.cpp
-@@ -32,19 +32,18 @@
- **
- **************************************************************************/
-
--#include <QDebug>
--#include <QDateTime>
- #include "windows.h"
-
-+#include <QDateTime>
-+
- void FileTimeToDateTime(const FILETIME *source, QDateTime *target)
- {
- ULARGE_INTEGER store;
-- QDateTime tempDateTime(QDate(1601, 1, 1));
--
- store.QuadPart = source->dwHighDateTime;
- store.QuadPart = store.QuadPart << 32;
- store.QuadPart += source->dwLowDateTime;
-
-+ const QDateTime tempDateTime(QDate(1601, 1, 1), QTime(0, 0, 0, 0), Qt::UTC);
- *target = tempDateTime.addMSecs(store.QuadPart / 10000);
- }
-
-@@ -60,6 +59,13 @@ void DateTimeToSystemTime(const QDateTime *source, SYSTEMTIME *target)
- target->wMilliseconds = source->time().msec();
- }
-
-+void DateTimeToFileTime(const QDateTime &dateTime, FILETIME *target)
-+{
-+ const qint64 nsecs = QDateTime(QDate(1601, 1, 1), QTime(0, 0, 0, 0), Qt::UTC)
-+ .msecsTo(dateTime) * 10000;
-+ target->dwLowDateTime = nsecs;
-+ target->dwHighDateTime = nsecs >> 32;
-+}
-
- BOOL WINAPI FileTimeToSystemTime(CONST FILETIME *source,SYSTEMTIME *target)
- {
-@@ -70,21 +76,6 @@ BOOL WINAPI FileTimeToSystemTime(CONST FILETIME *source,SYSTEMTIME *target)
- return TRUE;
- }
-
--BOOL WINAPI SystemTimeToFileTime(const SYSTEMTIME *source,FILETIME *target)
--{
-- // TODO: Implementation!
-- // This doesn't seem to be called at all
--
-- qDebug() << "SystemTimeToFileTime";
--
-- target->dwHighDateTime = 0;
-- target->dwLowDateTime = 0;
--
-- qWarning() << Q_FUNC_INFO;
--
-- return TRUE;
--}
--
- BOOL WINAPI FileTimeToLocalFileTime(CONST FILETIME *source,FILETIME *target)
- {
- target->dwHighDateTime = source->dwHighDateTime;
-@@ -137,3 +128,16 @@ VOID WINAPI GetSystemTime(SYSTEMTIME *st)
- QDateTime nowDateTime = QDateTime::currentDateTimeUtc();
- DateTimeToSystemTime(&nowDateTime, st);
- }
-+
-+VOID WINAPI GetSystemTimeAsFileTime(FILETIME *time)
-+{
-+ DateTimeToFileTime(QDateTime::currentDateTimeUtc(), time);
-+}
-+
-+DWORD WINAPI GetTickCount()
-+{
-+ struct timespec ts;
-+ if (clock_gettime(CLOCK_MONOTONIC, &ts))
-+ return DWORD(ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
-+ return DWORD(QDateTime::currentMSecsSinceEpoch());
-+}
-diff --git a/src/libs/7zip/unix/CPP/myWindows/myWindows.pri b/src/libs/7zip/unix/CPP/myWindows/myWindows.pri
-new file mode 100644
-index 0000000..0875fdb
---- /dev/null
-+++ b/src/libs/7zip/unix/CPP/myWindows/myWindows.pri
-@@ -0,0 +1,7 @@
-+HEADERS += $$7ZIP_BASE/CPP/myWindows/StdAfx.h \
-+ $$7ZIP_BASE/CPP/myWindows/config.h \
-+ $$7ZIP_BASE/CPP/myWindows/initguid.h \
-+ $$7ZIP_BASE/CPP/myWindows/myPrivate.h
-+
-+SOURCES += $$7ZIP_BASE/CPP/myWindows/myDateAndTime.cpp \
-+ $$7ZIP_BASE/CPP/myWindows/myCommandLineParser.cpp
-diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp
-index 8af28b9..e20858e 100644
---- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp
-+++ b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zOut.cpp
-@@ -4,8 +4,6 @@
-
- #include "../../../../C/7zCrc.h"
-
--#include "../../../Common/AutoPtr.h"
--
- #include "../../Common/StreamObjects.h"
-
- #include "7zOut.h"
-diff --git a/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h b/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h
-index 1e9bf14..82bd096 100644
---- a/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h
-+++ b/src/libs/7zip/win/CPP/7zip/Common/RegisterArc.h
-@@ -5,6 +5,8 @@
-
- #include "../Archive/IArchive.h"
-
-+#include <mutex>
-+
- struct CArcInfo
- {
- const char *Name;
-@@ -24,19 +26,35 @@ struct CArcInfo
- Func_IsArc IsArc;
-
- bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }
-+
-+ std::once_flag once;
- };
-
- void RegisterArc(const CArcInfo *arcInfo) throw();
-
- #define REGISTER_ARC_NAME(x) CRegister ## x
-
--#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \
-- REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \
-- static REGISTER_ARC_NAME(x) g_RegisterArc;
--
--#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \
-- REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \
-- static REGISTER_ARC_NAME(x) g_RegisterArc;
-+#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) \
-+ { \
-+ REGISTER_ARC_NAME(x)() \
-+ { \
-+ std::call_once(g_ArcInfo.once, [] { RegisterArc(&g_ArcInfo); }); \
-+ } \
-+ }; \
-+ static REGISTER_ARC_NAME(x) g_RegisterArc; \
-+ void registerArc##x() { static REGISTER_ARC_NAME(x) g_RegisterArc; }
-+
-+#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) \
-+ { \
-+ REGISTER_ARC_NAME(x)() { \
-+ std::call_once(g_ArcInfo.once, [] { \
-+ g_ArcInfo.Signature[0]--; \
-+ RegisterArc(&g_ArcInfo); \
-+ }); \
-+ } \
-+ }; \
-+ static REGISTER_ARC_NAME(x) g_RegisterArc; \
-+ void registerArcDec##x() { static REGISTER_ARC_NAME(x) g_RegisterArc; }
-
-
- #define IMP_CreateArcIn_2(c) \
-diff --git a/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h b/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h
-index 4222a30..0c6662a 100644
---- a/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h
-+++ b/src/libs/7zip/win/CPP/7zip/Common/RegisterCodec.h
-@@ -6,6 +6,8 @@
- #include "../Common/MethodId.h"
- #include "../ICoder.h"
-
-+#include <mutex>
-+
- typedef void * (*CreateCodecP)();
- struct CCodecInfo
- {
-@@ -15,21 +17,34 @@ struct CCodecInfo
- const wchar_t *Name;
- UInt32 NumInStreams;
- bool IsFilter;
-+ std::once_flag once;
- };
-
- void RegisterCodec(const CCodecInfo *codecInfo) throw();
-
- #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x
-
--#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
-- REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
-- static REGISTER_CODEC_NAME(x) g_RegisterCodec;
-+#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) \
-+ { \
-+ REGISTER_CODEC_NAME(x)() \
-+ { \
-+ std::call_once(g_CodecInfo.once, [] { RegisterCodec(&g_CodecInfo); }); \
-+ } \
-+ }; \
-+ static REGISTER_CODEC_NAME(x) g_RegisterCodec; \
-+ void registerCodec##x() { static REGISTER_CODEC_NAME(x) g_RegisterCodecs; }
-
- #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x
--#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
-- REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
-- RegisterCodec(&g_CodecsInfo[i]); }}; \
-- static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
-+#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) \
-+ { \
-+ REGISTER_CODECS_NAME(x)() \
-+ { \
-+ for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
-+ std::call_once(g_CodecsInfo[i].once, [&i] { RegisterCodec(&g_CodecsInfo[i]); }); \
-+ } \
-+ }; \
-+ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; \
-+ void registerCodec##x() { static REGISTER_CODECS_NAME(x) g_RegisterCodecs; }
-
-
- struct CHasherInfo
-diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp
-index df86620..13d2ad2 100644
---- a/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp
-+++ b/src/libs/7zip/win/CPP/7zip/UI/Common/Extract.cpp
-@@ -2,8 +2,6 @@
-
- #include "StdAfx.h"
-
--#include "../../../../C/Sort.h"
--
- #include "../../../Common/StringConvert.h"
-
- #include "../../../Windows/FileDir.h"
---
-2.3.7.windows.1
-
diff --git a/src/libs/ifwtools/binarycreator.cpp b/src/libs/ifwtools/binarycreator.cpp
index cf04355de..341052650 100644
--- a/src/libs/ifwtools/binarycreator.cpp
+++ b/src/libs/ifwtools/binarycreator.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -43,7 +43,7 @@
#include <QDirIterator>
#include <QDomDocument>
#include <QProcess>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QSettings>
#include <QTemporaryFile>
#include <QTemporaryDir>
@@ -223,7 +223,7 @@ static QVersionNumber readMachOMinimumSystemVersion(QIODevice *device)
}
#endif
-static int assemble(Input input, const QInstaller::Settings &settings, const QString &signingIdentity)
+static int assemble(Input input, const QInstaller::Settings &settings, const BinaryCreatorArgs &args)
{
#ifdef Q_OS_MACOS
if (QInstaller::isInBundle(input.installerExePath)) {
@@ -262,7 +262,7 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QFile pkgInfo(fi.filePath() + QLatin1String("/Contents/PkgInfo"));
pkgInfo.open(QIODevice::WriteOnly);
QTextStream pkgInfoStream(&pkgInfo);
- pkgInfoStream << QLatin1String("APPL????") << endl;
+ pkgInfoStream << QLatin1String("APPL????") << Qt::endl;
}
QString iconFile;
@@ -282,44 +282,44 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QFile infoPList(fi.filePath() + QLatin1String("/Contents/Info.plist"));
infoPList.open(QIODevice::WriteOnly);
QTextStream plistStream(&infoPList);
- plistStream << QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") << endl;
+ plistStream << QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") << Qt::endl;
plistStream << QLatin1String("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
- "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") << endl;
- plistStream << QLatin1String("<plist version=\"1.0\">") << endl;
- plistStream << QLatin1String("<dict>") << endl;
- plistStream << QLatin1String("\t<key>CFBundleIconFile</key>") << endl;
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") << Qt::endl;
+ plistStream << QLatin1String("<plist version=\"1.0\">") << Qt::endl;
+ plistStream << QLatin1String("<dict>") << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleIconFile</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << iconTargetFile << QLatin1String("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundlePackageType</key>") << endl;
- plistStream << QLatin1String("\t<string>APPL</string>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundlePackageType</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>APPL</string>") << Qt::endl;
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
- plistStream << QLatin1String("\t<key>CFBundleShortVersionString</key>") << endl;
+ plistStream << QLatin1String("\t<key>CFBundleShortVersionString</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundleVersion</key>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleVersion</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
- << endl;
+ << Qt::endl;
#undef QUOTE
#undef QUOTE_
- plistStream << QLatin1String("\t<key>CFBundleSignature</key>") << endl;
- plistStream << QLatin1String("\t<string>\?\?\?\?</string>") << endl;
- plistStream << QLatin1String("\t<key>CFBundleExecutable</key>") << endl;
+ plistStream << QLatin1String("\t<key>CFBundleSignature</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>\?\?\?\?</string>") << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleExecutable</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << fi.completeBaseName() << QLatin1String("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundleIdentifier</key>") << endl;
- plistStream << QLatin1String("\t<string>com.yourcompany.installerbase</string>") << endl;
- plistStream << QLatin1String("\t<key>NOTE</key>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleIdentifier</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>com.yourcompany.installerbase</string>") << Qt::endl;
+ plistStream << QLatin1String("\t<key>NOTE</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>This file was generated by Qt Installer Framework.</string>")
- << endl;
- plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << endl;
- plistStream << QLatin1String("\t<string>NSApplication</string>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>NSApplication</string>") << Qt::endl;
if (!minimumSystemVersion.isEmpty()) {
- plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << endl;
- plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << endl;
+ plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << Qt::endl;
}
- plistStream << QLatin1String("</dict>") << endl;
- plistStream << QLatin1String("</plist>") << endl;
+ plistStream << QLatin1String("</dict>") << Qt::endl;
+ plistStream << QLatin1String("</plist>") << Qt::endl;
input.outputPath = QString::fromLatin1("%1/Contents/MacOS/%2").arg(input.outputPath)
.arg(fi.completeBaseName());
@@ -405,22 +405,26 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QInstaller::appendData(&out, &exe, exe.size());
#endif
- foreach (const QInstallerTools::PackageInfo &info, input.packages) {
- QInstaller::ResourceCollection collection;
- collection.setName(info.name.toUtf8());
-
- qDebug() << "Creating resource archive for" << info.name;
- foreach (const QString &copiedFile, info.copiedFiles) {
- const QSharedPointer<Resource> resource(new Resource(copiedFile));
- qDebug().nospace() << "Appending " << copiedFile << " (" << humanReadableSize(resource->size()) << ")";
- collection.appendResource(resource);
+ if (!args.createMaintenanceTool) {
+ foreach (const QInstallerTools::PackageInfo &info, input.packages) {
+ QInstaller::ResourceCollection collection;
+ collection.setName(info.name.toUtf8());
+ qDebug() << "Creating resource archive for" << info.name;
+ foreach (const QString &copiedFile, info.copiedFiles) {
+ const QSharedPointer<Resource> resource(new Resource(copiedFile));
+ qDebug().nospace() << "Appending " << copiedFile << " (" << humanReadableSize(resource->size()) << ")";
+ collection.appendResource(resource);
+ }
+ input.manager.insertCollection(collection);
}
- input.manager.insertCollection(collection);
+
+ const QList<QInstaller::OperationBlob> operations;
+ BinaryContent::writeBinaryContent(&out, operations, input.manager,
+ BinaryContent::MagicInstallerMarker, BinaryContent::MagicCookie);
+ } else {
+ createMTDatFile(out);
}
- const QList<QInstaller::OperationBlob> operations;
- BinaryContent::writeBinaryContent(&out, operations, input.manager,
- BinaryContent::MagicInstallerMarker, BinaryContent::MagicCookie);
} catch (const Error &e) {
qCritical("Error occurred while assembling the installer: %s", qPrintable(e.message()));
QFile::remove(tempFile);
@@ -445,14 +449,14 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QFile::remove(tempFile);
#ifdef Q_OS_MACOS
- if (isBundle && !signingIdentity.isEmpty()) {
+ if (isBundle && !args.signingIdentity.isEmpty()) {
qDebug() << "Signing .app bundle...";
QProcess p;
p.start(QLatin1String("codesign"),
QStringList() << QLatin1String("--force")
<< QLatin1String("--deep")
- << QLatin1String("--sign") << signingIdentity
+ << QLatin1String("--sign") << args.signingIdentity
<< bundle);
if (!p.waitForFinished(-1)) {
@@ -503,8 +507,6 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QDir(bundle).removeRecursively();
qDebug() << "done.";
}
-#else
- Q_UNUSED(signingIdentity)
#endif
return EXIT_SUCCESS;
}
@@ -609,27 +611,38 @@ void QInstallerTools::copyConfigData(const QString &configFile, const QString &t
qDebug().noquote() << QString::fromLatin1("Read dom element: <%1>%2</%1>.").arg(tagName, elementText);
if (tagName == QLatin1String("ProductImages")) {
- const QDomNodeList childNodes = domElement.childNodes();
- for (int index = 0; index < childNodes.count(); ++index) {
- const QDomElement childElement = childNodes.at(index).toElement();
- const QString childName = childElement.tagName();
- if (childName != QLatin1String("Image"))
+ const QDomNodeList productImageNode = domElement.childNodes();
+ for (int j = 0; j < productImageNode.count(); ++j) {
+ QDomElement productImagesElement = productImageNode.at(j).toElement();
+ if (productImagesElement.isNull())
continue;
+ const QString childName = productImagesElement.tagName();
+ if (childName != QLatin1String("ProductImage"))
+ continue;
+ const QDomNodeList imageNode = productImagesElement.childNodes();
+ for (int k = 0; k < imageNode.count(); ++k) {
+ QDomElement productImageElement = imageNode.at(k).toElement();
+ if (productImageElement.isNull())
+ continue;
+ const QString imageChildName = productImageElement.tagName();
+ if (imageChildName != QLatin1String("Image"))
+ continue;
+ const QString targetFile = targetDir + QLatin1Char('/') + productImageElement.text();
+ const QFileInfo childFileInfo = QFileInfo(sourceConfigFilePath, productImageElement.text());
+ QInstallerTools::copyWithException(childFileInfo.absoluteFilePath(), targetFile, imageChildName);
+ copyHighDPIImage(childFileInfo, imageChildName, targetFile);
+ }
- const QString targetFile = targetDir + QLatin1Char('/') + childElement.text();
- const QFileInfo childFileInfo = QFileInfo(sourceConfigFilePath, childElement.text());
- QInstallerTools::copyWithException(childFileInfo.absoluteFilePath(), targetFile, childName);
- copyHighDPIImage(childFileInfo, childName, targetFile);
}
continue;
}
- QString newName = domElement.text().replace(QRegExp(QLatin1String("\\\\|/|\\.|:")),
- QLatin1String("_"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/|\\.|:"));
+ QString newName = domElement.text().replace(regex, QLatin1String("_"));
QString targetFile;
QFileInfo elementFileInfo;
- if (tagName == QLatin1String("Icon") || tagName == QLatin1String("InstallerApplicationIcon")) {
+ if (tagName == QLatin1String("InstallerApplicationIcon")) {
#if defined(Q_OS_MACOS)
const QString suffix = QLatin1String(".icns");
#elif defined(Q_OS_WIN)
@@ -691,13 +704,13 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
// Begin check arguments
foreach (const QString &packageDir, args.packagesDirectories) {
- if (!QFileInfo(packageDir).exists()) {
+ if (!QFileInfo::exists(packageDir)) {
argumentError = QString::fromLatin1("Error: Package directory not found at the specified location.");
return EXIT_FAILURE;
}
}
foreach (const QString &repositoryDir, args.repositoryDirectories) {
- if (!QFileInfo(repositoryDir).exists()) {
+ if (!QFileInfo::exists(repositoryDir)) {
argumentError = QString::fromLatin1("Error: Only local filesystem repositories now supported.");
return EXIT_FAILURE;
}
@@ -708,12 +721,12 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
"contain any components apart from the root component.");
return EXIT_FAILURE;
}
- if (!QFileInfo(args.templateBinary).exists()) {
+ if (!QFileInfo::exists(args.templateBinary)) {
#ifdef Q_OS_WIN
if (!args.templateBinary.endsWith(suffix))
args.templateBinary = args.templateBinary + suffix;
// Try again with added executable suffix
- if (!QFileInfo(args.templateBinary).exists()) {
+ if (!QFileInfo::exists(args.templateBinary)) {
argumentError = QString::fromLatin1("Error: Template base binary not found at the specified location.");
return EXIT_FAILURE;
}
@@ -743,7 +756,7 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
"--offline-only at the same time.");
return EXIT_FAILURE;
}
- if (args.target.isEmpty() && !args.compileResource) {
+ if (args.target.isEmpty() && !args.compileResource && !args.createMaintenanceTool) {
argumentError = QString::fromLatin1("Error: Target parameter missing.");
return EXIT_FAILURE;
}
@@ -751,7 +764,9 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
argumentError = QString::fromLatin1("Error: No configuration file selected.");
return EXIT_FAILURE;
}
- if (args.packagesDirectories.isEmpty() && args.repositoryDirectories.isEmpty()) {
+ if (args.packagesDirectories.isEmpty() && args.repositoryDirectories.isEmpty()
+ && !args.compileResource
+ && !args.createMaintenanceTool) {
argumentError = QString::fromLatin1("Error: Both Package directory and Repository parameters missing.");
return EXIT_FAILURE;
}
@@ -827,11 +842,6 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
confInternal.setValue(QLatin1String("offlineOnly"), args.offlineOnly);
}
-#ifdef Q_OS_MACOS
- // on mac, we enforce building a bundle
- if (!args.target.endsWith(QLatin1String(".app")) && !args.target.endsWith(QLatin1String(".dmg")))
- args.target += QLatin1String(".app");
-#endif
if (!args.compileResource) {
// 5; put the copied resources into a resource file
ResourceCollection metaCollection("QResources");
@@ -841,11 +851,20 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
input.manager.insertCollection(metaCollection);
input.packages = packages;
- input.outputPath = args.target;
+ if (args.createMaintenanceTool)
+ input.outputPath = settings.maintenanceToolName();
+ else
+ input.outputPath = args.target;
input.installerExePath = args.templateBinary;
+#ifdef Q_OS_MACOS
+ // on mac, we enforce building a bundle
+ if (!input.outputPath.endsWith(QLatin1String(".app")) && !input.outputPath.endsWith(QLatin1String(".dmg")))
+ input.outputPath += QLatin1String(".app");
+#endif
+
qDebug() << "Creating the binary";
- exitCode = assemble(input, settings, args.signingIdentity);
+ exitCode = assemble(input, settings, args);
} else {
createDefaultResourceFile(tmpMetaDir, QDir::currentPath() + QLatin1String("/update.rcc"));
exitCode = EXIT_SUCCESS;
@@ -867,3 +886,13 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
return exitCode;
}
+
+void QInstallerTools::createMTDatFile(QFile &datFile)
+{
+ QInstaller::appendInt64(&datFile, 0); // operations start
+ QInstaller::appendInt64(&datFile, 0); // operations end
+ QInstaller::appendInt64(&datFile, 0); // resource count
+ QInstaller::appendInt64(&datFile, 4 * sizeof(qint64)); // data block size
+ QInstaller::appendInt64(&datFile, BinaryContent::MagicUninstallerMarker);
+ QInstaller::appendInt64(&datFile, BinaryContent::MagicCookie);
+}
diff --git a/src/libs/ifwtools/binarycreator.h b/src/libs/ifwtools/binarycreator.h
index 7c14ea039..387195742 100644
--- a/src/libs/ifwtools/binarycreator.h
+++ b/src/libs/ifwtools/binarycreator.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -68,6 +68,7 @@ struct IFWTOOLS_EXPORT BinaryCreatorArgs
FilterType ftype = QInstallerTools::Exclude;
bool compileResource = false;
QString signingIdentity;
+ bool createMaintenanceTool = false;
};
class BundleBackup
@@ -76,7 +77,7 @@ public:
explicit BundleBackup(const QString &bundle = QString())
: bundle(bundle)
{
- if (!bundle.isEmpty() && QFileInfo(bundle).exists()) {
+ if (!bundle.isEmpty() && QFileInfo::exists(bundle)) {
backup = QInstaller::generateTemporaryFileName(bundle);
QFile::rename(bundle, backup);
}
@@ -124,6 +125,7 @@ void copyConfigData(const QString &configFile, const QString &targetDir);
void copyHighDPIImage(const QFileInfo &childFileInfo, const QString &childName, const QString &targetFile);
int IFWTOOLS_EXPORT createBinary(BinaryCreatorArgs args, QString &argumentError);
+void IFWTOOLS_EXPORT createMTDatFile(QFile &datFile);
} // namespace QInstallerTools
diff --git a/src/libs/ifwtools/rcc/rcc.cpp b/src/libs/ifwtools/rcc/rcc.cpp
index 12f399937..caef84433 100644
--- a/src/libs/ifwtools/rcc/rcc.cpp
+++ b/src/libs/ifwtools/rcc/rcc.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -36,7 +36,7 @@
#include <QtCore/QFile>
#include <QtCore/QIODevice>
#include <QtCore/QLocale>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtCore/QStack>
#include <QXmlStreamReader>
@@ -108,7 +108,7 @@ public:
QLocale::Country m_country;
QFileInfo m_fileInfo;
RCCFileInfo *m_parent;
- QHash<QString, RCCFileInfo*> m_children;
+ QMultiHash<QString, RCCFileInfo*> m_children;
int m_compressLevel;
int m_compressThreshold;
@@ -583,10 +583,10 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
if (!parent->m_children.contains(node)) {
RCCFileInfo *s = new RCCFileInfo(node, QFileInfo(), QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory);
s->m_parent = parent;
- parent->m_children.insert(node, s);
+ parent->m_children.replace(node, s);
parent = s;
} else {
- parent = parent->m_children[node];
+ parent = parent->m_children.value(node);
}
}
@@ -598,7 +598,7 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
qWarning("%s: Warning: potential duplicate alias detected: '%s'",
qPrintable(fileName), qPrintable(filename));
}
- parent->m_children.insertMulti(filename, s);
+ parent->m_children.insert(filename, s);
return true;
}
@@ -664,7 +664,7 @@ QStringList RCCResourceLibrary::dataFiles() const
pending.push(m_root);
while (!pending.isEmpty()) {
RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
+ for (QMultiHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
it != file->m_children.end(); ++it) {
RCCFileInfo *child = it.value();
if (child->m_flags & RCCFileInfo::Directory)
@@ -678,7 +678,7 @@ QStringList RCCResourceLibrary::dataFiles() const
// Determine map of resource identifier (':/newPrefix/images/p1.png') to file via recursion
static void resourceDataFileMapRecursion(const RCCFileInfo *m_root, const QString &path, RCCResourceLibrary::ResourceDataFileMap &m)
{
- typedef QHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator;
+ typedef QMultiHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator;
const QChar slash = QLatin1Char('/');
const ChildConstIterator cend = m_root->m_children.constEnd();
for (ChildConstIterator it = m_root->m_children.constBegin(); it != cend; ++it) {
@@ -815,7 +815,7 @@ bool RCCResourceLibrary::writeDataBlobs()
QString errorMessage;
while (!pending.isEmpty()) {
RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
+ for (QMultiHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
it != file->m_children.end(); ++it) {
RCCFileInfo *child = it.value();
if (child->m_flags & RCCFileInfo::Directory)
@@ -851,7 +851,7 @@ bool RCCResourceLibrary::writeDataNames()
qint64 offset = 0;
while (!pending.isEmpty()) {
RCCFileInfo *file = pending.pop();
- for (QHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
+ for (QMultiHash<QString, RCCFileInfo*>::iterator it = file->m_children.begin();
it != file->m_children.end(); ++it) {
RCCFileInfo *child = it.value();
if (child->m_flags & RCCFileInfo::Directory)
@@ -894,7 +894,7 @@ bool RCCResourceLibrary::writeDataStructure()
//sort by hash value for binary lookup
QList<RCCFileInfo*> m_children = file->m_children.values();
- qSort(m_children.begin(), m_children.end(), qt_rcc_compare_hash);
+ std::sort(m_children.begin(), m_children.end(), qt_rcc_compare_hash);
//write out the actual data now
for (int i = 0; i < m_children.size(); ++i) {
@@ -913,7 +913,7 @@ bool RCCResourceLibrary::writeDataStructure()
//sort by hash value for binary lookup
QList<RCCFileInfo*> m_children = file->m_children.values();
- qSort(m_children.begin(), m_children.end(), qt_rcc_compare_hash);
+ std::sort(m_children.begin(), m_children.end(), qt_rcc_compare_hash);
//write out the actual data now
for (int i = 0; i < m_children.size(); ++i) {
@@ -958,7 +958,7 @@ bool RCCResourceLibrary::writeInitializer()
QString initName = m_initName;
if (!initName.isEmpty()) {
initName.prepend(QLatin1Char('_'));
- initName.replace(QRegExp(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
+ initName.replace(QRegularExpression(QLatin1String("[^a-zA-Z0-9_]")), QLatin1String("_"));
}
//init
diff --git a/src/libs/ifwtools/repositorygen.cpp b/src/libs/ifwtools/repositorygen.cpp
index a045c5248..9232a02d4 100644
--- a/src/libs/ifwtools/repositorygen.cpp
+++ b/src/libs/ifwtools/repositorygen.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -34,6 +34,7 @@
#include "errors.h"
#include "globals.h"
#include "archivefactory.h"
+#include "metadata.h"
#include "settings.h"
#include "qinstallerglobal.h"
#include "utils.h"
@@ -42,7 +43,7 @@
#include "updater.h"
#include <QtCore/QDirIterator>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtXml/QDomDocument>
#include <QTemporaryDir>
@@ -128,6 +129,75 @@ static QStringList copyFilesFromNode(const QString &parentNode, const QString &c
return copiedFiles;
}
+/*
+ Returns \c true if the \a file is an archive or an SHA1 checksum
+ file for an archive, /c false otherwise.
+*/
+static bool isArchiveOrChecksum(const QString &file)
+{
+ if (file.endsWith(QLatin1String(".sha1")))
+ return true;
+
+ for (auto &supportedSuffix : ArchiveFactory::supportedTypes()) {
+ if (file.endsWith(supportedSuffix))
+ return true;
+ }
+ return false;
+}
+
+/*
+ Fills the package \a info with the name of the metadata archive when applicable. Returns
+ \c true if the component has metadata compressed in an archive or uncompressed to cache, or
+ if the metadata archive is redundant. Returns \c false if the component should have metadata
+ but none was found.
+*/
+static bool findMetaFile(const QString &repositoryDir, const QDomElement &packageUpdate, PackageInfo &info)
+{
+ // Note: the order here is important, when updating from an existing
+ // repository we shouldn't drop the empty metadata archives.
+
+ // 1. First, try with normal repository structure
+ QString metaFile = QString::fromLatin1("%1/%3%2").arg(info.directory,
+ QString::fromLatin1("meta.7z"), info.version);
+
+ if (QFileInfo::exists(metaFile)) {
+ info.metaFile = metaFile;
+ return true;
+ }
+
+ // 2. If that does not work, check for fetched temporary repository structure
+ metaFile = QString::fromLatin1("%1/%2-%3-%4").arg(repositoryDir,
+ info.name, info.version, QString::fromLatin1("meta.7z"));
+
+ if (QFileInfo::exists(metaFile)) {
+ info.metaFile = metaFile;
+ return true;
+ }
+
+ // 3. Try with the cached metadata directory structure
+ const QDir packageDir(info.directory);
+ const QStringList cachedMetaFiles = packageDir.entryList(QDir::Files);
+ for (auto &file : cachedMetaFiles) {
+ if (!isArchiveOrChecksum(file))
+ return true; // Return for first non-archive file
+ }
+
+ // 4. The meta archive may be redundant, skip in that case (cached item from a
+ // repository that has empty meta archive)
+ bool metaElementFound = false;
+ const QDomNodeList c1 = packageUpdate.childNodes();
+ for (int i = 0; i < c1.count(); ++i) {
+ const QDomElement e1 = c1.at(i).toElement();
+ for (const QString &meta : scMetaElements) {
+ if (e1.tagName() == meta) {
+ metaElementFound = true;
+ break;
+ }
+ }
+ }
+ return !metaElementFound;
+}
+
void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &metaDataDir,
const PackageInfoVector &packages, const QString &appName, const QString &appVersion,
const QStringList &uniteMetadatas)
@@ -297,39 +367,8 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
root.appendChild(update);
- // copy script file
- const QString script = package.firstChildElement(QLatin1String("Script")).text();
- if (!script.isEmpty()) {
- QFile scriptFile(QString::fromLatin1("%1/meta/%2").arg(info.directory, script));
- if (!scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- throw QInstaller::Error(QString::fromLatin1("Cannot open component script at \"%1\".")
- .arg(QDir::toNativeSeparators(scriptFile.fileName())));
- }
-
- const QString scriptContent = QLatin1String("(function() {")
- + QString::fromUtf8(scriptFile.readAll())
- + QLatin1String(";"
- " if (typeof Component == \"undefined\")"
- " throw \"Missing Component constructor. Please check your script.\";"
- "})();");
-
- // if the user isn't aware of the downloadable archives value we will add it automatically later
- foundDownloadableArchives |= scriptContent.contains(QLatin1String("addDownloadableArchive"))
- || scriptContent.contains(QLatin1String("removeDownloadableArchive"));
-
- static QInstaller::ScriptEngine testScriptEngine;
- const QJSValue value = testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
- if (value.isError()) {
- throw QInstaller::Error(QString::fromLatin1("Exception while loading component "
- "script at \"%1\": %2").arg(QDir::toNativeSeparators(scriptFile.fileName()),
- value.toString().isEmpty() ? QString::fromLatin1("Unknown error.") :
- value.toString() + QStringLiteral(" on line number: ") +
- value.property(QStringLiteral("lineNumber")).toString()));
- }
-
- const QString toLocation(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, script));
- copyWithException(scriptFile.fileName(), toLocation, QInstaller::scScript);
- }
+ // copy script files
+ copyScriptFiles(childNodes, info, foundDownloadableArchives, targetDir);
// write DownloadableArchives tag if that is missed by the user
if (!foundDownloadableArchives && !info.copiedFiles.isEmpty()) {
@@ -338,7 +377,7 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
if (!filePath.endsWith(QLatin1String(".sha1"), Qt::CaseInsensitive)) {
const QString fileName = QFileInfo(filePath).fileName();
// remove unnecessary version string from filename and add it to the list
- realContentFiles.append(fileName.mid(info.version.count()));
+ realContentFiles.append(fileName.mid(info.version.size()));
}
}
@@ -398,6 +437,19 @@ void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &met
throw Error(QString::fromLatin1("Could not extract archive \"%1\": %2").arg(
QDir::toNativeSeparators(info.metaFile), metaFile->errorString()));
}
+ } else {
+ // The metadata may have been already extracted, i.e. when reading from a
+ // local repository cache.
+ const QDir packageDir(info.directory);
+ const QStringList metaFiles = packageDir.entryList(QDir::Files);
+ for (auto &file : metaFiles) {
+ if (isArchiveOrChecksum(file))
+ continue; // Skip data archives
+
+ const QString source(QString::fromLatin1("%1/%2").arg(info.directory, file));
+ const QString target(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, file));
+ copyWithException(source, target, QLatin1String("cached metadata"));
+ }
}
// Restore "PackageUpdate" node;
@@ -517,15 +569,15 @@ PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packa
info.version = packageElement.firstChildElement(QLatin1String("Version")).text();
// Version cannot start with comparison characters, be an empty string
// or have whitespaces at the beginning or at the end
- if (!QRegExp(QLatin1String("(?![<=>\\s]+)(.+)")).exactMatch(info.version) ||
- (info.version != info.version.trimmed())) {
+ static const QRegularExpression regex(QLatin1String("^(?![<=>\\s]+)(.+)$"));
+ if (!regex.match(info.version).hasMatch() || (info.version != info.version.trimmed())) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QString::fromLatin1("Component version for \"%1\" is invalid! <Version>%2</Version>")
.arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()), info.version));
}
info.dependencies = packageElement.firstChildElement(QLatin1String("Dependencies")).text()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ .split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
info.directory = it->filePath();
if (packagesUpdatedWithSha.contains(info.name)) {
info.createContentSha1Node = true;
@@ -639,22 +691,9 @@ PackageInfoVector QInstallerTools::createListOfRepositoryPackages(const QStringL
info.directory = QString::fromLatin1("%1/%2").arg(it->filePath(), info.name);
if (!hasUnifiedMetaFile) {
const QDomElement sha1 = el.firstChildElement(QInstaller::scSHA1);
- if (!sha1.isNull()) {
- // 1. First, try with normal repository structure
- QString metaFile = QString::fromLatin1("%1/%3%2").arg(info.directory,
- QString::fromLatin1("meta.7z"), info.version);
-
- if (!QFileInfo(metaFile).exists()) {
- // 2. If that does not work, check for fetched temporary repository structure
- metaFile = QString::fromLatin1("%1/%2-%3-%4").arg(it->filePath(),
- info.name, info.version, QString::fromLatin1("meta.7z"));
-
- if (!QFileInfo(metaFile).exists()) {
- throw QInstaller::Error(QString::fromLatin1("Could not find meta archive for component "
- "%1 %2 in repository %3.").arg(info.name, info.version, it->filePath()));
- }
- }
- info.metaFile = metaFile;
+ if (!sha1.isNull() && !findMetaFile(it->filePath(), el, info)) {
+ throw QInstaller::Error(QString::fromLatin1("Could not find metadata archive for component "
+ "%1 %2 in repository %3.").arg(info.name, info.version, it->filePath()));
}
}
@@ -663,10 +702,10 @@ PackageInfoVector QInstallerTools::createListOfRepositoryPackages(const QStringL
const QDomElement c2Element = c2.at(j).toElement();
if (c2Element.tagName() == QInstaller::scDependencies)
info.dependencies = c2Element.text()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ .split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
else if (c2Element.tagName() == QInstaller::scDownloadableArchives) {
QStringList names = c2Element.text()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ .split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
foreach (const QString &name, names) {
info.copiedFiles.append(QString::fromLatin1("%1/%3%2").arg(info.directory,
name, info.version));
@@ -907,6 +946,50 @@ void QInstallerTools::splitMetadata(const QStringList &entryList, const QString
}
}
+void QInstallerTools::copyScriptFiles(const QDomNodeList &childNodes, const PackageInfo &info, bool &foundDownloadableArchives, const QString &targetDir)
+{
+ for (int i = 0; i < childNodes.count(); ++i) {
+ const QDomNode node = childNodes.at(i);
+ const QString key = node.nodeName();
+
+ if (key != QLatin1String("Script"))
+ continue;
+ const QString script = node.toElement().text();
+ if (script.isEmpty())
+ continue;
+
+ QFile scriptFile(QString::fromLatin1("%1/meta/%2").arg(info.directory, script));
+ if (!scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ throw QInstaller::Error(QString::fromLatin1("Cannot open component script at \"%1\".")
+ .arg(QDir::toNativeSeparators(scriptFile.fileName())));
+ }
+
+ const QString scriptContent = QLatin1String("(function() {")
+ + QString::fromUtf8(scriptFile.readAll())
+ + QLatin1String(";"
+ " if (typeof Component == \"undefined\")"
+ " throw \"Missing Component constructor. Please check your script.\";"
+ "})();");
+
+ // if the user isn't aware of the downloadable archives value we will add it automatically later
+ foundDownloadableArchives |= scriptContent.contains(QLatin1String("addDownloadableArchive"))
+ || scriptContent.contains(QLatin1String("removeDownloadableArchive"));
+
+ static QInstaller::ScriptEngine testScriptEngine;
+ const QJSValue value = testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
+ if (value.isError()) {
+ throw QInstaller::Error(QString::fromLatin1("Exception while loading component "
+ "script at \"%1\": %2").arg(QDir::toNativeSeparators(scriptFile.fileName()),
+ value.toString().isEmpty() ? QString::fromLatin1("Unknown error.") :
+ value.toString() + QStringLiteral(" on line number: ") +
+ value.property(QStringLiteral("lineNumber")).toString()));
+ }
+
+ const QString toLocation(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, script));
+ copyWithException(scriptFile.fileName(), toLocation, QInstaller::scScript);
+ }
+}
+
void QInstallerTools::copyComponentData(const QStringList &packageDirs, const QString &repoDir,
PackageInfoVector *const infos, const QString &archiveSuffix, Compression compression)
{
diff --git a/src/libs/ifwtools/repositorygen.h b/src/libs/ifwtools/repositorygen.h
index 054c023f4..7ad3dd073 100644
--- a/src/libs/ifwtools/repositorygen.h
+++ b/src/libs/ifwtools/repositorygen.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -88,6 +88,7 @@ void IFWTOOLS_EXPORT compressMetaDirectories(const QString &repoDir, const QStri
QStringList unifyMetadata(const QString &repoDir, const QString &existingRepoDir, QDomDocument doc);
void splitMetadata(const QStringList &entryList, const QString &repoDir, QDomDocument doc,
const QHash<QString, QString> &versionMapping);
+void copyScriptFiles(const QDomNodeList &childNodes, const PackageInfo &info, bool &foundDownloadableArchives, const QString &targetDir);
void IFWTOOLS_EXPORT copyMetaData(const QString &outDir, const QString &dataDir, const PackageInfoVector &packages,
const QString &appName, const QString& appVersion, const QStringList &uniteMetadatas);
diff --git a/src/libs/installer/abstractarchive.h b/src/libs/installer/abstractarchive.h
index 77cc35b61..86b4b4ffa 100644
--- a/src/libs/installer/abstractarchive.h
+++ b/src/libs/installer/abstractarchive.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -46,16 +46,19 @@ struct INSTALLER_EXPORT ArchiveEntry
{
ArchiveEntry()
: isDirectory(false)
+ , isSymbolicLink(false)
, compressedSize(0)
, uncompressedSize(0)
, permissions_mode(0)
- , permissions_enum(0)
{}
+ ArchiveEntry(const ArchiveEntry &) = default;
+
QString path;
QDateTime utcTime;
QPoint archiveIndex;
bool isDirectory;
+ bool isSymbolicLink;
quint64 compressedSize;
quint64 uncompressedSize;
mode_t permissions_mode;
diff --git a/src/libs/installer/abstracttask.h b/src/libs/installer/abstracttask.h
index 9a44c50a9..5ee23bef5 100644
--- a/src/libs/installer/abstracttask.h
+++ b/src/libs/installer/abstracttask.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,7 +31,9 @@
#include "runextensions.h"
+#include <QException>
#include <QFutureInterface>
+#include <QVariant>
namespace QInstaller {
@@ -58,9 +60,9 @@ public:
: m_message(message)
{}
- void raise() const { throw *this; }
+ void raise() const override { throw *this; }
QString message() const { return m_message; }
- TaskException *clone() const { return new TaskException(*this); }
+ TaskException *clone() const override { return new TaskException(*this); }
private:
QString m_message;
diff --git a/src/libs/installer/archivefactory.cpp b/src/libs/installer/archivefactory.cpp
index a946f9416..56811d8e3 100644
--- a/src/libs/installer/archivefactory.cpp
+++ b/src/libs/installer/archivefactory.cpp
@@ -27,9 +27,10 @@
**************************************************************************/
#include "archivefactory.h"
-#include "lib7zarchive.h"
#ifdef IFW_LIBARCHIVE
#include "libarchivewrapper.h"
+#elif defined(IFW_LIB7Z)
+#include "lib7zarchive.h"
#endif
#include <QFileInfo>
@@ -50,7 +51,8 @@ using namespace QInstaller;
of this class can be created and its reference can be fetched from
the \c {instance()} method.
- The following archive handlers are registered by default:
+ Depending of the configuration features set at build time, one of the
+ following archive handlers is registered by default:
\list
\li Lib7z
\li LibArchive
@@ -137,11 +139,13 @@ bool ArchiveFactory::isSupportedType(const QString &filename)
*/
ArchiveFactory::ArchiveFactory()
{
- registerArchive<Lib7zArchive>(QLatin1String("Lib7z"), QStringList()
- << QLatin1String("7z"));
#ifdef IFW_LIBARCHIVE
registerArchive<LibArchiveWrapper>(QLatin1String("LibArchive"), QStringList()
- << QLatin1String("tar.gz") << QLatin1String("tar.bz2")
- << QLatin1String("tar.xz") << QLatin1String("zip") );
+ << QLatin1String("tar") << QLatin1String("tar.gz") << QLatin1String("tar.bz2")
+ << QLatin1String("tar.xz") << QLatin1String("zip") << QLatin1String("7z")
+ << QLatin1String("qbsp"));
+#elif defined(IFW_LIB7Z)
+ registerArchive<Lib7zArchive>(QLatin1String("Lib7z"), QStringList()
+ << QLatin1String("7z") << QLatin1String("qbsp"));
#endif
}
diff --git a/src/libs/installer/aspectratiolabel.cpp b/src/libs/installer/aspectratiolabel.cpp
index c8c3c1693..b5a21424d 100644
--- a/src/libs/installer/aspectratiolabel.cpp
+++ b/src/libs/installer/aspectratiolabel.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -28,6 +28,9 @@
#include "aspectratiolabel.h"
+#include <QDesktopServices>
+#include <QTimer>
+
using namespace QInstaller;
/*!
@@ -42,16 +45,35 @@ using namespace QInstaller;
*/
AspectRatioLabel::AspectRatioLabel(QWidget *parent)
: QLabel(parent)
+ , m_discardMousePress(false)
{
setMinimumSize(1, 1);
setScaledContents(false);
+ setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
}
/*!
- Sets the \a pixmap shown on the label. Setting a new pixmap clears the previous content.
+ Sets the \a pixmap shown on the label. Setting a new pixmap clears
+ the previous content.
+
+ \note This redefines the non-virtual slot of the same signature from the
+ QLabel base class, which results in non polymorphic behavior when
+ called via a base class pointer.
*/
void AspectRatioLabel::setPixmap(const QPixmap &pixmap)
{
+ setPixmapAndUrl(pixmap, QString());
+}
+
+/*!
+ Sets the \a pixmap shown on the label and an \a url. Setting a new
+ pixmap clears the previous content. When clicking the \a pixmap, \a url
+ is opened in a browser. If the \a url is a reference to a file, it will
+ be opened with a suitable application instead of a Web browser.
+*/
+void AspectRatioLabel::setPixmapAndUrl(const QPixmap &pixmap, const QString &url)
+{
+ m_clickableUrl = url;
m_pixmap = pixmap;
QLabel::setPixmap(scaledPixmap());
}
@@ -98,3 +120,28 @@ void AspectRatioLabel::resizeEvent(QResizeEvent *event)
if (!m_pixmap.isNull())
QLabel::setPixmap(scaledPixmap());
}
+
+/*!
+ \reimp
+*/
+void AspectRatioLabel::mousePressEvent(QMouseEvent* event)
+{
+ Q_UNUSED(event)
+ if (!m_clickableUrl.isEmpty() && !m_discardMousePress)
+ QDesktopServices::openUrl(m_clickableUrl);
+}
+
+/*!
+ \reimp
+*/
+bool AspectRatioLabel::event(QEvent *e)
+{
+ if (e->type() == QEvent::WindowActivate) {
+ QTimer::singleShot(100, [&]() {
+ m_discardMousePress = false;
+ });
+ } else if (e->type() == QEvent::WindowDeactivate) {
+ m_discardMousePress = true;
+ }
+ return QLabel::event(e);
+}
diff --git a/src/libs/installer/aspectratiolabel.h b/src/libs/installer/aspectratiolabel.h
index 6fbc774a2..bbe54d3a1 100644
--- a/src/libs/installer/aspectratiolabel.h
+++ b/src/libs/installer/aspectratiolabel.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -44,18 +44,25 @@ class INSTALLER_EXPORT AspectRatioLabel : public QLabel
public:
explicit AspectRatioLabel(QWidget *parent = nullptr);
- int heightForWidth(int w) const Q_DECL_OVERRIDE;
- QSize sizeHint() const Q_DECL_OVERRIDE;
+ int heightForWidth(int w) const override;
+ QSize sizeHint() const override;
public slots:
- void setPixmap (const QPixmap &pixmap);
- void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
+ void setPixmap(const QPixmap &pixmap);
+ void setPixmapAndUrl (const QPixmap &pixmap, const QString &url);
+ void resizeEvent(QResizeEvent *event) override;
+
+protected:
+ void mousePressEvent(QMouseEvent* event) override;
+ bool event(QEvent *e) override;
private:
QPixmap scaledPixmap() const;
private:
QPixmap m_pixmap;
+ QString m_clickableUrl;
+ bool m_discardMousePress;
};
} // namespace QInstaller
diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp
index 9ed7742db..ad80ba7bb 100644
--- a/src/libs/installer/binaryformat.cpp
+++ b/src/libs/installer/binaryformat.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -153,12 +153,19 @@ void Resource::setName(const QByteArray &name)
Opens a resource in QIODevice::ReadOnly mode. The function returns \c true
if successful.
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
bool Resource::open()
+#else
+bool Resource::open(std::optional<QFile::Permissions> permissions)
+#endif
{
if (isOpen())
return false;
-
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
if (!m_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
+#else
+ if (!m_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered, permissions)) {
+#endif
setErrorString(m_file.errorString());
return false;
}
diff --git a/src/libs/installer/binaryformat.h b/src/libs/installer/binaryformat.h
index 3bd8a6aa3..e7505a341 100644
--- a/src/libs/installer/binaryformat.h
+++ b/src/libs/installer/binaryformat.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -58,11 +58,15 @@ public:
Resource(const QString &path, const Range<qint64> &segment);
~Resource();
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
bool open();
- void close();
+#else
+ bool open(std::optional<QFile::Permissions> permissions = std::nullopt);
+#endif
+ void close() override;
- bool seek(qint64 pos);
- qint64 size() const;
+ bool seek(qint64 pos) override;
+ qint64 size() const override;
QByteArray name() const;
void setName(const QByteArray &name);
@@ -74,10 +78,10 @@ public:
static void copyData(Resource *archive, QFileDevice *out);
private:
- qint64 readData(char *data, qint64 maxSize);
- qint64 writeData(const char *data, qint64 maxSize);
+ qint64 readData(char *data, qint64 maxSize) override;
+ qint64 writeData(const char *data, qint64 maxSize) override;
- bool open(OpenMode mode) { return QIODevice::open(mode); }
+ bool open(OpenMode mode) override { return QIODevice::open(mode); }
void setOpenMode(OpenMode mode) { QIODevice::setOpenMode(mode); }
private:
diff --git a/src/libs/installer/binaryformatengine.cpp b/src/libs/installer/binaryformatengine.cpp
index ec6926031..7f00c8d47 100644
--- a/src/libs/installer/binaryformatengine.cpp
+++ b/src/libs/installer/binaryformatengine.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -28,7 +28,7 @@
#include "binaryformatengine.h"
-#include <QRegExp>
+#include <QRegularExpression>
namespace {
@@ -127,9 +127,16 @@ bool BinaryFormatEngine::close()
/*!
\internal
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
bool BinaryFormatEngine::open(QIODevice::OpenMode mode)
+#else
+bool BinaryFormatEngine::open(QIODevice::OpenMode mode, std::optional<QFile::Permissions> permissions)
+#endif
{
Q_UNUSED(mode)
+#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
+ Q_UNUSED(permissions)
+#endif
return m_resource.isNull() ? false : m_resource->open();
}
@@ -263,15 +270,17 @@ QStringList BinaryFormatEngine::entryList(QDir::Filters filters, const QStringLi
if (filterNames.isEmpty())
return result;
- QList<QRegExp> regexps;
- foreach (const QString &i, filterNames)
- regexps.append(QRegExp(i, Qt::CaseInsensitive, QRegExp::Wildcard));
+ QList<QRegularExpression> regexps;
+ for (const QString &i : filterNames) {
+ regexps.append(QRegularExpression(QRegularExpression::wildcardToRegularExpression(i),
+ QRegularExpression::CaseInsensitiveOption));
+ }
QStringList entries;
- foreach (const QString &i, result) {
+ for (const QString &i : qAsConst(result)) {
bool matched = false;
- foreach (const QRegExp &reg, regexps) {
- matched = reg.exactMatch(i);
+ for (const QRegularExpression &reg : qAsConst(regexps)) {
+ matched = reg.match(i).hasMatch();
if (matched)
break;
}
diff --git a/src/libs/installer/binaryformatengine.h b/src/libs/installer/binaryformatengine.h
index 64d0e95f7..9321e9d9c 100644
--- a/src/libs/installer/binaryformatengine.h
+++ b/src/libs/installer/binaryformatengine.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -43,21 +43,26 @@ public:
BinaryFormatEngine(const QHash<QByteArray, ResourceCollection> &collections,
const QString &fileName);
- void setFileName(const QString &file);
+ void setFileName(const QString &file) override;
- bool copy(const QString &newName);
- bool close();
- bool open(QIODevice::OpenMode mode);
- qint64 pos() const;
- qint64 read(char *data, qint64 maxlen);
- bool seek(qint64 offset);
- qint64 size() const;
+ bool copy(const QString &newName) override;
+ bool close() override;
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
+ bool open(QIODevice::OpenMode mode) override;
+#else
+ bool open(QIODevice::OpenMode mode,
+ std::optional<QFile::Permissions> permissions = std::nullopt) override;
+#endif
+ qint64 pos() const override;
+ qint64 read(char *data, qint64 maxlen) override;
+ bool seek(qint64 offset) override;
+ qint64 size() const override;
- QString fileName(FileName file = DefaultName) const;
- FileFlags fileFlags(FileFlags type = FileInfoAll) const;
+ QString fileName(FileName file = DefaultName) const override;
+ FileFlags fileFlags(FileFlags type = FileInfoAll) const override;
- Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
- QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
+ QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
private:
QString m_fileNamePath;
diff --git a/src/libs/installer/calculatorbase.cpp b/src/libs/installer/calculatorbase.cpp
new file mode 100644
index 000000000..4f1732677
--- /dev/null
+++ b/src/libs/installer/calculatorbase.cpp
@@ -0,0 +1,76 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "calculatorbase.h"
+
+#include "component.h"
+
+namespace QInstaller {
+
+CalculatorBase::CalculatorBase(PackageManagerCore *core)
+ : m_core(core)
+{
+}
+
+CalculatorBase::~CalculatorBase()
+{
+}
+
+void CalculatorBase::insertResolution(Component *component, const Resolution resolutionType
+ , const QString &referencedComponent)
+{
+ // Keep the first reason
+ if (m_componentNameResolutionHash.contains(component->name()))
+ return;
+
+ m_componentNameResolutionHash.insert(component->name(),
+ QPair<Resolution, QString>(resolutionType, referencedComponent));
+}
+
+QList<Component *> CalculatorBase::resolvedComponents() const
+{
+ return m_resolvedComponents;
+}
+
+CalculatorBase::Resolution CalculatorBase::resolutionType(Component *component) const
+{
+ return m_componentNameResolutionHash.value(component->name()).first;
+}
+
+QString CalculatorBase::error() const
+{
+ return m_errorString;
+}
+
+QString CalculatorBase::referencedComponent(Component *component) const
+{
+ return m_componentNameResolutionHash.value(component->name()).second;
+}
+
+} // namespace QInstaller
+
diff --git a/src/libs/installer/calculatorbase.h b/src/libs/installer/calculatorbase.h
new file mode 100644
index 000000000..351658f99
--- /dev/null
+++ b/src/libs/installer/calculatorbase.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef CALCULATORBASE_H
+#define CALCULATORBASE_H
+
+#include "installer_global.h"
+
+#include <QList>
+#include <QString>
+#include <QMetaEnum>
+
+namespace QInstaller {
+
+class Component;
+class PackageManagerCore;
+
+class INSTALLER_EXPORT CalculatorBase
+{
+public:
+ enum class Resolution {
+ Selected = 0, // "Selected Component(s) without Dependencies" / "Deselected Component(s)"
+ Replaced, // "Component(s) replaced by other components"
+ VirtualDependent, // "No dependencies to virtual component"
+ Dependent, // "Added as dependency for %1." / "Removed as dependency component is removed"
+ Automatic, // "Component(s) added as automatic dependencies" / "Removed as autodependency component is removed"
+ Resolved, // "Component(s) that have resolved Dependencies"
+ Alias // "Components added from selected alias"
+ };
+
+ CalculatorBase(PackageManagerCore *core);
+ virtual ~CalculatorBase() = 0;
+
+ virtual bool solve(const QList<Component *> &components) = 0;
+ void insertResolution(Component *component, const Resolution resolutionType,
+ const QString &referencedComponent = QString());
+
+ QList<Component *> resolvedComponents() const;
+ virtual QString resolutionText(Component *component) const = 0;
+ Resolution resolutionType(Component *component) const;
+
+ QString error() const;
+
+protected:
+ virtual bool solveComponent(Component *component, const QString &version = QString()) = 0;
+ QString referencedComponent(Component *component) const;
+
+protected:
+ PackageManagerCore *m_core;
+ QString m_errorString;
+
+ QList<Component *> m_resolvedComponents;
+ QHash<QString, QPair<Resolution, QString> > m_componentNameResolutionHash;
+};
+
+} // namespace QInstaller
+
+Q_DECLARE_METATYPE(QInstaller::CalculatorBase::Resolution)
+
+#endif // CALCULATORBASE_H
diff --git a/src/libs/installer/commandlineparser.cpp b/src/libs/installer/commandlineparser.cpp
index 4bfc4ad3a..f9e1f663e 100644
--- a/src/libs/installer/commandlineparser.cpp
+++ b/src/libs/installer/commandlineparser.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -28,6 +28,7 @@
#include "commandlineparser.h"
+#include "commandlineparser_p.h"
#include "constants.h"
#include "globals.h"
@@ -47,7 +48,7 @@ CommandLineParser::CommandLineParser()
"headless mode. The installation operations can be invoked with the following commands and "
"options. Note that the options marked with \"CLI\" are available in the headless mode only.\n")
+ QLatin1String("\nCommands:\n")
- + indent + QString::fromLatin1("%1, %2 - install default or selected packages - <pkg ...>\n")
+ + indent + QString::fromLatin1("%1, %2 - install default or selected packages and aliases - <pkg|alias ...>\n")
.arg(CommandLineOptions::scInstallShort, CommandLineOptions::scInstallLong)
+ indent + QString::fromLatin1("%1, %2 - show available updates information on maintenance tool\n")
.arg(CommandLineOptions::scCheckUpdatesShort, CommandLineOptions::scCheckUpdatesLong)
@@ -55,15 +56,20 @@ CommandLineParser::CommandLineParser()
.arg(CommandLineOptions::scUpdateShort, CommandLineOptions::scUpdateLong)
+ indent + QString::fromLatin1("%1, %2 - uninstall packages and their child components - <pkg ...>\n")
.arg(CommandLineOptions::scRemoveShort, CommandLineOptions::scRemoveLong)
- + indent + QString::fromLatin1("%1, %2 - list currently installed packages - <regexp>\n")
+ + indent + QString::fromLatin1("%1, %2 - list currently installed packages - <regexp for pkg>\n")
.arg(CommandLineOptions::scListShort, CommandLineOptions::scListLong)
- + indent + QString::fromLatin1("%1, %2 - search available packages - <regexp>\n")
+ + indent + QString::fromLatin1("%1, %2 - search available aliases or packages - <regexp for pkg|alias>\n")
.arg(CommandLineOptions::scSearchShort, CommandLineOptions::scSearchLong)
+ indent + indent + QString::fromLatin1("Note: The --%1 option can be used to specify\n")
.arg(CommandLineOptions::scFilterPackagesLong)
+ indent + indent + QLatin1String("additional filters for the search operation\n")
+ + indent + indent + QString::fromLatin1("Note: The --%1 option can be used to specify\n")
+ .arg(CommandLineOptions::scTypeLong)
+ + indent + indent + QLatin1String("the content type to search\n")
+ indent + QString::fromLatin1("%1, %2 - create offline installer from selected packages - <pkg ...>\n")
.arg(CommandLineOptions::scCreateOfflineShort, CommandLineOptions::scCreateOfflineLong)
+ + indent + QString::fromLatin1("%1, %2 - clear contents of the local metadata cache\n")
+ .arg(CommandLineOptions::scClearCacheShort, CommandLineOptions::scClearCacheLong)
+ indent + QString::fromLatin1("%1, %2 - uninstall all packages and remove entire program directory")
.arg(CommandLineOptions::scPurgeShort, CommandLineOptions::scPurgeLong);
@@ -170,6 +176,16 @@ CommandLineParser::CommandLineParser()
"search command. The keys can be any of the possible package information elements, like "
"\"DisplayName\" and \"Description\"."),
QLatin1String("element=regex,...")), CommandLineOnly);
+ addOption(QCommandLineOption(QStringList()
+ << CommandLineOptions::scLocalCachePathShort << CommandLineOptions::scLocalCachePathLong,
+ QLatin1String("Sets the path used for local metadata cache. The path must be writable by the current user."),
+ QLatin1String("path")));
+ addOption(QCommandLineOption(QStringList()
+ << CommandLineOptions::scTypeLong,
+ QLatin1String("[CLI] Sets the type of the given arguments for commands supporting multiple argument types, "
+ "like \"search\". By default aliases are searched first, and if no matching aliases are found, "
+ "then packages are searched with the same search pattern."),
+ QLatin1String("package|alias")));
// Message query options
addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scAcceptMessageQueryShort
@@ -194,7 +210,7 @@ CommandLineParser::CommandLineParser()
QLatin1String("[CLI] Automatically sets the QFileDialog values getExistingDirectory() or getOpenFileName() "
"requested by install script. "
"Several identifier=value pairs can be given separated with comma, "
- "for example --file-query filedialog.id=C:\Temp,filedialog.id2=C:\Temp2"),
+ "for example --file-query filedialog.id=C:/Temp,filedialog.id2=C:/Temp2"),
QLatin1String("identifier=value")), CommandLineOnly);
addOptionWithContext(QCommandLineOption(QStringList() << CommandLineOptions::scConfirmCommandShort
<< CommandLineOptions::scConfirmCommandLong, QLatin1String("[CLI] Confirms starting of "
@@ -219,19 +235,36 @@ CommandLineParser::CommandLineParser()
QLatin1String("socketname, key")));
addOption(QCommandLineOption(QStringList()
<< CommandLineOptions::scSquishPortShort << CommandLineOptions::scSquishPortLong,
- QLatin1String("Give a port where Squish can connect to. If no port is given, default port 11233 is "
- "used. Note: To enable Squish support you first need to build IFW with SQUISH_PATH "
+ QLatin1String("Give a port where Squish can connect to. If no port is given, attach to squish "
+ "not done. Note: To enable Squish support you first need to build IFW with SQUISH_PATH "
"parameter where SQUISH_PATH is pointing to your Squish installation folder: "
"<path_to_qt>/bin/qmake -r SQUISH_PATH=<pat_to_squish>"),
QLatin1String("port number")));
+ addOption(QCommandLineOption(QStringList()
+ << CommandLineOptions::scMaxConcurrentOperationsShort << CommandLineOptions::scMaxConcurrentOperationsLong,
+ QLatin1String("Specifies the maximum number of threads used to perform concurrent operations "
+ "in the unpacking phase of components. Set to a positive number, or 0 (default) "
+ "to let the application determine the ideal thread count from the amount of logical "
+ "processor cores in the system."),
+ QLatin1String("threads")));
+
+ QCommandLineOption cleanupUpdate(CommandLineOptions::scCleanupUpdate);
+ cleanupUpdate.setValueName(QLatin1String("path"));
+ cleanupUpdate.setFlags(QCommandLineOption::HiddenFromHelp);
+ addOption(cleanupUpdate);
+
+ QCommandLineOption cleanupUpdateOnly(CommandLineOptions::scCleanupUpdateOnly);
+ cleanupUpdateOnly.setValueName(QLatin1String("path"));
+ cleanupUpdateOnly.setFlags(QCommandLineOption::HiddenFromHelp);
+ addOption(cleanupUpdateOnly);
// Deprecated options
QCommandLineOption deprecatedUpdater(CommandLineOptions::scDeprecatedUpdater);
- deprecatedUpdater.setHidden(true);
+ deprecatedUpdater.setFlags(QCommandLineOption::HiddenFromHelp);
addOption(deprecatedUpdater);
QCommandLineOption deprecatedCheckUpdates(CommandLineOptions::scDeprecatedCheckUpdates);
- deprecatedCheckUpdates.setHidden(true);
+ deprecatedCheckUpdates.setFlags(QCommandLineOption::HiddenFromHelp);
addOption(deprecatedCheckUpdates); // Behaves like check-updates but does not default to verbose output
// Custom extension options
@@ -269,3 +302,42 @@ CommandLineParser::OptionContextFlags CommandLineParser::optionContextFlags(cons
{
return m_optionContextFlagsNameHash.value(option);
}
+
+/*
+ Returns the command line arguments of the application. The returned list
+ is context-aware, i.e. options that are set on the parser with
+ \c OptionContextFlag::NoEchoValue are returned with their value hidden.
+*/
+QStringList CommandLineParser::arguments() const
+{
+ const QStringList arguments = QCoreApplication::arguments();
+ QStringList returnArguments;
+ bool skipNext = false;
+ for (const QString &arg : arguments) {
+ if (skipNext) {
+ skipNext = false;
+ continue;
+ }
+ returnArguments << arg;
+ // Append positional arguments as-is
+ if (!arg.startsWith(QLatin1String("--")) && !arg.startsWith(QLatin1Char('-')))
+ continue;
+
+ QString normalizedOption = arg;
+ while (normalizedOption.startsWith(QLatin1Char('-')))
+ normalizedOption.remove(QLatin1Char('-'));
+
+ const OptionContextFlags flags = optionContextFlags(normalizedOption);
+ if (!flags.testFlag(OptionContextFlag::NoEchoValue))
+ continue;
+
+ QString nextArg = arguments.value(arguments.indexOf(arg) + 1);
+ if (!nextArg.isEmpty() && !nextArg.startsWith(QLatin1String("--"))
+ && !nextArg.startsWith(QLatin1Char('-'))) {
+ nextArg = QLatin1String("******");
+ returnArguments << nextArg;
+ skipNext = true;
+ }
+ }
+ return returnArguments;
+}
diff --git a/src/libs/installer/commandlineparser.h b/src/libs/installer/commandlineparser.h
index 8f112fcb9..3c14d9f45 100644
--- a/src/libs/installer/commandlineparser.h
+++ b/src/libs/installer/commandlineparser.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,15 +29,16 @@
#ifndef COMMANDLINEPARSER_H
#define COMMANDLINEPARSER_H
-#include "commandlineparser_p.h"
-
#include <QCommandLineParser>
+class CommandLineParserPrivate;
+
class CommandLineParser
{
public:
enum OptionContextFlag {
- CommandLineOnly = 0x1
+ CommandLineOnly = 0x1,
+ NoEchoValue = 0x2
};
Q_DECLARE_FLAGS(OptionContextFlags, OptionContextFlag)
@@ -48,7 +49,7 @@ public:
bool addOptionWithContext(const QCommandLineOption &option, OptionContextFlags flags);
QString helpText() const { return m_parser.helpText(); }
- bool isSet(const QString &option) { return m_parser.isSet(option); }
+ bool isSet(const QString &option) const { return m_parser.isSet(option); }
QStringList unknownOptionNames() const { return m_parser.unknownOptionNames(); }
QStringList positionalArguments() const { return m_parser.positionalArguments(); }
bool parse(const QStringList &argumens) { return m_parser.parse(argumens); }
@@ -56,12 +57,15 @@ public:
QStringList optionNames() const { return m_parser.optionNames(); }
OptionContextFlags optionContextFlags(const QString &option) const;
+ QStringList arguments() const;
private:
QCommandLineParser m_parser;
- class CommandLineParserPrivate *const d;
+ CommandLineParserPrivate *const d;
QHash<QString, OptionContextFlags> m_optionContextFlagsNameHash;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(CommandLineParser::OptionContextFlags)
+
#endif // COMMANDLINEPARSER_H
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 1a83291c1..ce76a2927 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -37,17 +37,21 @@
#include "remoteclient.h"
#include "settings.h"
#include "utils.h"
+#include "constants.h"
#include "updateoperationfactory.h"
#include <productkeycheck.h>
#include <QtCore/QDirIterator>
-#include <QtCore/QRegExp>
#include <QtCore/QTranslator>
#include <QtCore/QRegularExpression>
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+#include <QtCore/QTextCodec>
+#endif
#include <QApplication>
+#include <QtConcurrentFilter>
#include <QtUiTools/QUiLoader>
@@ -60,20 +64,14 @@
#include <private/qv4object_p.h>
#include <algorithm>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
+#include <QJSEngine>
+#else
+#include <QQmlEngine>
+#endif
using namespace QInstaller;
-static const QLatin1String scScriptTag("Script");
-static const QLatin1String scVirtual("Virtual");
-static const QLatin1String scInstalled("Installed");
-static const QLatin1String scUpdateText("UpdateText");
-static const QLatin1String scUninstalled("Uninstalled");
-static const QLatin1String scCurrentState("CurrentState");
-static const QLatin1String scForcedInstallation("ForcedInstallation");
-static const QLatin1String scCheckable("Checkable");
-static const QLatin1String scExpandedByDefault("ExpandedByDefault");
-static const QLatin1String scUnstable("Unstable");
-
/*!
\enum QInstaller::Component::UnstableError
@@ -87,6 +85,10 @@ static const QLatin1String scUnstable("Unstable");
Component script has errors or loading fails.
\value MissingDependency
Component has dependencies to missing components.
+ \value InvalidTreeName
+ Component has an invalid tree name.
+ \value DescendantOfUnstable
+ Component is descendant of an unstable component.
*/
/*!
@@ -248,8 +250,13 @@ static const QLatin1String scUnstable("Unstable");
*/
Component::Component(PackageManagerCore *core)
: d(new ComponentPrivate(core, this))
- , m_defaultArchivePath(QLatin1String("@TargetDir@"))
+ , m_defaultArchivePath(scTargetDirPlaceholder)
{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
+ QJSEngine::setObjectOwnership(this, QJSEngine::CppOwnership);
+#else
+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
+#endif
setPrivate(d);
connect(this, &Component::valueChanged, this, &Component::updateModelData);
@@ -285,16 +292,16 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package)
{
setValue(scName, package.name);
setValue(scDisplayName, package.title);
- setValue(scTreeName, package.treeName);
setValue(scDescription, package.description);
setValue(scVersion, package.version);
setValue(scInheritVersion, package.inheritVersionFrom);
setValue(scInstalledVersion, package.version);
- setValue(QLatin1String("LastUpdateDate"), package.lastUpdateDate.toString());
- setValue(QLatin1String("InstallDate"), package.installDate.toString());
+ setValue(scLastUpdateDate, package.lastUpdateDate.toString());
+ setValue(scInstallDate, package.installDate.toString());
setValue(scUncompressedSize, QString::number(package.uncompressedSize));
- setValue(scDependencies, package.dependencies.join(QLatin1String(",")));
- setValue(scAutoDependOn, package.autoDependencies.join(QLatin1String(",")));
+ setValue(scDependencies, package.dependencies.join(scCommaWithSpace));
+ setValue(scAutoDependOn, package.autoDependencies.join(scCommaWithSpace));
+ setValue(scSortingPriority, QString::number(package.sortingPriority));
setValue(scForcedInstallation, package.forcedInstallation ? scTrue : scFalse);
setValue(scVirtual, package.virtualComp ? scTrue : scFalse);
@@ -302,6 +309,13 @@ void Component::loadDataFromPackage(const KDUpdater::LocalPackage &package)
setValue(scCheckable, package.checkable ? scTrue : scFalse);
setValue(scExpandedByDefault, package.expandedByDefault ? scTrue : scFalse);
setValue(scContentSha1, package.contentSha1);
+
+ setValue(scTreeName, package.treeName.first);
+ d->m_treeNameMoveChildren = package.treeName.second;
+
+ // scDependencies might be updated from repository later,
+ // keep the local dependencies as well.
+ setValue(scLocalDependencies, value(scDependencies));
}
/*!
@@ -316,7 +330,6 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scName, package.data(scName).toString());
setValue(scDisplayName, package.data(scDisplayName).toString());
- setValue(scTreeName, package.data(scTreeName).toString());
setValue(scDescription, package.data(scDescription).toString());
setValue(scDefault, package.data(scDefault).toString());
setValue(scAutoDependOn, package.data(scAutoDependOn).toString());
@@ -334,8 +347,7 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scUpdateText, package.data(scUpdateText).toString());
setValue(scNewComponent, package.data(scNewComponent).toString());
setValue(scRequiresAdminRights, package.data(scRequiresAdminRights).toString());
-
- setValue(scScriptTag, package.data(scScriptTag).toString());
+ d->m_scriptHash = package.data(scScriptTag).toHash();
setValue(scReplaces, package.data(scReplaces).toString());
setValue(scReleaseDate, package.data(scReleaseDate).toString());
setValue(scCheckable, package.data(scCheckable).toString());
@@ -346,25 +358,30 @@ void Component::loadDataFromPackage(const Package &package)
forced = scFalse;
setValue(scForcedInstallation, forced);
setValue(scContentSha1, package.data(scContentSha1).toString());
+ setValue(scCheckSha1CheckSum, package.data(scCheckSha1CheckSum, scTrue).toString().toLower());
+
+ const auto treeNamePair = package.data(scTreeName).value<QPair<QString, bool>>();
+ setValue(scTreeName, treeNamePair.first);
+ d->m_treeNameMoveChildren = treeNamePair.second;
if (d->m_core->isPackageViewer())
return;
setLocalTempPath(QInstaller::pathFromUrl(package.packageSource().url));
- const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
- if (!uis.isEmpty())
- loadUserInterfaces(QDir(QString::fromLatin1("%1/%2").arg(localTempPath(), name())), uis);
+
+ const QStringList uiList = QInstaller::splitStringWithComma(package.data(scUserInterfaces).toString());
+ if (!uiList.isEmpty())
+ loadUserInterfaces(QDir(scTwoArgs.arg(localTempPath(), name())), uiList);
+
#ifndef IFW_DISABLE_TRANSLATIONS
- const QStringList qms = package.data(QLatin1String("Translations")).toString()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ const QStringList qms = QInstaller::splitStringWithComma(package.data(scTranslations).toString());
if (!qms.isEmpty())
- loadTranslations(QDir(QString::fromLatin1("%1/%2").arg(localTempPath(), name())), qms);
+ loadTranslations(QDir(scTwoArgs.arg(localTempPath(), name())), qms);
#endif
- QHash<QString, QVariant> licenseHash = package.data(QLatin1String("Licenses")).toHash();
+ QHash<QString, QVariant> licenseHash = package.data(scLicenses).toHash();
if (!licenseHash.isEmpty())
- loadLicenses(QString::fromLatin1("%1/%2/").arg(localTempPath(), name()), licenseHash);
- QVariant operationsVariant = package.data(QLatin1String("Operations"));
+ loadLicenses(scTwoArgs.arg(localTempPath(), name()), licenseHash);
+ QVariant operationsVariant = package.data(scOperations);
if (operationsVariant.canConvert<QList<QPair<QString, QVariant>>>())
m_operationsList = operationsVariant.value<QList<QPair<QString, QVariant>>>();
}
@@ -425,6 +442,16 @@ QString Component::value(const QString &key, const QString &defaultValue) const
}
/*!
+ Removes all the values that have the \a key from the variables set for this component.
+ Returns the number of values removed which is 1 if the key exists in the variables,
+ and 0 otherwise.
+*/
+int Component::removeValue(const QString &key)
+{
+ return d->m_vars.remove(key);
+}
+
+/*!
Sets the value of the variable with \a key to \a value.
\sa {component::setValue}{component.setValue}
@@ -440,16 +467,22 @@ void Component::setValue(const QString &key, const QString &value)
if (key == scName)
d->m_componentName = normalizedValue;
- if (key == scCheckable)
- this->setCheckable(normalizedValue.toLower() == scTrue);
+ if (key == scCheckable) // Non-checkable components can still be toggled in updater
+ this->setCheckable(normalizedValue.toLower() == scTrue || d->m_core->isUpdater());
if (key == scExpandedByDefault)
this->setExpandedByDefault(normalizedValue.toLower() == scTrue);
if (key == scForcedInstallation) {
- if (value == scTrue && !PackageManagerCore::noForceInstallation()) {
+ if (value == scTrue && !d->m_core->isUpdater() && !PackageManagerCore::noForceInstallation()) {
+ // Forced installation components can still be toggled in updater or when
+ // core is set to ignore forced installations.
setCheckable(false);
setCheckState(Qt::Checked);
}
}
+ if (key == scAutoDependOn)
+ packageManagerCore()->createAutoDependencyHash(name(), d->m_vars[key], normalizedValue);
+ if (key == scLocalDependencies)
+ packageManagerCore()->createLocalDependencyHash(name(), normalizedValue);
d->m_vars[key] = normalizedValue;
emit valueChanged(key, normalizedValue);
@@ -553,53 +586,60 @@ QString Component::displayName() const
*/
QString Component::treeName() const
{
- return d->m_vars.value(scTreeName, name());
+ const QString defaultValue = d->m_vars.value(scAutoTreeName, name());
+ return d->m_vars.value(scTreeName, defaultValue);
}
/*!
- Loads the component script into the script engine.
+ Returns \c true if descendants of this component should have automatically
+ created tree names in relation to the parent component's modified location,
+ \c false otherwise.
*/
-void Component::loadComponentScript()
+bool Component::treeNameMoveChildren() const
{
- const QString script = d->m_vars.value(scScriptTag);
- if (!localTempPath().isEmpty() && !script.isEmpty())
- loadComponentScript(QString::fromLatin1("%1/%2/%3").arg(localTempPath(), name(), script));
+ return d->m_treeNameMoveChildren;
}
/*!
- Loads the script at \a fileName into the script engine. The installer and all its
- components as well as other useful things are being exported into the script.
- For more information, see \l{Component Scripting}.
+ Loads the component script into the script engine. Call this method with
+ \a postLoad \c true to a list of components that are updated or installed
+ to improve performance if the amount of components is huge and there are no script
+ functions that need to be called before the installation starts.
+*/
+void Component::loadComponentScript(const bool postLoad)
+{
+ const QString installScript(!postLoad ? d->m_scriptHash.value(scInstallScript).toString()
+ : d->m_scriptHash.value(scPostLoadScript).toString());
+
+ if (!localTempPath().isEmpty() && !installScript.isEmpty()) {
+ evaluateComponentScript(scThreeArgs.arg(localTempPath(), name()
+ , installScript), postLoad);
+ }
+}
- Throws an error when either the script at \a fileName could not be opened, or QScriptEngine
- could not evaluate the script.
+/*!
+ \internal
*/
-void Component::loadComponentScript(const QString &fileName)
+void Component::evaluateComponentScript(const QString &fileName, const bool postScriptContent)
{
// introduce the component object as javascript value and call the name to check that it
// was successful
try {
- d->m_scriptContext = d->scriptEngine()->loadInContext(QLatin1String("Component"), fileName,
- QString::fromLatin1("var component = installer.componentByName('%1'); component.name;")
- .arg(name()));
- if (packageManagerCore()->settings().allowUnstableComponents()) {
- // Check if component has dependency to a broken component. Dependencies to broken
- // components are checked if error is thrown but if dependency to a broken
- // component is added in script, the script might not be loaded yet
- foreach (QString dependency, dependencies()) {
- Component *dependencyComponent = packageManagerCore()->componentByName
- (PackageManagerCore::checkableName(dependency));
- if (dependencyComponent && dependencyComponent->isUnstable())
- setUnstable(Component::UnstableError::DepencyToUnstable, QLatin1String("Dependent on unstable component"));
- }
+ if (postScriptContent) {
+ d->m_postScriptContext = d->scriptEngine()->loadInContext(scComponent, fileName,
+ scComponentScriptTest.arg(name()));
+ } else {
+ d->m_scriptContext = d->scriptEngine()->loadInContext(scComponent, fileName,
+ scComponentScriptTest.arg(name()));
}
} catch (const Error &error) {
- if (packageManagerCore()->settings().allowUnstableComponents()) {
- setUnstable(Component::UnstableError::ScriptLoadingFailed, error.message());
- qCWarning(QInstaller::lcDeveloperBuild) << error.message();
- } else {
+ qCWarning(QInstaller::lcDeveloperBuild) << error.message();
+ setUnstable(Component::UnstableError::ScriptLoadingFailed, error.message());
+ // evaluateComponentScript is called with postScriptContent after we have selected components
+ // and are about to install. Do not allow install if unstable components are allowed
+ // as we then end up installing a component which has invalid script.
+ if (!packageManagerCore()->settings().allowUnstableComponents() || postScriptContent)
throw error;
- }
}
emit loaded();
@@ -613,7 +653,7 @@ void Component::loadComponentScript(const QString &fileName)
*/
void Component::languageChanged()
{
- d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("retranslateUi"));
+ callScriptMethod(scRetranslateUi);
}
/*!
@@ -625,7 +665,7 @@ void Component::loadTranslations(const QDir &directory, const QStringList &qms)
{
QDirIterator it(directory.path(), qms, QDir::Files);
const QStringList translations = d->m_core->settings().translations();
- const QString uiLanguage = QLocale().uiLanguages().value(0, QLatin1String("en"));
+ const QString uiLanguage = QLocale().uiLanguages().value(0, scEn);
while (it.hasNext()) {
const QString filename = it.next();
const QString basename = QFileInfo(filename).baseName();
@@ -633,18 +673,18 @@ void Component::loadTranslations(const QDir &directory, const QStringList &qms)
if (!translations.isEmpty()) {
bool found = false;
foreach (const QString &translation, translations)
- found |= translation.startsWith(QLatin1String("ifw_") + basename, Qt::CaseInsensitive);
+ found |= translation.startsWith(scIfw_ + basename, Qt::CaseInsensitive);
if (!found) // don't load the file if it does match the UI language but is not allowed to be used
continue;
} else if (!uiLanguage.startsWith(QFileInfo(filename).baseName(), Qt::CaseInsensitive)) {
continue; // do not load the file if it does not match the UI language
}
- QScopedPointer<QTranslator> translator(new QTranslator(this));
+ std::unique_ptr<QTranslator> translator(new QTranslator(this));
if (translator->load(filename)) {
// Do not throw if translator returns false as it may just be an intentionally
// empty file. See also QTBUG-31031
- qApp->installTranslator(translator.take());
+ qApp->installTranslator(translator.release());
}
}
}
@@ -662,17 +702,17 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
while (it.hasNext()) {
QFile file(it.next());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Cannot open the requested UI file \"%1\": %2").arg(
- it.fileName(), file.errorString()));
+ throw Error(tr("Cannot open the requested UI file \"%1\": %2.\n\n%3 \"%4\"").arg(
+ it.fileName(), file.errorString(), tr(scClearCacheHint), packageManagerCore()->settings().localCachePath()));
}
- static QUiLoader loader;
- loader.setTranslationEnabled(true);
- loader.setLanguageChangeEnabled(true);
- QWidget *const widget = loader.load(&file, 0);
+ QUiLoader *const loader = ProductKeyCheck::instance()->uiLoader();
+ loader->setTranslationEnabled(true);
+ loader->setLanguageChangeEnabled(true);
+ QWidget *const widget = loader->load(&file, 0);
if (!widget) {
- throw Error(tr("Cannot load the requested UI file \"%1\": %2").arg(
- it.fileName(), loader.errorString()));
+ throw Error(tr("Cannot load the requested UI file \"%1\": %2.\n\n%3 \"%4\"").arg(
+ it.fileName(), loader->errorString(), tr(scClearCacheHint), packageManagerCore()->settings().localCachePath()));
}
d->scriptEngine()->newQObject(widget);
d->m_userInterfaces.insert(widget->objectName(), widget);
@@ -688,7 +728,7 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
QHash<QString, QVariant>::const_iterator it;
for (it = licenseHash.begin(); it != licenseHash.end(); ++it) {
QVariantMap license = it.value().toMap();
- const QString &fileName = license.value(QLatin1String("file")).toString();
+ const QString &fileName = license.value(scFile).toString();
if (!ProductKeyCheck::instance()->isValidLicenseTextFile(fileName))
continue;
@@ -699,8 +739,8 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
break;
QList<QFileInfo> fileCandidates;
- foreach (const QString &locale, QInstaller::localeCandidates(lang.toLower())) {
- fileCandidates << QFileInfo(QString::fromLatin1("%1%2_%3.%4").arg(
+ foreach (const QString &locale, QInstaller::localeCandidates(lang)) {
+ fileCandidates << QFileInfo(scLocalesArgs.arg(
directory, fileInfo.baseName(), locale,
fileInfo.completeSuffix()));
}
@@ -717,12 +757,14 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
QFile file(fileInfo.filePath());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Cannot open the requested license file \"%1\": %2").arg(
- file.fileName(), file.errorString()));
+ throw Error(tr("Cannot open the requested license file \"%1\": %2.\n\n%3 \"%4\"").arg(
+ file.fileName(), file.errorString(), tr(scClearCacheHint), packageManagerCore()->settings().localCachePath()));
}
QTextStream stream(&file);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
stream.setCodec("UTF-8");
- license.insert(QLatin1String("content"), stream.readAll());
+#endif
+ license.insert(scContent, stream.readAll());
d->m_licenses.insert(it.key(), license);
}
}
@@ -733,8 +775,8 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
*/
void Component::loadXMLOperations()
{
- for (auto operation: m_operationsList) {
- if (operation.first != QLatin1String("Extract"))
+ for (auto operation: qAsConst(m_operationsList)) {
+ if (operation.first != scExtract)
addOperation(operation.first, operation.second.toStringList());
}
}
@@ -745,14 +787,14 @@ void Component::loadXMLOperations()
*/
void Component::loadXMLExtractOperations()
{
- for (auto operation: m_operationsList) {
- if (operation.first == QLatin1String("Extract")) {
+ for (auto &operation: qAsConst(m_operationsList)) {
+ if (operation.first == scExtract) {
// Create hash for Extract operations. Operation has a mandatory extract folder as
// first argument and optional archive name as second argument.
const QStringList &operationArgs = operation.second.toStringList();
if (operationArgs.count() == 2) {
const QString archiveName = value(scVersion) + operationArgs.at(1);
- const QString archivePath = QString::fromLatin1("installer://%1/%2").arg(name()).arg(archiveName);
+ const QString archivePath = scInstallerPrefixWithTwoArgs.arg(name()).arg(archiveName);
m_archivesHash.insert(archivePath, operationArgs.at(0));
} else if (operationArgs.count() == 1) {
m_defaultArchivePath = operationArgs.at(0);
@@ -810,25 +852,23 @@ void Component::createOperationsForPath(const QString &path)
const QFileInfo fi(path);
// don't copy over a checksum file
- if (fi.suffix() == QLatin1String("sha1") && QFileInfo(fi.dir(), fi.completeBaseName()).exists())
+ if (fi.suffix() == scSha1 && QFileInfo(fi.dir(), fi.completeBaseName()).exists())
return;
// the script can override this method
- if (!d->scriptEngine()->callScriptMethod(d->m_scriptContext,
- QLatin1String("createOperationsForPath"), QJSValueList() << path).isUndefined()) {
- return;
- }
+ if (!callScriptMethod(scCreateOperationsForPath, QJSValueList() << path).isUndefined())
+ return;
QString target;
- static const QString prefix = QString::fromLatin1("installer://");
- target = QString::fromLatin1("@TargetDir@%1").arg(path.mid(prefix.length() + name().length()));
+ static const QString prefix = scInstallerPrefix;
+ target = scTargetDirPlaceholderWithArg.arg(path.mid(prefix.length() + name().length()));
if (fi.isFile()) {
- static const QString copy = QString::fromLatin1("Copy");
+ static const QString copy = scCopy;
addOperation(copy, QStringList() << fi.filePath() << target);
} else if (fi.isDir()) {
qApp->processEvents();
- static const QString mkdir = QString::fromLatin1("Mkdir");
+ static const QString mkdir = scMkdir;
addOperation(mkdir, QStringList(target));
QDirIterator it(fi.filePath());
@@ -856,14 +896,12 @@ void Component::createOperationsForArchive(const QString &archive)
const QFileInfo fi(archive);
// don't do anything with sha1 files
- if (fi.suffix() == QLatin1String("sha1") && QFileInfo(fi.dir(), fi.completeBaseName()).exists())
+ if (fi.suffix() == scSha1 && QFileInfo(fi.dir(), fi.completeBaseName()).exists())
return;
// the script can override this method
- if (!d->scriptEngine()->callScriptMethod(d->m_scriptContext,
- QLatin1String("createOperationsForArchive"), QJSValueList() << archive).isUndefined()) {
- return;
- }
+ if (!callScriptMethod(scCreateOperationsForArchive, QJSValueList() << archive).isUndefined())
+ return;
QScopedPointer<AbstractArchive> archiveFile(ArchiveFactory::instance().create(archive));
const bool isZip = (archiveFile && archiveFile->open(QIODevice::ReadOnly) && archiveFile->isSupported());
@@ -871,9 +909,9 @@ void Component::createOperationsForArchive(const QString &archive)
if (isZip) {
// component.xml can override this value
if (m_archivesHash.contains(archive))
- addOperation(QLatin1String("Extract"), QStringList() << archive << m_archivesHash.value(archive));
+ addOperation(scExtract, QStringList() << archive << m_archivesHash.value(archive));
else
- addOperation(QLatin1String("Extract"), QStringList() << archive << m_defaultArchivePath);
+ addOperation(scExtract, QStringList() << archive << m_defaultArchivePath);
} else {
createOperationsForPath(archive);
}
@@ -885,7 +923,7 @@ void Component::createOperationsForArchive(const QString &archive)
void Component::beginInstallation()
{
// the script can override this method
- d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("beginInstallation"));
+ callScriptMethod(scBeginInstallation);
}
/*!
@@ -895,10 +933,9 @@ void Component::beginInstallation()
void Component::createOperations()
{
// the script can override this method
- if (!d->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("createOperations"))
- .isUndefined()) {
- d->m_operationsCreated = true;
- return;
+ if (!callScriptMethod(scCreateOperations).isUndefined()) {
+ d->m_operationsCreated = true;
+ return;
}
loadXMLExtractOperations();
foreach (const QString &archive, archives())
@@ -935,10 +972,17 @@ QList<QPair<QString, bool> > Component::pathsForUninstallation() const
*/
QStringList Component::archives() const
{
- QString pathString = QString::fromLatin1("installer://%1/").arg(name());
+ static const QRegularExpression regExp(scCaretSymbol);
+ QString pathString = scInstallerPrefixWithOneArgs.arg(name());
QStringList archivesNameList = QDir(pathString).entryList();
+
+ // In resources we may have older version of archives, this can happen
+ // when there is offline installer with same component with lower version
+ // number and newer version is available online
+ archivesNameList = archivesNameList.filter(value(scVersion));
+
//RegExp "^" means line beginning
- archivesNameList.replaceInStrings(QRegExp(QLatin1String("^")), pathString);
+ archivesNameList.replaceInStrings(regExp, pathString);
return archivesNameList;
}
@@ -958,6 +1002,15 @@ void Component::addDownloadableArchive(const QString &path)
}
/*!
+ \internal
+*/
+void Component::addDownloadableArchives(const QString& archives)
+{
+ Q_ASSERT(isFromOnlineRepository());
+ d->m_downloadableArchivesVariable = archives;
+}
+
+/*!
Removes the archive \a path previously added via addDownloadableArchive() from this component.
This can only be called if this component was downloaded from an online repository.
@@ -972,9 +1025,15 @@ void Component::removeDownloadableArchive(const QString &path)
/*!
Returns the archives to be downloaded from the online repository before installation.
+ Should be called only once when the installation starts.
*/
-QStringList Component::downloadableArchives() const
+QStringList Component::downloadableArchives()
{
+ const QStringList downloadableArchives = d->m_downloadableArchivesVariable
+ .split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+ foreach (const QString downloadableArchive, downloadableArchives)
+ addDownloadableArchive(downloadableArchive);
+
return d->m_downloadableArchives;
}
@@ -1025,35 +1084,43 @@ QStringList Component::stopProcessForUpdateRequests() const
/*!
Returns the operations needed to install this component. If autoCreateOperations() is \c true,
createOperations() is called if no operations have been automatically created yet.
+
+ The \a mask parameter filters the returned operations by their group.
*/
-OperationList Component::operations() const
+OperationList Component::operations(const Operation::OperationGroups &mask) const
{
if (d->m_autoCreateOperations && !d->m_operationsCreated) {
const_cast<Component*>(this)->createOperations();
if (!d->m_minimumProgressOperation) {
d->m_minimumProgressOperation = KDUpdater::UpdateOperationFactory::instance()
- .create(QLatin1String("MinimumProgress"), d->m_core);
- d->m_minimumProgressOperation->setValue(QLatin1String("component"), name());
+ .create(scMinimumProgress, d->m_core);
+ d->m_minimumProgressOperation->setValue(scComponentSmall, name());
d->m_operations.append(d->m_minimumProgressOperation);
}
if (!d->m_licenses.isEmpty()) {
d->m_licenseOperation = KDUpdater::UpdateOperationFactory::instance()
- .create(QLatin1String("License"), d->m_core);
- d->m_licenseOperation->setValue(QLatin1String("component"), name());
+ .create(scLicense, d->m_core);
+ d->m_licenseOperation->setValue(scComponentSmall, name());
QVariantMap licenses;
const QList<QVariantMap> values = d->m_licenses.values();
for (int i = 0; i < values.count(); ++i) {
- licenses.insert(values.at(i).value(QLatin1String("file")).toString(),
- values.at(i).value(QLatin1String("content")));
+ licenses.insert(values.at(i).value(scFile).toString(),
+ values.at(i).value(scContent));
}
- d->m_licenseOperation->setValue(QLatin1String("licenses"), licenses);
+ d->m_licenseOperation->setValue(scLicensesValue, licenses);
d->m_operations.append(d->m_licenseOperation);
}
}
- return d->m_operations;
+ OperationList operations;
+ std::copy_if(d->m_operations.begin(), d->m_operations.end(), std::back_inserter(operations),
+ [&](const Operation *op) {
+ return mask.testFlag(op->group());
+ }
+ );
+ return operations;
}
/*!
@@ -1063,7 +1130,7 @@ void Component::addOperation(Operation *operation)
{
d->m_operations.append(operation);
if (RemoteClient::instance().isActive())
- operation->setValue(QLatin1String("admin"), true);
+ operation->setValue(scAdmin, true);
}
/*!
@@ -1073,7 +1140,7 @@ void Component::addOperation(Operation *operation)
void Component::addElevatedOperation(Operation *operation)
{
addOperation(operation);
- operation->setValue(QLatin1String("admin"), true);
+ operation->setValue(scAdmin, true);
}
/*!
@@ -1128,9 +1195,6 @@ Operation *Component::createOperation(const QString &operationName, const QStrin
return operation;
}
- if (operation->name() == QLatin1String("Delete"))
- operation->setValue(QLatin1String("performUndo"), false);
-
// Operation can contain variables which are resolved when performing the operation
if (operation->requiresUnreplacedVariables())
operation->setArguments(parameters);
@@ -1138,11 +1202,11 @@ Operation *Component::createOperation(const QString &operationName, const QStrin
operation->setArguments(d->m_core->replaceVariables(parameters));
- operation->setValue(QLatin1String("component"), name());
+ operation->setValue(scComponentSmall, name());
return operation;
}
-void Component::markComponentUnstable()
+void Component::markComponentUnstable(Component::UnstableError error, const QString &errorMessage)
{
setValue(scDefault, scFalse);
// Mark unstable component unchecked if:
@@ -1155,6 +1219,23 @@ void Component::markComponentUnstable()
if (d->m_core->isInstaller() || !isInstalled() || d->m_core->isUpdater())
setCheckState(Qt::Unchecked);
setValue(scUnstable, scTrue);
+ QMetaEnum metaEnum = QMetaEnum::fromType<Component::UnstableError>();
+ emit packageManagerCore()->unstableComponentFound(QLatin1String(metaEnum.valueToKey(error)), errorMessage, this->name());
+
+ // Update the description and tooltip texts to contain
+ // information about the unstable error.
+ updateModelData(scDescription, QString());
+}
+
+QJSValue Component::callScriptMethod(const QString &methodName, const QJSValueList &arguments) const
+{
+ QJSValue scriptContext;
+ if (!d->m_postScriptContext.isUndefined() && d->m_postScriptContext.property(methodName).isCallable())
+ scriptContext = d->m_postScriptContext;
+ else
+ scriptContext = d->m_scriptContext;
+ return d->scriptEngine()->callScriptMethod(scriptContext,
+ methodName, arguments);
}
namespace {
@@ -1176,7 +1257,7 @@ inline bool convert(QQmlV4Function *func, QStringList *toArgs)
QV4::Object *array = val->as<QV4::Object>();
uint length = array->getLength();
for (uint ii = 0; ii < length; ++ii) {
- valtmp = array->getIndexed(ii);
+ valtmp = array->get(ii);
*toArgs << valtmp->toQStringNoThrow();
}
} else {
@@ -1291,6 +1372,15 @@ bool Component::forcedInstallation() const
}
/*!
+ Returns whether this component is essential. Essential components
+ are always installed, and updated before other components.
+*/
+bool Component::isEssential() const
+{
+ return d->m_vars.value(scEssential, scFalse).toLower() == scTrue;
+}
+
+/*!
Sets the validator callback name to \a name.
*/
void Component::setValidatorCallbackName(const QString &name)
@@ -1305,7 +1395,7 @@ void Component::setValidatorCallbackName(const QString &name)
bool Component::validatePage()
{
if (!validatorCallbackName.isEmpty())
- return d->scriptEngine()->callScriptMethod(d->m_scriptContext, validatorCallbackName).toBool();
+ return callScriptMethod(validatorCallbackName).toBool();
return true;
}
@@ -1324,12 +1414,23 @@ void Component::addDependency(const QString &newDependency)
if (oldDependencies.isEmpty())
setValue(scDependencies, newDependency);
else
- setValue(scDependencies, oldDependencies + QLatin1String(", ") + newDependency);
+ setValue(scDependencies, oldDependencies + scCommaWithSpace + newDependency);
}
+/*!
+ Returns a list of dependencies defined in the the repository or in the package.xml.
+*/
QStringList Component::dependencies() const
{
- return d->m_vars.value(scDependencies).split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ return QInstaller::splitStringWithComma(d->m_vars.value(scDependencies));
+}
+
+/*!
+ Returns a list of installed components dependencies defined in the components.xml.
+*/
+QStringList Component::localDependencies() const
+{
+ return QInstaller::splitStringWithComma(d->m_vars.value(scLocalDependencies));
}
/*!
@@ -1347,12 +1448,30 @@ void Component::addAutoDependOn(const QString &newDependOn)
if (oldDependOn.isEmpty())
setValue(scAutoDependOn, newDependOn);
else
- setValue(scAutoDependOn, oldDependOn + QLatin1String(", ") + newDependOn);
+ setValue(scAutoDependOn, oldDependOn + scCommaWithSpace + newDependOn);
}
QStringList Component::autoDependencies() const
{
- return d->m_vars.value(scAutoDependOn).split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ return d->m_vars.value(scAutoDependOn).split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+}
+
+/*!
+ Returns a list of dependencies that the component currently has. The
+ dependencies can vary when component is already installed with different
+ dependency list than what is introduced in the repository. If component is
+ not installed, or update is requested to an installed component,
+ current dependencies are read from repository so that correct dependencies
+ are calculated for the component when it is installed or updated.
+*/
+QStringList Component::currentDependencies() const
+{
+ QStringList dependenciesList;
+ if (isInstalled() && !updateRequested())
+ dependenciesList = localDependencies();
+ else
+ dependenciesList = dependencies();
+ return dependenciesList;
}
/*!
@@ -1383,7 +1502,7 @@ bool Component::isAutoDependOn(const QSet<QString> &componentsToInstall) const
// essential updates needs to be installed first, otherwise non-essential components
// will be installed
if (packageManagerCore()->foundEssentialUpdate()) {
- const QSet<QString> autoDependOnSet = autoDependOnList.toSet();
+ const QSet<QString> autoDependOnSet(autoDependOnList.begin(), autoDependOnList.end());
if (componentsToInstall.contains(autoDependOnSet)) {
foreach (const QString &autoDep, autoDependOnSet) {
Component *component = packageManagerCore()->componentByName(autoDep);
@@ -1421,8 +1540,7 @@ bool Component::isDefault() const
if (d->m_vars.value(scDefault).compare(scScript, Qt::CaseInsensitive) == 0) {
QJSValue valueFromScript;
try {
- valueFromScript = d->scriptEngine()->callScriptMethod(d->m_scriptContext,
- QLatin1String("isDefault"));
+ valueFromScript = callScriptMethod(scIsDefault);
} catch (const Error &error) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("isDefaultError"), tr("Cannot resolve isDefault in %1").arg(name()),
@@ -1478,11 +1596,21 @@ void Component::setUpdateAvailable(bool isUpdateAvailable)
}
/*!
+ Returns whether update is available for this component.
+
+ \sa {component::isUpdateAvailable}{component.isUpdateAvailable}
+*/
+bool Component::isUpdateAvailable() const
+{
+ return d->m_updateIsAvailable && !isUnstable();
+}
+
+/*!
Returns whether the user wants to install the update for this component.
\sa {component::updateRequested}{component.updateRequested}
*/
-bool Component::updateRequested()
+bool Component::updateRequested() const
{
return d->m_updateIsAvailable && isSelected() && !isUnstable();
}
@@ -1544,22 +1672,23 @@ void Component::setUnstable(Component::UnstableError error, const QString &error
{
QList<Component*> dependencies = d->m_core->dependees(this);
// Mark this component unstable
- markComponentUnstable();
+ markComponentUnstable(error, errorMessage);
// Marks all components unstable that depend on the unstable component
foreach (Component *dependency, dependencies) {
- dependency->markComponentUnstable();
+ dependency->markComponentUnstable(UnstableError::DepencyToUnstable,
+ QLatin1String("Dependent on unstable component"));
foreach (Component *descendant, dependency->descendantComponents()) {
- descendant->markComponentUnstable();
+ descendant->markComponentUnstable(UnstableError::DescendantOfUnstable,
+ QLatin1String("Descendant of unstable component"));
}
}
// Marks all child components unstable
foreach (Component *descendant, this->descendantComponents()) {
- descendant->markComponentUnstable();
+ descendant->markComponentUnstable(UnstableError::DescendantOfUnstable,
+ QLatin1String("Descendant of unstable component"));
}
- QMetaEnum metaEnum = QMetaEnum::fromType<Component::UnstableError>();
- emit packageManagerCore()->unstableComponentFound(QLatin1String(metaEnum.valueToKey(error)), errorMessage, this->name());
}
/*!
@@ -1645,23 +1774,26 @@ void Component::updateModelData(const QString &key, const QString &data)
setData(humanReadableSize(size), UncompressedSize);
}
- QString tooltipText;
- const QString &updateInfo = d->m_vars.value(scUpdateText);
- if (!d->m_core->isUpdater() || updateInfo.isEmpty()) {
- tooltipText = QString::fromLatin1("<html><body>%1</body></html>").arg(d->m_vars.value(scDescription));
- } else {
- tooltipText = d->m_vars.value(scDescription) + QLatin1String("<br><br>")
- + tr("Update Info: ") + updateInfo;
- }
- if (isUnstable()) {
- tooltipText += QLatin1String("<br>") + tr("There was an error loading the selected component. "
+ if (key == scUpdateText || key == scDescription) {
+ QString tooltipText;
+ const QString &updateInfo = d->m_vars.value(scUpdateText);
+ if (!d->m_core->isUpdater() || updateInfo.isEmpty()) {
+ tooltipText = QString::fromLatin1("<html><body>%1</body></html>").arg(d->m_vars.value(scDescription));
+ } else {
+ tooltipText = d->m_vars.value(scDescription) + scBr + scBr
+ + tr("Update Info: ") + updateInfo;
+ }
+ if (isUnstable()) {
+ tooltipText += scBr + tr("There was an error loading the selected component. "
"This component cannot be installed.");
- }
- // replace {external-link}='' fields in component description with proper link tags
- tooltipText.replace(QRegularExpression(QLatin1String("{external-link}='(.*?)'")),
- QLatin1String("<a href=\"\\1\">\\1</a>"));
+ }
+ static const QRegularExpression externalLinkRegexp(QLatin1String("{external-link}='(.*?)'"));
+ static const QLatin1String externalLinkElement(QLatin1String("<a href=\"\\1\">\\1</a>"));
+ // replace {external-link}='' fields in component description with proper link tags
+ tooltipText.replace(externalLinkRegexp, externalLinkElement);
- setData(tooltipText, Qt::ToolTipRole);
+ setData(tooltipText, Qt::ToolTipRole);
+ }
}
/*!
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index d042bfe6a..8f17b2d98 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,7 +32,6 @@
#include "constants.h"
#include "component_p.h"
#include "qinstallerglobal.h"
-#include "packagemanagercore.h"
#include <QtCore/QDir>
#include <QtCore/QMetaType>
@@ -44,6 +43,8 @@ QT_FORWARD_DECLARE_CLASS(QQmlV4Function)
namespace QInstaller {
+class PackageManagerCore;
+
class INSTALLER_EXPORT Component : public QObject, public ComponentModelHelper
{
Q_OBJECT
@@ -72,7 +73,9 @@ public:
DepencyToUnstable = 0,
ShaMismatch,
ScriptLoadingFailed,
- MissingDependency
+ MissingDependency,
+ InvalidTreeName,
+ DescendantOfUnstable
};
Q_ENUM(UnstableError)
@@ -106,6 +109,7 @@ public:
QHash<QString, QString> variables() const;
Q_INVOKABLE void setValue(const QString &key, const QString &value);
Q_INVOKABLE QString value(const QString &key, const QString &defaultValue = QString()) const;
+ int removeValue(const QString &key);
QStringList archives() const;
PackageManagerCore *packageManagerCore() const;
@@ -115,10 +119,9 @@ public:
void removeComponent(Component *component);
QList<Component*> descendantComponents() const;
- void loadComponentScript();
+ void loadComponentScript(const bool postLoad = false);
+ void evaluateComponentScript(const QString &fileName, const bool postScriptContext = false);
- //move this to private
- void loadComponentScript(const QString &fileName);
void loadTranslations(const QDir &directory, const QStringList &qms);
void loadUserInterfaces(const QDir &directory, const QStringList &uis);
void loadLicenses(const QString &directory, const QHash<QString, QVariant> &hash);
@@ -137,7 +140,7 @@ public:
QList<QPair<QString, bool> > pathsForUninstallation() const;
Q_INVOKABLE void registerPathForUninstallation(const QString &path, bool wipe = false);
- OperationList operations() const;
+ OperationList operations(const Operation::OperationGroups &mask = Operation::All) const;
void addOperation(Operation *operation);
Q_INVOKABLE bool addOperation(QQmlV4Function *args);
@@ -147,9 +150,10 @@ public:
Q_INVOKABLE bool addElevatedOperation(QQmlV4Function *args);
bool addElevatedOperation(const QString &operation, const QStringList &parameters);
- QStringList downloadableArchives() const;
+ QStringList downloadableArchives();
Q_INVOKABLE void addDownloadableArchive(const QString &path);
Q_INVOKABLE void removeDownloadableArchive(const QString &path);
+ void addDownloadableArchives(const QString& archives);
QStringList stopProcessForUpdateRequests() const;
Q_INVOKABLE void addStopProcessForUpdateRequest(const QString &process);
@@ -159,6 +163,7 @@ public:
QString name() const;
QString displayName() const;
QString treeName() const;
+ bool treeNameMoveChildren() const;
quint64 updateUncompressedSize();
QUrl repositoryUrl() const;
@@ -166,8 +171,10 @@ public:
Q_INVOKABLE void addDependency(const QString &newDependency);
QStringList dependencies() const;
+ QStringList localDependencies() const;
Q_INVOKABLE void addAutoDependOn(const QString &newDependOn);
QStringList autoDependencies() const;
+ QStringList currentDependencies() const;
void languageChanged();
QString localTempPath() const;
@@ -190,7 +197,8 @@ public:
Q_INVOKABLE bool isFromOnlineRepository() const;
Q_INVOKABLE void setUpdateAvailable(bool isUpdateAvailable);
- Q_INVOKABLE bool updateRequested();
+ Q_INVOKABLE bool isUpdateAvailable() const;
+ Q_INVOKABLE bool updateRequested() const;
Q_INVOKABLE bool componentChangeRequested();
Q_INVOKABLE bool isForcedUpdate();
@@ -201,6 +209,7 @@ public:
bool isVirtual() const;
bool isSelected() const;
bool forcedInstallation() const;
+ bool isEssential() const;
void setValidatorCallbackName(const QString &name);
@@ -227,7 +236,9 @@ private:
const QString &parameter8 = QString(), const QString &parameter9 = QString(),
const QString &parameter10 = QString());
Operation *createOperation(const QString &operationName, const QStringList &parameters);
- void markComponentUnstable();
+ void markComponentUnstable(const Component::UnstableError error, const QString &errorMessage);
+
+ QJSValue callScriptMethod(const QString &methodName, const QJSValueList &arguments = QJSValueList()) const;
private:
QString validatorCallbackName;
diff --git a/src/libs/installer/component_p.cpp b/src/libs/installer/component_p.cpp
index 0f74e423c..bf3941274 100644
--- a/src/libs/installer/component_p.cpp
+++ b/src/libs/installer/component_p.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -54,7 +54,10 @@ ComponentPrivate::ComponentPrivate(PackageManagerCore *core, Component *qq)
, m_autoCreateOperations(true)
, m_operationsCreatedSuccessfully(true)
, m_updateIsAvailable(false)
- , m_unstable(false)
+ , m_treeNameMoveChildren(false)
+ , m_postLoadScript(false)
+ , m_scriptContext(QJSValue::UndefinedValue)
+ , m_postScriptContext(QJSValue::UndefinedValue)
{
}
@@ -150,7 +153,7 @@ void ComponentModelHelper::setEnabled(bool enabled)
*/
bool ComponentModelHelper::isTristate() const
{
- return (flags() & Qt::ItemIsTristate) != 0;
+ return (flags() & Qt::ItemIsAutoTristate) != 0;
}
/*!
@@ -161,7 +164,7 @@ bool ComponentModelHelper::isTristate() const
*/
void ComponentModelHelper::setTristate(bool tristate)
{
- changeFlags(tristate, Qt::ItemIsTristate);
+ changeFlags(tristate, Qt::ItemIsAutoTristate);
}
/*!
@@ -185,6 +188,7 @@ void ComponentModelHelper::setCheckable(bool checkable)
setData(Qt::Unchecked, Qt::CheckStateRole);
}
changeFlags(checkable, Qt::ItemIsUserCheckable);
+ m_componentPrivate->m_vars[scCheckable] = checkable ? scTrue : scFalse;
}
/*!
diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h
index e4d28d26a..dea2d4935 100644
--- a/src/libs/installer/component_p.h
+++ b/src/libs/installer/component_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -63,18 +63,22 @@ public:
bool m_autoCreateOperations;
bool m_operationsCreatedSuccessfully;
bool m_updateIsAvailable;
- bool m_unstable;
+ bool m_treeNameMoveChildren;
+ bool m_postLoadScript;
QString m_componentName;
QUrl m_repositoryUrl;
QString m_localTempPath;
QJSValue m_scriptContext;
+ QJSValue m_postScriptContext;
QHash<QString, QString> m_vars;
QList<Component*> m_childComponents;
QList<Component*> m_allChildComponents;
QStringList m_downloadableArchives;
+ QString m_downloadableArchivesVariable;
QStringList m_stopProcessForUpdateRequests;
QHash<QString, QPointer<QWidget> > m_userInterfaces;
+ QHash<QString, QVariant> m_scriptHash;
// < display name, < file name, file content > >
QHash<QString, QVariantMap> m_licenses;
diff --git a/src/libs/installer/componentalias.cpp b/src/libs/installer/componentalias.cpp
new file mode 100644
index 000000000..955d715fd
--- /dev/null
+++ b/src/libs/installer/componentalias.cpp
@@ -0,0 +1,649 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "componentalias.h"
+
+#include "constants.h"
+#include "globals.h"
+#include "packagemanagercore.h"
+#include "updater.h"
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+
+namespace QInstaller {
+
+static const QStringList scPossibleElements {
+ scName,
+ scDisplayName,
+ scDescription,
+ scVersion,
+ scVirtual,
+ scRequiredComponents,
+ scRequiredAliases,
+ scOptionalComponents,
+ scOptionalAliases,
+ scReleaseDate
+};
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::AliasSource
+ \brief Describes a source for alias declarations.
+*/
+
+/*!
+ \enum QInstaller::AliasSource::SourceFileFormat
+
+ This enum type holds the possible file formats for alias source:
+
+ \value Unknown
+ Invalid or unknown file format.
+ \value Xml
+ XML file format.
+ \value Json
+ JSON file format.
+*/
+
+/*!
+ Constructs an alias source with empty information.
+*/
+AliasSource::AliasSource()
+ : priority(-1)
+{}
+
+/*!
+ Constructs an alias source with source file format \a aFormat, filename \a aFilename, and priority \a aPriority.
+*/
+AliasSource::AliasSource(SourceFileFormat aFormat, const QString &aFilename, int aPriority)
+ : format(aFormat)
+ , filename(aFilename)
+ , priority(aPriority)
+{}
+
+/*!
+ Copy-constructs an alias source from \a other.
+*/
+AliasSource::AliasSource(const AliasSource &other)
+{
+ format = other.format;
+ filename = other.filename;
+ priority = other.priority;
+}
+
+/*!
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+hashValue qHash(const AliasSource &key, hashValue seed)
+{
+ return qHash(key.filename, seed) ^ key.priority;
+}
+
+/*!
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
+*/
+bool operator==(const AliasSource &lhs, const AliasSource &rhs)
+{
+ return lhs.filename == rhs.filename && lhs.priority == rhs.priority && lhs.format == rhs.format;
+}
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::AliasFinder
+ \brief Creates component alias objects from parsed alias source files, based
+ on version and source priorities.
+*/
+
+/*!
+ Constructs a new alias finder with \a core as the package manager instance.
+*/
+AliasFinder::AliasFinder(PackageManagerCore *core)
+ : m_core(core)
+{
+}
+
+/*!
+ Destroys the finder and cleans unreleased results.
+*/
+AliasFinder::~AliasFinder()
+{
+ clear();
+}
+
+/*!
+ Runs the finder. Parses the alias source files and creates component alias
+ objects based on the parsed data. Same alias may be declared in multiple source
+ files, thus source priority and version information is used to decide which
+ source is used for creating the alias object.
+
+ Any previous results are cleared when calling this.
+
+ Returns \c true if at least one alias was found, \c false otherwise.
+*/
+bool AliasFinder::run()
+{
+ clear();
+
+ if (m_sources.isEmpty())
+ return false;
+
+ // 1. Parse source files
+ for (auto &source : qAsConst(m_sources)) {
+ if (source.format == AliasSource::SourceFileFormat::Unknown) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Unknown alias source format for file:" << source.filename;
+ continue;
+ }
+ if (source.format == AliasSource::SourceFileFormat::Xml)
+ parseXml(source);
+ else if (source.format == AliasSource::SourceFileFormat::Json)
+ parseJson(source);
+ }
+
+ // 2. Create aliases based on priority & version
+ for (auto &data : qAsConst(m_aliasData)) {
+ const QString name = data.value(scName).toString();
+ const Resolution resolution = checkPriorityAndVersion(data);
+ if (resolution == Resolution::KeepExisting)
+ continue;
+
+ if (resolution == Resolution::RemoveExisting)
+ delete m_aliases.take(name);
+
+ ComponentAlias *alias = new ComponentAlias(m_core);
+ AliasData::const_iterator it;
+ for (it = data.cbegin(); it != data.cend(); ++it) {
+ if (it.value().canConvert<QString>())
+ alias->setValue(it.key(), it.value().toString());
+ }
+ m_aliases.insert(name, alias);
+ }
+
+ return !m_aliases.isEmpty();
+}
+
+/*!
+ Returns a list of the found aliases.
+*/
+QList<ComponentAlias *> AliasFinder::aliases() const
+{
+ return m_aliases.values();
+}
+
+/*!
+ Sets the alias sources to look alias information from to \a sources.
+*/
+void AliasFinder::setAliasSources(const QSet<AliasSource> &sources)
+{
+ clear();
+ m_sources = sources;
+}
+
+/*!
+ Clears the results of the finder.
+*/
+void AliasFinder::clear()
+{
+ qDeleteAll(m_aliases);
+
+ m_aliases.clear();
+ m_aliasData.clear();
+}
+
+/*!
+ Reads an XML file specified by \a filename, and constructs a variant map of
+ the data for each alias.
+
+ Returns \c true on success, \c false otherwise.
+*/
+bool AliasFinder::parseXml(AliasSource source)
+{
+ QFile file(source.filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open alias definition for reading:" << file.errorString();
+ return false;
+ }
+
+ QString error;
+ int errorLine;
+ int errorColumn;
+
+ QDomDocument doc;
+ if (!doc.setContent(&file, &error, &errorLine, &errorColumn)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot read alias definition document:" << error
+ << "line:" << errorLine << "column:" << errorColumn;
+ return false;
+ }
+ file.close();
+
+ const QDomElement root = doc.documentElement();
+ const QDomNodeList children = root.childNodes();
+
+ for (int i = 0; i < children.count(); ++i) {
+ const QDomElement el = children.at(i).toElement();
+ const QString tag = el.tagName();
+ if (el.isNull() || tag != scAlias) {
+ qCWarning(lcInstallerInstallLog) << "Unexpected element name:" << tag;
+ continue;
+ }
+
+ AliasData data;
+ data.insert(QLatin1String("source"), QVariant::fromValue(source));
+
+ const QDomNodeList c2 = el.childNodes();
+ for (int j = 0; j < c2.count(); ++j) {
+ const QDomElement el2 = c2.at(j).toElement();
+ const QString tag2 = el2.tagName();
+ if (!scPossibleElements.contains(tag2)) {
+ qCWarning(lcInstallerInstallLog) << "Unexpected element name:" << tag2;
+ continue;
+ }
+ data.insert(tag2, el2.text());
+ }
+
+ m_aliasData.insert(data.value(scName).toString(), data);
+ }
+
+ return true;
+}
+
+/*!
+ Reads a JSON file specified by \a source, and constructs a variant map of
+ the data for each alias.
+
+ Returns \c true on success, \c false otherwise.
+*/
+bool AliasFinder::parseJson(AliasSource source)
+{
+ QFile file(source.filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open alias definition for reading:" << file.errorString();
+ return false;
+ }
+
+ const QByteArray jsonData = file.readAll();
+ const QJsonDocument doc(QJsonDocument::fromJson(jsonData));
+ const QJsonObject docJsonObject = doc.object();
+
+ const QJsonArray aliases = docJsonObject.value(QLatin1String("alias-packages")).toArray();
+ for (auto &it : aliases) {
+ AliasData data;
+ data.insert(QLatin1String("source"), QVariant::fromValue(source));
+
+ QJsonObject aliasObj = it.toObject();
+ for (const auto &key : aliasObj.keys()) {
+ if (!scPossibleElements.contains(key)) {
+ qCWarning(lcInstallerInstallLog) << "Unexpected element name:" << key;
+ continue;
+ }
+
+ const QJsonValue jsonValue = aliasObj.value(key);
+ if (key == scRequiredComponents || key == scRequiredAliases
+ || key == scOptionalComponents || key == scOptionalAliases) {
+ const QJsonArray requirements = jsonValue.toArray();
+ QString requiresString;
+
+ for (const auto &it2 : requirements) {
+ requiresString.append(it2.toString());
+ if (it2 != requirements.last())
+ requiresString.append(QLatin1Char(','));
+ }
+
+ data.insert(key, requiresString);
+ } else if (key == scVirtual) {
+ data.insert(key, QVariant(jsonValue.toBool()))->toString();
+ } else {
+ data.insert(key, jsonValue.toString());
+ }
+ }
+
+ m_aliasData.insert(data.value(scName).toString(), data);
+ }
+
+ return true;
+}
+
+/*!
+ Checks whether \a data should be used for creating a new alias object,
+ based on version and source priority.
+
+ If an alias of the same name exists, always use the one with the higher
+ version. If the new alias has the same version but a higher
+ priority, use the new new alias. Otherwise keep the already existing alias.
+
+ Returns the resolution of the check.
+*/
+AliasFinder::Resolution AliasFinder::checkPriorityAndVersion(const AliasData &data) const
+{
+ for (const auto &existingData : m_aliasData.values(data.value(scName).toString())) {
+ if (existingData == data)
+ continue;
+
+ const int versionMatch = KDUpdater::compareVersion(data.value(scVersion).toString(),
+ existingData.value(scVersion).toString());
+
+ const AliasSource newSource = data.value(QLatin1String("source")).value<AliasSource>();
+ const AliasSource oldSource = existingData.value(QLatin1String("source")).value<AliasSource>();
+
+ if (versionMatch > 0) {
+ // new alias has higher version, use
+ qCDebug(QInstaller::lcDeveloperBuild).nospace() << "Remove Alias 'Name: "
+ << data.value(scName).toString() << ", Version: " << existingData.value(scVersion).toString()
+ << ", Source: " << oldSource.filename
+ << "' found an alias with higher version 'Name: "
+ << data.value(scName).toString() << ", Version: " << data.value(scVersion).toString()
+ << ", Source: " << newSource.filename << "'";
+
+ return Resolution::RemoveExisting;
+ }
+
+ if ((versionMatch == 0) && (newSource.priority > oldSource.priority)) {
+ // new alias version equals but priority is higher, use
+ qCDebug(QInstaller::lcDeveloperBuild).nospace() << "Remove Alias 'Name: "
+ << data.value(scName).toString() << ", Priority: " << oldSource.priority
+ << ", Source: " << oldSource.filename
+ << "' found an alias with higher priority 'Name: "
+ << data.value(scName).toString() << ", Priority: " << newSource.priority
+ << ", Source: " << newSource.filename << "'";
+
+ return Resolution::RemoveExisting;
+ }
+
+ return Resolution::KeepExisting; // otherwise keep existing
+ }
+
+ return Resolution::AddNew;
+}
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::ComponentAlias
+ \brief The ComponentAlias class represents an alias for single or multiple components.
+*/
+
+/*!
+ \enum QInstaller::ComponentAlias::UnstableError
+
+ This enum type holds the possible reasons for marking an alias unstable:
+
+ \value ReferenceToUnstable
+ Alias requires another alias that is marked unstable.
+ \value MissingComponent
+ Alias requires a component that is missing.
+ \value UnselectableComponent
+ Alias requires a component that cannot be selected.
+ \value MissingAlias
+ Alias requires another alias that is missing.
+ \value ComponentNameConfict
+ Alias has a name that conflicts with a name of a component
+*/
+
+/*!
+ Constructs a new component alias with \a core as the package manager instance.
+*/
+ComponentAlias::ComponentAlias(PackageManagerCore *core)
+ : m_core(core)
+ , m_selected(false)
+ , m_unstable(false)
+{
+}
+
+/*!
+ Destructs the alias.
+*/
+ComponentAlias::~ComponentAlias()
+{
+}
+
+/*!
+ Returns the name of the alias.
+*/
+QString ComponentAlias::name() const
+{
+ return m_variables.value(scName);
+}
+
+/*!
+ Returns the display name of the alias.
+*/
+QString ComponentAlias::displayName() const
+{
+ return m_variables.value(scDisplayName);
+}
+
+/*!
+ Returns the description text of the alias.
+*/
+QString ComponentAlias::description() const
+{
+ return m_variables.value(scDescription);
+}
+
+/*!
+ Returns the version of the alias.
+*/
+QString ComponentAlias::version() const
+{
+ return m_variables.value(scVersion);
+}
+
+/*!
+ Returns \c true if the alias is virtual, \c false otherwise.
+
+ Virtual aliases are aliases that cannot be selected by the
+ user, and are invisible. They can be required by other aliases however.
+*/
+bool ComponentAlias::isVirtual() const
+{
+ return m_variables.value(scVirtual, scFalse).toLower() == scTrue;
+}
+
+/*!
+ Returns \c true if the alias is selected for installation, \c false otherwise.
+*/
+bool ComponentAlias::isSelected() const
+{
+ return m_selected;
+}
+
+/*!
+ Sets the selection state of the alias to \a selected. The selection
+ does not have an effect if the alias is unselectable.
+*/
+void ComponentAlias::setSelected(bool selected)
+{
+ if (selected && (isUnstable() || isVirtual()))
+ return;
+
+ m_selected = selected;
+}
+
+/*!
+ Returns the list of components required by this alias, or an
+ empty list if this alias does not require any components.
+*/
+QList<Component *> ComponentAlias::components()
+{
+ if (m_components.isEmpty()) {
+ const QStringList componentList = QInstaller::splitStringWithComma(
+ m_variables.value(scRequiredComponents));
+
+ const QStringList optionalComponentList = QInstaller::splitStringWithComma(
+ m_variables.value(scOptionalComponents));
+
+ addRequiredComponents(componentList, false);
+ addRequiredComponents(optionalComponentList, true);
+ }
+
+ return m_components;
+}
+
+/*!
+ Returns the list of other aliases required by this alias, or an
+ empty list if this alias does not require any other aliases.
+*/
+QList<ComponentAlias *> ComponentAlias::aliases()
+{
+ if (m_aliases.isEmpty()) {
+ const QStringList aliasList = QInstaller::splitStringWithComma(
+ m_variables.value(scRequiredAliases));
+
+ const QStringList optionalAliasList = QInstaller::splitStringWithComma(
+ m_variables.value(scOptionalAliases));
+
+ addRequiredAliases(aliasList, false);
+ addRequiredAliases(optionalAliasList, true);
+ }
+
+ return m_aliases;
+}
+
+/*!
+ Returns the value specified by \a key, with an optional default value \a defaultValue.
+*/
+QString ComponentAlias::value(const QString &key, const QString &defaultValue) const
+{
+ return m_variables.value(key, defaultValue);
+}
+
+/*!
+ Sets the value specified by \a key to \a value. If the value exists already,
+ it is replaced with the new value.
+*/
+void ComponentAlias::setValue(const QString &key, const QString &value)
+{
+ const QString normalizedValue = m_core->replaceVariables(value);
+ if (m_variables.value(key) == normalizedValue)
+ return;
+
+ m_variables[key] = normalizedValue;
+}
+
+/*!
+ Returns all keys for the component alias values.
+*/
+QStringList ComponentAlias::keys() const
+{
+ return m_variables.keys();
+}
+
+/*!
+ Returns \c true if the alias is marked unstable, \c false otherwise.
+*/
+bool ComponentAlias::isUnstable() const
+{
+ return m_unstable;
+}
+
+/*!
+ Sets the alias unstable with \a error, and a \a message describing the error.
+*/
+void ComponentAlias::setUnstable(UnstableError error, const QString &message)
+{
+ setSelected(false);
+ m_unstable = true;
+
+ const QMetaEnum metaEnum = QMetaEnum::fromType<ComponentAlias::UnstableError>();
+ emit m_core->unstableComponentFound(
+ QLatin1String(metaEnum.valueToKey(error)), message, name());
+}
+
+/*!
+ \internal
+
+ Adds the \a aliases to the list of required aliases by this alias. If \a optional
+ is \c true, missing alias references are ignored.
+*/
+void ComponentAlias::addRequiredAliases(const QStringList &aliases, const bool optional)
+{
+ for (const auto &aliasName : aliases) {
+ ComponentAlias *alias = m_core->aliasByName(aliasName);
+ if (!alias) {
+ if (optional)
+ continue;
+
+ const QString error = QLatin1String("No required alias found by name: ") + aliasName;
+ qCWarning(lcInstallerInstallLog) << error;
+
+ setUnstable(UnstableError::MissingAlias, error);
+ continue;
+ }
+
+ if (alias->isUnstable()) {
+ const QString error = QLatin1String("Alias requires another alias "
+ "that is marked unstable: ") + aliasName;
+ qCWarning(lcInstallerInstallLog) << error;
+
+ setUnstable(UnstableError::ReferenceToUnstable, error);
+ continue;
+ }
+
+ m_aliases.append(alias);
+ }
+}
+
+/*!
+ \internal
+
+ Adds the \a components to the list of required components by this alias. If \a optional
+ is \c true, missing component references are ignored.
+*/
+void ComponentAlias::addRequiredComponents(const QStringList &components, const bool optional)
+{
+ for (const auto &componentName : components) {
+ Component *component = m_core->componentByName(componentName);
+ if (!component) {
+ if (optional)
+ continue;
+
+ const QString error = QLatin1String("No required component found by name: ")
+ + componentName;
+ qCWarning(lcInstallerInstallLog) << error;
+
+ setUnstable(UnstableError::MissingComponent, error);
+ continue;
+ }
+
+ if (component->isUnstable() || !component->isCheckable()) {
+ const QString error = QLatin1String("Alias requires component that is uncheckable or unstable: ")
+ + componentName;
+ qCWarning(lcInstallerInstallLog) << error;
+
+ setUnstable(UnstableError::UnselectableComponent, error);
+ continue;
+ }
+
+ m_components.append(component);
+ }
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/componentalias.h b/src/libs/installer/componentalias.h
new file mode 100644
index 000000000..e99c343d9
--- /dev/null
+++ b/src/libs/installer/componentalias.h
@@ -0,0 +1,160 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef COMPONENTALIAS_H
+#define COMPONENTALIAS_H
+
+#include "installer_global.h"
+
+#include <QHash>
+#include <QMetaEnum>
+#include <QString>
+#include <QSet>
+
+namespace QInstaller {
+
+class Component;
+class ComponentAlias;
+class PackageManagerCore;
+
+struct INSTALLER_EXPORT AliasSource
+{
+ enum class SourceFileFormat {
+ Unknown = -1,
+ Xml = 0,
+ Json
+ };
+
+ AliasSource();
+ AliasSource(SourceFileFormat aFormat, const QString &aFilename, int aPriority);
+ AliasSource(const AliasSource &other);
+
+ SourceFileFormat format;
+ QString filename;
+ int priority;
+};
+
+INSTALLER_EXPORT hashValue qHash(const AliasSource &key, hashValue seed);
+INSTALLER_EXPORT bool operator==(const AliasSource &lhs, const AliasSource &rhs);
+
+class INSTALLER_EXPORT AliasFinder
+{
+public:
+ using AliasData = QVariantMap;
+ using AliasDataHash = QMultiHash<QString, AliasData>;
+
+ enum struct Resolution {
+ AddNew,
+ KeepExisting,
+ RemoveExisting
+ };
+
+ explicit AliasFinder(PackageManagerCore *core);
+ ~AliasFinder();
+
+ bool run();
+ QList<ComponentAlias *> aliases() const;
+
+ void setAliasSources(const QSet<AliasSource> &sources);
+
+private:
+ void clear();
+ Resolution checkPriorityAndVersion(const AliasData &data) const;
+
+ bool parseXml(AliasSource source);
+ bool parseJson(AliasSource source);
+
+private:
+ PackageManagerCore *const m_core;
+
+ QSet<AliasSource> m_sources;
+ AliasDataHash m_aliasData;
+ QHash<QString, ComponentAlias *> m_aliases;
+};
+
+class INSTALLER_EXPORT ComponentAlias : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY_MOVE(ComponentAlias)
+
+public:
+ enum UnstableError {
+ ReferenceToUnstable = 0,
+ MissingComponent,
+ UnselectableComponent,
+ MissingAlias,
+ ComponentNameConfict
+ };
+ Q_ENUM(UnstableError)
+
+ ComponentAlias(PackageManagerCore *core);
+ ~ComponentAlias();
+
+ QString name() const;
+ QString displayName() const;
+ QString description() const;
+
+ QString version() const;
+
+ bool isVirtual() const;
+
+ bool isSelected() const;
+ void setSelected(bool selected);
+
+ QList<Component *> components();
+ QList<ComponentAlias *> aliases();
+
+ QString value(const QString &key, const QString &defaultValue = QString()) const;
+ void setValue(const QString &key, const QString &value);
+ QStringList keys() const;
+
+ bool isUnstable() const;
+ void setUnstable(UnstableError error, const QString &message = QString());
+
+private:
+ void addRequiredAliases(const QStringList &aliases, const bool optional);
+ void addRequiredComponents(const QStringList &components, const bool optional);
+
+private:
+ PackageManagerCore *const m_core;
+
+ QHash<QString, QString> m_variables;
+
+ bool m_selected;
+ bool m_unstable;
+
+ QList<Component *> m_components;
+ QList<ComponentAlias *> m_aliases;
+};
+
+} // namespace QInstaller
+
+Q_DECLARE_METATYPE(QInstaller::ComponentAlias *)
+Q_DECLARE_METATYPE(QInstaller::AliasSource);
+
+#endif // COMPONENTALIAS_H
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index 56ee57fc6..1e8dd1ff7 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -47,6 +47,8 @@ namespace QInstaller {
This enum value holds the checked state of the components available for
installation.
+ \value Empty
+ The model does not contain any components.
\value AllChecked
All components are checked.
\value AllUnchecked
@@ -58,13 +60,6 @@ namespace QInstaller {
*/
/*!
- \fn void QInstaller::ComponentModel::checkStateChanged(const QModelIndex &index)
-
- This signal is emitted whenever the checked state of a component is changed. The \a index value
- indicates the QModelIndex representation of the component as seen from the model.
-*/
-
-/*!
\fn void QInstaller::ComponentModel::checkStateChanged(QInstaller::ComponentModel::ModelState state)
This signal is emitted whenever the checked state of a model is changed after all state
@@ -221,7 +216,10 @@ QVariant ComponentModel::data(const QModelIndex &index, int role) const
return component->data(Qt::UserRole + index.column());
}
if (role == Qt::CheckStateRole) {
- if (!component->isCheckable() || !component->autoDependencies().isEmpty() || component->isUnstable())
+ if (!component->isCheckable() || component->isUnstable())
+ return QVariant();
+
+ if (!m_core->isUpdater() && !component->autoDependencies().isEmpty())
return QVariant();
}
if (role == ComponentModelHelper::ExpandedByDefault) {
@@ -238,7 +236,6 @@ QVariant ComponentModel::data(const QModelIndex &index, int role) const
/*!
Sets the \a role data for the item at \a index to \a value. Returns true if successful;
otherwise returns false. The dataChanged() signal is emitted if the data was successfully set.
- The checkStateChanged() signals are emitted in addition if the checked state of the item is set.
*/
bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
@@ -252,17 +249,17 @@ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, in
if (role == Qt::CheckStateRole) {
if (index.column() != 0)
return false;
- ComponentSet nodes = component->childItems().toSet();
+
+ const QList<Component*> childItems = component->childItems();
+ ComponentSet nodes(childItems.begin(), childItems.end());
Qt::CheckState newValue = Qt::CheckState(value.toInt());
if (newValue == Qt::PartiallyChecked) {
const Qt::CheckState oldValue = component->checkState();
newValue = (oldValue == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
}
- QSet<QModelIndex> changed = updateCheckedState(nodes << component, newValue);
- foreach (const QModelIndex &changedIndex, changed) {
+ const QSet<QModelIndex> changed = updateCheckedState(nodes << component, newValue);
+ foreach (const QModelIndex &changedIndex, changed)
emit dataChanged(changedIndex, changedIndex);
- emit checkStateChanged(changedIndex);
- }
updateAndEmitModelState(); // update the internal state
} else {
component->setData(value, role);
@@ -338,6 +335,22 @@ QSet<Component *> ComponentModel::uncheckable() const
return m_uncheckable;
}
+bool ComponentModel::componentsSelected() const
+{
+ if (m_core->isInstaller() || m_core->isUpdater())
+ return checked().count();
+
+ if (checkedState().testFlag(ComponentModel::DefaultChecked) == false)
+ return true;
+
+ const QSet<Component *> uncheckables = uncheckable();
+ for (auto &component : uncheckables) {
+ if (component->forcedInstallation() && !component->isInstalled())
+ return true; // allow installation for new forced components
+ }
+ return false;
+}
+
/*!
Returns a pointer to the PackageManagerCore this model belongs to.
*/
@@ -384,20 +397,20 @@ Component *ComponentModel::componentFromIndex(const QModelIndex &index) const
// -- public slots
/*!
- Sets \a rootComponents to be the list of currently shown components.
+ Resets model and sets \a rootComponents to be the list of currently shown components.
The model is repopulated and the individual component's checked state is used to show the check
mark in front of the visual component representation. The modelAboutToBeReset() and
modelReset() signals are emitted.
*/
-void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootComponents)
+void ComponentModel::reset(QList<Component *> rootComponents)
{
beginResetModel();
m_uncheckable.clear();
m_indexByNameCache.clear();
m_rootComponentList.clear();
- m_modelState = DefaultChecked;
+ m_modelState = !rootComponents.isEmpty() ? DefaultChecked : Empty;
// Initialize these with an empty set for every possible state, cause we compare the hashes later in
// updateAndEmitModelState(). The comparison than might lead to wrong results if one of the checked
@@ -423,36 +436,26 @@ void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootCompone
Sets the checked state of every component in the model to be \a state.
The ComponentModel::PartiallyChecked flag is ignored by this function. Note that components
- are not changed if they are not checkable. The dataChanged() and checkStateChanged() signals
- are emitted.
+ are not changed if they are not checkable. The modelCheckStateChanged() signal
+ is emitted.
*/
void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag state)
{
- QSet<QModelIndex> changed;
switch (state) {
case AllChecked:
- changed = updateCheckedState(m_currentCheckedState[Qt::Unchecked], Qt::Checked);
+ updateCheckedState(m_currentCheckedState[Qt::Unchecked], Qt::Checked);
break;
case AllUnchecked:
- changed = updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
+ updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
break;
case DefaultChecked:
// record all changes, to be able to update the UI properly
- changed = updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
- changed += updateCheckedState(m_initialCheckedState[Qt::Checked], Qt::Checked);
+ updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
+ updateCheckedState(m_initialCheckedState[Qt::Checked], Qt::Checked);
break;
default:
break;
}
-
- if (changed.isEmpty())
- return;
-
- // notify about changes done to the model
- foreach (const QModelIndex &index, changed) {
- emit dataChanged(index, index);
- emit checkStateChanged(index);
- }
updateAndEmitModelState(); // update the internal state
}
@@ -462,7 +465,7 @@ void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag
void ComponentModel::onVirtualStateChanged()
{
// If the virtual state of a component changes, force a reset of the component model.
- setRootComponents(m_core->components(PackageManagerCore::ComponentType::Root));
+ reset(m_core->components(PackageManagerCore::ComponentType::Root));
}
@@ -496,6 +499,10 @@ void ComponentModel::postModelReset()
void ComponentModel::updateAndEmitModelState()
{
+ if (m_rootComponentList.isEmpty()) {
+ m_modelState = ComponentModel::Empty;
+ return;
+ }
m_modelState = ComponentModel::DefaultChecked;
if (m_initialCheckedState != m_currentCheckedState)
m_modelState = ComponentModel::PartiallyChecked;
@@ -554,13 +561,13 @@ static Qt::CheckState verifyPartiallyChecked(Component *component)
} // namespace ComponentModelPrivate
-QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, Qt::CheckState state)
+QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, const Qt::CheckState state)
{
// get all parent nodes for the components we're going to update
- QMap<QString, Component *> sortedNodesMap;
+ QMultiMap<QString, Component *> sortedNodesMap;
foreach (Component *component, components) {
while (component && !sortedNodesMap.values(component->treeName()).contains(component)) {
- sortedNodesMap.insertMulti(component->treeName(), component);
+ sortedNodesMap.insert(component->treeName(), component);
component = component->parentComponent();
}
}
@@ -571,14 +578,16 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
for (int i = sortedNodes.count(); i > 0; i--) {
Component * const node = sortedNodes.at(i - 1);
- bool checkable = true;
- if (node->value(scCheckable, scTrue).toLower() == scFalse) {
- checkable = false;
- }
+ if (!node->isEnabled() || node->isUnstable())
+ continue;
- if ((!node->isCheckable() && checkable) || !node->isEnabled() || !node->autoDependencies().isEmpty() || node->isUnstable())
+ //Do not let forced installations to be uninstalled
+ if (!m_core->isUpdater() && node->forcedInstallation() && (node->checkState() != Qt::Unchecked))
continue;
+ if (!m_core->isUpdater() && !node->autoDependencies().isEmpty())
+ continue;
+
Qt::CheckState newState = state;
const Qt::CheckState recentState = node->checkState();
if (node->isTristate())
diff --git a/src/libs/installer/componentmodel.h b/src/libs/installer/componentmodel.h
index e5cd2c57d..c93dd60ae 100644
--- a/src/libs/installer/componentmodel.h
+++ b/src/libs/installer/componentmodel.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,6 +31,8 @@
#include "qinstallerglobal.h"
+#include "component.h"
+
#include <QtCore/QAbstractItemModel>
#include <QtCore/QList>
#include <QtCore/QSet>
@@ -38,7 +40,6 @@
namespace QInstaller {
-class Component;
class PackageManagerCore;
class INSTALLER_EXPORT ComponentModel : public QAbstractItemModel
@@ -49,6 +50,7 @@ class INSTALLER_EXPORT ComponentModel : public QAbstractItemModel
public:
enum ModelStateFlag {
+ Empty = -0x01,
AllChecked = 0x01,
AllUnchecked = 0x02,
DefaultChecked = 0x04,
@@ -59,25 +61,26 @@ public:
explicit ComponentModel(int columns, PackageManagerCore *core = 0);
~ComponentModel();
- Qt::ItemFlags flags(const QModelIndex &index) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- QModelIndex parent(const QModelIndex &child) const;
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
- int role = Qt::EditRole);
+ int role = Qt::EditRole) override;
QSet<Component *> checked() const;
QSet<Component *> partially() const;
QSet<Component *> unchecked() const;
QSet<Component *> uncheckable() const;
+ bool componentsSelected() const;
PackageManagerCore *core() const;
ComponentModel::ModelState checkedState() const;
@@ -86,11 +89,10 @@ public:
Component* componentFromIndex(const QModelIndex &index) const;
public Q_SLOTS:
- void setRootComponents(QList<QInstaller::Component*> rootComponents);
+ void reset(QList<Component *> rootComponents = QList<Component *>());
void setCheckedState(QInstaller::ComponentModel::ModelStateFlag state);
Q_SIGNALS:
- void checkStateChanged(const QModelIndex &index);
void checkStateChanged(QInstaller::ComponentModel::ModelState state);
private Q_SLOTS:
@@ -100,7 +102,7 @@ private:
void postModelReset();
void updateAndEmitModelState();
void collectComponents(Component *const component, const QModelIndex &parent) const;
- QSet<QModelIndex> updateCheckedState(const ComponentSet &components, Qt::CheckState state);
+ QSet<QModelIndex> updateCheckedState(const ComponentSet &components, const Qt::CheckState state);
private:
PackageManagerCore *m_core;
diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp
index 7717f4cf3..b68eebf06 100644
--- a/src/libs/installer/componentselectionpage_p.cpp
+++ b/src/libs/installer/componentselectionpage_p.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -28,12 +28,14 @@
#include "componentselectionpage_p.h"
+#include "globals.h"
#include "packagemanagergui.h"
#include "componentmodel.h"
#include "settings.h"
#include "component.h"
#include "fileutils.h"
#include "messageboxhandler.h"
+#include "customcombobox.h"
#include <QTreeView>
#include <QLabel>
@@ -44,13 +46,13 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QCheckBox>
-#include <QHeaderView>
#include <QStandardPaths>
#include <QFileDialog>
#include <QStackedLayout>
#include <QStackedWidget>
-#include <QToolBox>
#include <QLineEdit>
+#include <QStandardItemModel>
+#include <QStyledItemDelegate>
namespace QInstaller {
@@ -60,23 +62,29 @@ namespace QInstaller {
\internal
*/
+constexpr int scNoCheckSelectionIndex = -1;
+constexpr int scCheckDefaultIndex = 0;
+constexpr int scCheckAllIndex = 1;
+constexpr int scUncheckAllIndex = 2;
+
ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionPage *qq, PackageManagerCore *core)
: q(qq)
, m_core(core)
, m_treeView(new QTreeView(q))
- , m_allModel(m_core->defaultComponentModel())
- , m_updaterModel(m_core->updaterComponentModel())
- , m_currentModel(m_allModel)
- , m_allowCompressedRepositoryInstall(false)
- , m_toolBox(nullptr)
+ , m_tabWidget(nullptr)
, m_descriptionBaseWidget(nullptr)
, m_categoryWidget(Q_NULLPTR)
+ , m_allowCreateOfflineInstaller(false)
, m_categoryLayoutVisible(false)
- , m_proxyModel(new ComponentSortFilterProxyModel(q))
+ , m_allModel(m_core->defaultComponentModel())
+ , m_updaterModel(m_core->updaterComponentModel())
+ , m_currentModel(m_allModel)
+ , m_proxyModel(m_core->componentSortFilterProxyModel())
+ , m_componentsResolved(false)
+ , m_headerStretchLastSection(false)
{
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
- m_proxyModel->setRecursiveFilteringEnabled(true);
- m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ m_treeView->setUniformRowHeights(true);
m_descriptionBaseWidget = new QWidget(q);
m_descriptionBaseWidget->setObjectName(QLatin1String("DescriptionBaseWidget"));
@@ -85,8 +93,12 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
descriptionVLayout->setObjectName(QLatin1String("DescriptionLayout"));
descriptionVLayout->setContentsMargins(0, 0, 0, 0);
- m_toolBox = new QToolBox(q);
- m_toolBox->setObjectName(QLatin1String("ToolBox"));
+ m_tabWidget = new QTabWidget(q);
+ m_tabWidget->setObjectName(QLatin1String("ComponentSelectionTabWidget"));
+ m_tabWidget->tabBar()->setObjectName(QLatin1String("ComponentSelectionTabBar"));
+ m_tabWidget->hide();
+
+ m_rightSideVLayout = new QVBoxLayout;
QScrollArea *descriptionScrollArea = new QScrollArea(q);
descriptionScrollArea->setWidgetResizable(true);
@@ -107,46 +119,67 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel"));
descriptionVLayout->addWidget(m_sizeLabel);
- QHBoxLayout *buttonHLayout = new QHBoxLayout;
- m_checkDefault = new QPushButton;
- connect(m_checkDefault, &QAbstractButton::clicked,
- this, &ComponentSelectionPagePrivate::selectDefault);
+ m_createOfflinePushButton = new QPushButton(q);
+ m_createOfflinePushButton->setVisible(false);
+ m_createOfflinePushButton->setText(ComponentSelectionPage::tr("Create Offline Installer"));
+ m_createOfflinePushButton->setToolTip(
+ ComponentSelectionPage::tr("Create offline installer from selected components, instead "
+ "of installing now."));
+
+ connect(m_createOfflinePushButton, &QPushButton::clicked,
+ this, &ComponentSelectionPagePrivate::createOfflineButtonClicked);
+ connect(q, &ComponentSelectionPage::completeChanged,
+ this, [&]() { m_createOfflinePushButton->setEnabled(q->isComplete()); });
+
+ m_qbspPushButton = new QPushButton(q);
+ m_qbspPushButton->setVisible(false);
+ m_qbspPushButton->setText(ComponentSelectionPage::tr("Browse &QBSP files"));
+ m_qbspPushButton->setToolTip(
+ ComponentSelectionPage::tr("Select a Qt Board Support Package file to install "
+ "additional content that is not directly available from the online repositories."));
+
+ connect(m_qbspPushButton, &QPushButton::clicked,
+ this, &ComponentSelectionPagePrivate::qbspButtonClicked);
+
+ m_rightSideVLayout->addWidget(m_descriptionBaseWidget);
+ m_rightSideVLayout->addWidget(m_createOfflinePushButton);
+ m_rightSideVLayout->addWidget(m_qbspPushButton);
+
+ QHBoxLayout *topHLayout = new QHBoxLayout;
+
+ // Using custom combobox to workaround QTBUG-90595
+ m_checkStateComboBox = new CustomComboBox(q);
+#ifdef Q_OS_MACOS
+ QStyledItemDelegate *delegate = new QStyledItemDelegate(this);
+ m_checkStateComboBox->setItemDelegate(delegate);
+#endif
+ m_checkStateComboBox->setObjectName(QLatin1String("CheckStateComboBox"));
+ topHLayout->addWidget(m_checkStateComboBox);
+
+ connect(m_checkStateComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &ComponentSelectionPagePrivate::updateAllCheckStates);
+
+ // Workaround invisible placeholder text
+ QPalette palette = m_checkStateComboBox->palette();
+ palette.setColor(QPalette::PlaceholderText, palette.color(QPalette::Text));
+ m_checkStateComboBox->setPalette(palette);
+
+ m_checkStateComboBox->setPlaceholderText(ComponentSelectionPage::tr("Select"));
if (m_core->isInstaller()) {
- m_checkDefault->setObjectName(QLatin1String("SelectDefaultComponentsButton"));
- m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+A",
- "Select default components")));
- m_checkDefault->setText(ComponentSelectionPage::tr("Def&ault"));
- m_checkDefault->setToolTip(ComponentSelectionPage::tr("Select default components in the tree view."));
+ m_checkStateComboBox->insertItem(scCheckDefaultIndex, ComponentSelectionPage::tr("Default"));
+ m_checkStateComboBox->setItemData(scCheckDefaultIndex,
+ ComponentSelectionPage::tr("Select default components in the tree view."), Qt::ToolTipRole);
} else {
- m_checkDefault->setEnabled(false);
- m_checkDefault->setObjectName(QLatin1String("ResetComponentsButton"));
- m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+R",
- "Reset to already installed components")));
- m_checkDefault->setText(ComponentSelectionPage::tr("&Reset"));
- m_checkDefault->setToolTip(
- ComponentSelectionPage::tr("Reset all components to their original selection state in the tree view."));
+ m_checkStateComboBox->insertItem(scCheckDefaultIndex, ComponentSelectionPage::tr("Reset"));
+ m_checkStateComboBox->setItemData(scCheckDefaultIndex,
+ ComponentSelectionPage::tr("Reset all components to their original selection state in the tree view."), Qt::ToolTipRole);
}
- buttonHLayout->addWidget(m_checkDefault);
-
- m_checkAll = new QPushButton;
- connect(m_checkAll, &QAbstractButton::clicked,
- this, &ComponentSelectionPagePrivate::selectAll);
- m_checkAll->setObjectName(QLatin1String("SelectAllComponentsButton"));
- m_checkAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+S",
- "Select all components")));
- m_checkAll->setText(ComponentSelectionPage::tr("&Select All"));
- m_checkAll->setToolTip(ComponentSelectionPage::tr("Select all components in the tree view."));
- buttonHLayout->addWidget(m_checkAll);
-
- m_uncheckAll = new QPushButton;
- connect(m_uncheckAll, &QAbstractButton::clicked,
- this, &ComponentSelectionPagePrivate::deselectAll);
- m_uncheckAll->setObjectName(QLatin1String("DeselectAllComponentsButton"));
- m_uncheckAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+D",
- "Deselect all components")));
- m_uncheckAll->setText(ComponentSelectionPage::tr("&Deselect All"));
- m_uncheckAll->setToolTip(ComponentSelectionPage::tr("Deselect all components in the tree view."));
- buttonHLayout->addWidget(m_uncheckAll);
+ m_checkStateComboBox->insertItem(scCheckAllIndex, ComponentSelectionPage::tr("Select All"));
+ m_checkStateComboBox->setItemData(scCheckAllIndex,
+ ComponentSelectionPage::tr("Select all components in the tree view."), Qt::ToolTipRole);
+ m_checkStateComboBox->insertItem(scUncheckAllIndex, ComponentSelectionPage::tr("Deselect All"));
+ m_checkStateComboBox->setItemData(scUncheckAllIndex,
+ ComponentSelectionPage::tr("Deselect all components in the tree view."), Qt::ToolTipRole);
QWidget *progressStackedWidget = new QWidget();
QVBoxLayout *metaLayout = new QVBoxLayout(progressStackedWidget);
@@ -166,17 +199,24 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
connect(m_searchLineEdit, &QLineEdit::textChanged,
this, &ComponentSelectionPagePrivate::setSearchPattern);
connect(q, &ComponentSelectionPage::entered, m_searchLineEdit, &QLineEdit::clear);
+ topHLayout->addWidget(m_searchLineEdit);
QVBoxLayout *treeViewVLayout = new QVBoxLayout;
treeViewVLayout->setObjectName(QLatin1String("TreeviewLayout"));
treeViewVLayout->addWidget(m_treeView, 3);
- treeViewVLayout->addWidget(m_searchLineEdit);
QWidget *mainStackedWidget = new QWidget();
m_mainGLayout = new QGridLayout(mainStackedWidget);
- m_mainGLayout->addLayout(buttonHLayout, 0, 0);
+ {
+ int left = 0;
+ int top = 0;
+ int bottom = 0;
+ m_mainGLayout->getContentsMargins(&left, &top, nullptr, &bottom);
+ m_mainGLayout->setContentsMargins(left, top, 0, bottom);
+ }
+ m_mainGLayout->addLayout(topHLayout, 0, 0);
m_mainGLayout->addLayout(treeViewVLayout, 1, 0);
- m_mainGLayout->addWidget(m_descriptionBaseWidget, 1, 1);
+ m_mainGLayout->addLayout(m_rightSideVLayout, 0, 1, 0, -1);
m_mainGLayout->setColumnStretch(0, 3);
m_mainGLayout->setColumnStretch(1, 2);
@@ -185,23 +225,15 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
m_stackedLayout->addWidget(progressStackedWidget);
m_stackedLayout->setCurrentIndex(0);
- connect(m_allModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
- SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState)));
- connect(m_updaterModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)),
- this, SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState)));
+ connect(m_allModel, &ComponentModel::checkStateChanged,
+ this, &ComponentSelectionPagePrivate::onModelStateChanged);
+ connect(m_updaterModel, &ComponentModel::checkStateChanged,
+ this, &ComponentSelectionPagePrivate::onModelStateChanged);
connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int)));
connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString)));
connect(m_core, &PackageManagerCore::metaJobTotalProgress, this,
&ComponentSelectionPagePrivate::setTotalProgress);
-
- // force a recalculation of components to install to keep the state correct
- connect(q, &ComponentSelectionPage::left,
- m_core, &PackageManagerCore::clearComponentsToInstallCalculated);
-
-#ifdef INSTALLCOMPRESSED
- allowCompressedRepositoryInstall();
-#endif
}
ComponentSelectionPagePrivate::~ComponentSelectionPagePrivate()
@@ -209,36 +241,28 @@ ComponentSelectionPagePrivate::~ComponentSelectionPagePrivate()
}
-void ComponentSelectionPagePrivate::allowCompressedRepositoryInstall()
+void ComponentSelectionPagePrivate::setAllowCreateOfflineInstaller(bool allow)
{
- m_allowCompressedRepositoryInstall = true;
+ m_allowCreateOfflineInstaller = allow;
}
void ComponentSelectionPagePrivate::showCompressedRepositoryButton()
{
- QWizard *wizard = qobject_cast<QWizard*>(m_core->guiObject());
- if (wizard && !(wizard->options() & QWizard::HaveCustomButton2) && m_allowCompressedRepositoryInstall) {
- wizard->setOption(QWizard::HaveCustomButton2, true);
- wizard->setButtonText(QWizard::CustomButton2,
- ComponentSelectionPage::tr("&Browse QBSP files"));
- wizard->button(QWizard::CustomButton2)->setToolTip(
- ComponentSelectionPage::tr("Select a Qt Board Support Package file to install "
- "additional content that is not directly available from the online repositories."));
- connect(wizard, &QWizard::customButtonClicked,
- this, &ComponentSelectionPagePrivate::customButtonClicked);
- q->gui()->updateButtonLayout();
- }
+ if (m_core->allowCompressedRepositoryInstall())
+ m_qbspPushButton->setVisible(true);
}
void ComponentSelectionPagePrivate::hideCompressedRepositoryButton()
{
- QWizard *wizard = qobject_cast<QWizard*>(m_core->guiObject());
- if (wizard && (wizard->options() & QWizard::HaveCustomButton2)) {
- wizard->setOption(QWizard::HaveCustomButton2, false);
- disconnect(wizard, &QWizard::customButtonClicked,
- this, &ComponentSelectionPagePrivate::customButtonClicked);
- q->gui()->updateButtonLayout();
- }
+ m_qbspPushButton->setVisible(false);
+}
+
+void ComponentSelectionPagePrivate::showCreateOfflineInstallerButton(bool show)
+{
+ if (show && m_allowCreateOfflineInstaller)
+ m_createOfflinePushButton->setVisible(m_core->isInstaller() && !m_core->isOfflineOnly());
+ else
+ m_createOfflinePushButton->setVisible(false);
}
void ComponentSelectionPagePrivate::setupCategoryLayout()
@@ -272,7 +296,7 @@ void ComponentSelectionPagePrivate::setupCategoryLayout()
vLayout->addWidget(m_categoryGroupBox);
vLayout->addStretch();
- m_toolBox->insertItem(1, m_categoryWidget, m_core->settings().repositoryCategoryDisplayName());
+ m_tabWidget->insertTab(1, m_categoryWidget, m_core->settings().repositoryCategoryDisplayName());
}
void ComponentSelectionPagePrivate::showCategoryLayout(bool show)
@@ -285,27 +309,27 @@ void ComponentSelectionPagePrivate::showCategoryLayout(bool show)
setupCategoryLayout();
if (show) {
- m_mainGLayout->removeWidget(m_descriptionBaseWidget);
- m_toolBox->insertItem(0, m_descriptionBaseWidget, tr("Component Information"));
- m_mainGLayout->addWidget(m_toolBox, 1, 1);
+ m_rightSideVLayout->removeWidget(m_descriptionBaseWidget);
+ m_tabWidget->insertTab(0, m_descriptionBaseWidget, tr("Information"));
+ m_rightSideVLayout->insertWidget(0, m_tabWidget);
} else {
- m_toolBox->removeItem(0);
- m_mainGLayout->removeWidget(m_toolBox);
- m_mainGLayout->addWidget(m_descriptionBaseWidget, 1, 1);
+ m_tabWidget->removeTab(0);
+ m_rightSideVLayout->removeWidget(m_tabWidget);
+ m_rightSideVLayout->insertWidget(0, m_descriptionBaseWidget);
+ m_descriptionBaseWidget->setVisible(true);
}
- m_toolBox->setVisible(show);
+ m_tabWidget->setVisible(show);
m_categoryLayoutVisible = show;
}
void ComponentSelectionPagePrivate::updateTreeView()
{
- m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager());
+ setComboBoxItemEnabled(scCheckDefaultIndex, m_core->isInstaller() || m_core->isPackageManager());
if (m_treeView->selectionModel()) {
disconnect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ComponentSelectionPagePrivate::currentSelectedChanged);
}
- m_searchLineEdit->setVisible(!m_core->isUpdater());
m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel;
m_proxyModel->setSourceModel(m_currentModel);
m_treeView->setModel(m_proxyModel);
@@ -373,6 +397,9 @@ void ComponentSelectionPagePrivate::expandDefault()
*/
void ComponentSelectionPagePrivate::expandSearchResults()
{
+ // Avoid resizing the sections after each expand of a node
+ storeHeaderResizeModes();
+
// Expand parents of root indexes accepted by filter
const QVector<QModelIndex> acceptedIndexes = m_proxyModel->directlyAcceptedIndexes();
for (auto proxyModelIndex : acceptedIndexes) {
@@ -388,6 +415,16 @@ void ComponentSelectionPagePrivate::expandSearchResults()
index = index.parent();
}
}
+ restoreHeaderResizeModes();
+}
+
+/*!
+ Returns \c true if the components to install and uninstall are calculated
+ successfully, \c false otherwise.
+*/
+bool ComponentSelectionPagePrivate::componentsResolved() const
+{
+ return m_componentsResolved;
}
void ComponentSelectionPagePrivate::currentSelectedChanged(const QModelIndex &current)
@@ -413,6 +450,32 @@ void ComponentSelectionPagePrivate::currentSelectedChanged(const QModelIndex &cu
}
}
+/*!
+ Updates the checkstate of the components based on the value of \c which.
+*/
+void ComponentSelectionPagePrivate::updateAllCheckStates(int which)
+{
+ switch (which) {
+ case scNoCheckSelectionIndex:
+ // A 'helper' text index, no selection
+ return;
+ case scCheckDefaultIndex:
+ selectDefault();
+ break;
+ case scCheckAllIndex:
+ selectAll();
+ break;
+ case scUncheckAllIndex:
+ deselectAll();
+ break;
+ default:
+ qCWarning(lcInstallerInstallLog) << "Invalid index for check state selection!";
+ break;
+ }
+ // Reset back to 'helper' text index
+ m_checkStateComboBox->setCurrentIndex(scNoCheckSelectionIndex);
+}
+
void ComponentSelectionPagePrivate::selectAll()
{
m_currentModel->setCheckedState(ComponentModel::AllChecked);
@@ -423,27 +486,6 @@ void ComponentSelectionPagePrivate::deselectAll()
m_currentModel->setCheckedState(ComponentModel::AllUnchecked);
}
-void ComponentSelectionPagePrivate::enableRepositoryCategory(const QString &repositoryName, bool enable)
-{
- QMap<QString, RepositoryCategory> organizedRepositoryCategories = m_core->settings().organizedRepositoryCategories();
-
- QMap<QString, RepositoryCategory>::iterator i = organizedRepositoryCategories.find(repositoryName);
- RepositoryCategory repoCategory;
- while (i != organizedRepositoryCategories.end() && i.key() == repositoryName) {
- repoCategory = i.value();
- i++;
- }
-
- RepositoryCategory replacement = repoCategory;
- replacement.setEnabled(enable);
- QSet<RepositoryCategory> tmpRepoCategories = m_core->settings().repositoryCategories();
- if (tmpRepoCategories.contains(repoCategory)) {
- tmpRepoCategories.remove(repoCategory);
- tmpRepoCategories.insert(replacement);
- m_core->settings().addRepositoryCategories(tmpRepoCategories);
- }
-}
-
void ComponentSelectionPagePrivate::updateWidgetVisibility(bool show)
{
if (show)
@@ -451,8 +493,12 @@ void ComponentSelectionPagePrivate::updateWidgetVisibility(bool show)
else
m_stackedLayout->setCurrentIndex(0);
- if (QAbstractButton *bspButton = q->gui()->button(QWizard::CustomButton2))
- bspButton->setEnabled(!show);
+ m_qbspPushButton->setEnabled(!show);
+
+ if (show) {
+ q->gui()->button(QWizard::NextButton)->setEnabled(false);
+ q->gui()->button(QWizard::BackButton)->setEnabled(false);
+ }
// In macOS 10.12 the widgets are not hidden if those are not updated immediately
#ifdef Q_OS_MACOS
@@ -467,7 +513,7 @@ void ComponentSelectionPagePrivate::fetchRepositoryCategories()
QList<QCheckBox*> checkboxes = m_categoryGroupBox->findChildren<QCheckBox *>();
for (int i = 0; i < checkboxes.count(); i++) {
QCheckBox *checkbox = checkboxes.at(i);
- enableRepositoryCategory(checkbox->objectName(), checkbox->isChecked());
+ m_core->enableRepositoryCategory(checkbox->objectName(), checkbox->isChecked());
}
if (!m_core->fetchRemotePackagesTree()) {
@@ -478,31 +524,28 @@ void ComponentSelectionPagePrivate::fetchRepositoryCategories()
m_searchLineEdit->text().isEmpty() ? expandDefault() : expandSearchResults();
}
-void ComponentSelectionPagePrivate::customButtonClicked(int which)
+void ComponentSelectionPagePrivate::createOfflineButtonClicked()
{
- if (QWizard::WizardButton(which) == QWizard::CustomButton2) {
- QString defaultDownloadDirectory =
- QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
- QStringList fileNames = QFileDialog::getOpenFileNames(nullptr,
- ComponentSelectionPage::tr("Open File"),defaultDownloadDirectory,
- QLatin1String("QBSP or 7z Files (*.qbsp *.7z)"));
-
- QSet<Repository> set;
- foreach (QString fileName, fileNames) {
- Repository repository = Repository::fromUserInput(fileName, true);
- repository.setEnabled(true);
- set.insert(repository);
- }
- if (set.count() > 0) {
- updateWidgetVisibility(true);
- m_core->settings().addTemporaryRepositories(set, false);
- if (!m_core->fetchCompressedPackagesTree()) {
- MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("FailToFetchPackages"), tr("Error"), m_core->error());
- }
+ m_core->setOfflineGenerator();
+ q->gui()->button(QWizard::NextButton)->click();
+}
+
+void ComponentSelectionPagePrivate::qbspButtonClicked()
+{
+ QString defaultDownloadDirectory =
+ QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+ QStringList fileNames = QFileDialog::getOpenFileNames(nullptr,
+ ComponentSelectionPage::tr("Open File"),defaultDownloadDirectory,
+ QLatin1String("QBSP or 7z Files (*.qbsp *.7z)"));
+
+ if (m_core->addQBspRepositories(fileNames)) {
+ updateWidgetVisibility(true);
+ if (!m_core->fetchCompressedPackagesTree()) {
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
+ QLatin1String("FailToFetchPackages"), tr("Error"), m_core->error());
}
- updateWidgetVisibility(false);
}
+ updateWidgetVisibility(false);
}
/*!
@@ -536,6 +579,21 @@ void ComponentSelectionPagePrivate::selectDefault()
void ComponentSelectionPagePrivate::onModelStateChanged(QInstaller::ComponentModel::ModelState state)
{
+ if (state.testFlag(ComponentModel::Empty)) {
+ setComboBoxItemEnabled(scCheckAllIndex, false);
+ setComboBoxItemEnabled(scUncheckAllIndex, false);
+ setComboBoxItemEnabled(scCheckDefaultIndex, false);
+ return;
+ }
+
+ m_componentsResolved = m_core->recalculateAllComponents();
+ if (!m_componentsResolved) {
+ const QString error = !m_core->componentsToInstallError().isEmpty()
+ ? m_core->componentsToInstallError() : m_core->componentsToUninstallError();
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
+ QLatin1String("CalculateComponentsError"), tr("Error"), error);
+ }
+
q->setModified(state.testFlag(ComponentModel::DefaultChecked) == false);
// If all components in the checked list are only checkable when run without forced
// installation, set ComponentModel::AllUnchecked as well, as we cannot uncheck anything.
@@ -545,9 +603,9 @@ void ComponentSelectionPagePrivate::onModelStateChanged(QInstaller::ComponentMod
state |= ComponentModel::AllUnchecked;
}
// enable the button if the corresponding flag is not set
- m_checkAll->setEnabled(state.testFlag(ComponentModel::AllChecked) == false);
- m_uncheckAll->setEnabled(state.testFlag(ComponentModel::AllUnchecked) == false);
- m_checkDefault->setEnabled(state.testFlag(ComponentModel::DefaultChecked) == false);
+ setComboBoxItemEnabled(scCheckAllIndex, state.testFlag(ComponentModel::AllChecked) == false);
+ setComboBoxItemEnabled(scUncheckAllIndex, state.testFlag(ComponentModel::AllUnchecked) == false);
+ setComboBoxItemEnabled(scCheckDefaultIndex, state.testFlag(ComponentModel::DefaultChecked) == false);
// update the current selected node (important to reflect possible sub-node changes)
if (m_treeView->selectionModel())
@@ -576,4 +634,45 @@ void ComponentSelectionPagePrivate::setSearchPattern(const QString &text)
}
}
+/*!
+ Stores the current resize modes of the tree view header's columns, and sets
+ the new resize modes to \c QHeaderView::Fixed.
+*/
+void ComponentSelectionPagePrivate::storeHeaderResizeModes()
+{
+ m_headerStretchLastSection = m_treeView->header()->stretchLastSection();
+ for (int i = 0; i < ComponentModelHelper::LastColumn; ++i)
+ m_headerResizeModes.insert(i, m_treeView->header()->sectionResizeMode(i));
+
+ m_treeView->header()->setStretchLastSection(false);
+ m_treeView->header()->setSectionResizeMode(QHeaderView::Fixed);
+}
+
+/*!
+ Restores the resize modes of the tree view header's columns, that were
+ stored when calling \l storeHeaderResizeModes().
+*/
+void ComponentSelectionPagePrivate::restoreHeaderResizeModes()
+{
+ m_treeView->header()->setStretchLastSection(m_headerStretchLastSection);
+ for (int i = 0; i < ComponentModelHelper::LastColumn; ++i)
+ m_treeView->header()->setSectionResizeMode(i, m_headerResizeModes.value(i));
+}
+
+/*!
+ Sets the enabled state of the combo box item in \a index to \a enabled.
+*/
+void ComponentSelectionPagePrivate::setComboBoxItemEnabled(int index, bool enabled)
+{
+ auto *model = qobject_cast<QStandardItemModel *>(m_checkStateComboBox->model());
+ if (!model)
+ return;
+
+ QStandardItem *item = model->item(index);
+ if (!item)
+ return;
+
+ item->setEnabled(enabled);
+}
+
} // namespace QInstaller
diff --git a/src/libs/installer/componentselectionpage_p.h b/src/libs/installer/componentselectionpage_p.h
index fc37ebdaa..187fce61d 100644
--- a/src/libs/installer/componentselectionpage_p.h
+++ b/src/libs/installer/componentselectionpage_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,6 +31,7 @@
#include <QObject>
#include <QWidget>
+#include <QHeaderView>
#include "componentmodel.h"
#include "packagemanagergui.h"
@@ -47,13 +48,13 @@ class QVBoxLayout;
class QHBoxLayout;
class QGridLayout;
class QStackedLayout;
-class QToolBox;
namespace QInstaller {
class PackageManagerCore;
class ComponentModel;
class ComponentSelectionPage;
+class CustomComboBox;
class ComponentSelectionPagePrivate : public QObject
{
@@ -65,23 +66,26 @@ public:
explicit ComponentSelectionPagePrivate(ComponentSelectionPage *qq, PackageManagerCore *core);
~ComponentSelectionPagePrivate();
- void allowCompressedRepositoryInstall();
+ void setAllowCreateOfflineInstaller(bool allow);
void showCompressedRepositoryButton();
void hideCompressedRepositoryButton();
+ void showCreateOfflineInstallerButton(bool show);
void setupCategoryLayout();
void showCategoryLayout(bool show);
void updateTreeView();
void expandDefault();
void expandSearchResults();
+ bool componentsResolved() const;
public slots:
void currentSelectedChanged(const QModelIndex &current);
+ void updateAllCheckStates(int which);
void selectAll();
void deselectAll();
- void enableRepositoryCategory(const QString &repositoryName, bool enable);
void updateWidgetVisibility(bool show);
void fetchRepositoryCategories();
- void customButtonClicked(int which);
+ void createOfflineButtonClicked();
+ void qbspButtonClicked();
void onProgressChanged(int progress);
void setMessage(const QString &msg);
void setTotalProgress(int totalProgress);
@@ -90,22 +94,28 @@ public slots:
void setSearchPattern(const QString &text);
private:
+ void storeHeaderResizeModes();
+ void restoreHeaderResizeModes();
+ void setComboBoxItemEnabled(int index, bool enabled);
+
+private:
ComponentSelectionPage *q;
PackageManagerCore *m_core;
QTreeView *m_treeView;
- QToolBox *m_toolBox;
+ QTabWidget *m_tabWidget;
QWidget *m_descriptionBaseWidget;
QLabel *m_sizeLabel;
QLabel *m_descriptionLabel;
- QPushButton *m_checkAll;
- QPushButton *m_uncheckAll;
- QPushButton *m_checkDefault;
+ QPushButton *m_createOfflinePushButton;
+ QPushButton *m_qbspPushButton;
+ CustomComboBox *m_checkStateComboBox;
QWidget *m_categoryWidget;
QGroupBox *m_categoryGroupBox;
QLabel *m_metadataProgressLabel;
QProgressBar *m_progressBar;
QGridLayout *m_mainGLayout;
- bool m_allowCompressedRepositoryInstall;
+ QVBoxLayout *m_rightSideVLayout;
+ bool m_allowCreateOfflineInstaller;
bool m_categoryLayoutVisible;
ComponentModel *m_allModel;
ComponentModel *m_updaterModel;
@@ -113,6 +123,10 @@ private:
QStackedLayout *m_stackedLayout;
ComponentSortFilterProxyModel *m_proxyModel;
QLineEdit *m_searchLineEdit;
+ bool m_componentsResolved;
+
+ bool m_headerStretchLastSection;
+ QHash<int, QHeaderView::ResizeMode> m_headerResizeModes;
};
} // namespace QInstaller
diff --git a/src/libs/installer/componentsortfilterproxymodel.cpp b/src/libs/installer/componentsortfilterproxymodel.cpp
index ab736a7c9..9308d2356 100644
--- a/src/libs/installer/componentsortfilterproxymodel.cpp
+++ b/src/libs/installer/componentsortfilterproxymodel.cpp
@@ -51,7 +51,7 @@ namespace QInstaller {
Index was accepted directly by filter.
\value Descendant
Index is a descendant of an accepted index.
- \value Reject
+ \value Rejected
Index was not accepted by filter.
*/
diff --git a/src/libs/installer/componentsortfilterproxymodel.h b/src/libs/installer/componentsortfilterproxymodel.h
index a6167d17b..12fd0a627 100644
--- a/src/libs/installer/componentsortfilterproxymodel.h
+++ b/src/libs/installer/componentsortfilterproxymodel.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -51,7 +51,7 @@ public:
QVector<QModelIndex> directlyAcceptedIndexes() const;
protected:
- bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
private:
bool acceptsRow(int sourceRow, const QModelIndex &sourceParent, AcceptType *type = nullptr) const;
diff --git a/src/libs/installer/concurrentoperationrunner.cpp b/src/libs/installer/concurrentoperationrunner.cpp
new file mode 100644
index 000000000..b0eb5f582
--- /dev/null
+++ b/src/libs/installer/concurrentoperationrunner.cpp
@@ -0,0 +1,279 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "concurrentoperationrunner.h"
+
+#include "errors.h"
+#include "operationtracer.h"
+
+#include <QtConcurrent>
+
+using namespace QInstaller;
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::ConcurrentOperationRunner
+ \brief The ConcurrentOperationRunner class can be used to perform installer
+ operations concurrently.
+
+ The class accepts an operation list of any registered operation type. It can be
+ used to execute the \c Backup, \c Perform, or \c Undo steps of the operations. The
+ operations are run in a separate thread pool of this class, which by default limits
+ the maximum number of threads to the ideal number of logical processor cores in the
+ system.
+*/
+
+/*!
+ \fn QInstaller::ConcurrentOperationRunner::operationStarted(QInstaller::Operation *operation)
+
+ Emitted when the execution of \a operation is started.
+*/
+
+/*!
+ \fn QInstaller::ConcurrentOperationRunner::finished()
+
+ Emitted when the execution of all pooled operations is finished.
+*/
+
+/*!
+ \fn QInstaller::ConcurrentOperationRunner::progressChanged(const int completed, const int total)
+
+ Emitted when the count of \a completed of the \a total operations changes.
+*/
+
+/*!
+ Constructs an operation runner with \a parent as the parent object.
+*/
+ConcurrentOperationRunner::ConcurrentOperationRunner(QObject *parent)
+ : QObject(parent)
+ , m_completedOperations(0)
+ , m_totalOperations(0)
+ , m_operations(nullptr)
+ , m_type(Operation::OperationType::Perform)
+ , m_threadPool(new QThreadPool(this))
+{
+ connect(this, &ConcurrentOperationRunner::operationStarted,
+ this, &ConcurrentOperationRunner::onOperationStarted);
+}
+
+/*!
+ Constructs an operation runner with \a operations of type \a type to be performed,
+ and \a parent as the parent object.
+*/
+ConcurrentOperationRunner::ConcurrentOperationRunner(OperationList *operations,
+ const Operation::OperationType type, QObject *parent)
+ : QObject(parent)
+ , m_completedOperations(0)
+ , m_totalOperations(0)
+ , m_operations(operations)
+ , m_type(type)
+ , m_threadPool(new QThreadPool(this))
+{
+ m_totalOperations = m_operations->size();
+
+ connect(this, &ConcurrentOperationRunner::operationStarted,
+ this, &ConcurrentOperationRunner::onOperationStarted);
+}
+
+/*!
+ Destroys the instance and releases resources.
+*/
+ConcurrentOperationRunner::~ConcurrentOperationRunner()
+{
+ qDeleteAll(m_operationWatchers);
+}
+
+/*!
+ Sets the list of operations to be performed to \a operations.
+*/
+void ConcurrentOperationRunner::setOperations(OperationList *operations)
+{
+ m_operations = operations;
+ m_totalOperations = m_operations->size();
+}
+
+/*!
+ Sets \a type of operations to be performed. This can be either
+ \c Backup, \c Perform, or \c Undo.
+*/
+void ConcurrentOperationRunner::setType(const Operation::OperationType type)
+{
+ m_type = type;
+}
+
+/*!
+ Sets the maximum \a count of threads used by the thread pool of this class.
+ A value of \c 0 sets the count automatically to ideal number of threads.
+*/
+void ConcurrentOperationRunner::setMaxThreadCount(int count)
+{
+ if (count == 0) {
+ m_threadPool->setMaxThreadCount(QThread::idealThreadCount());
+ return;
+ }
+ m_threadPool->setMaxThreadCount(count);
+}
+
+/*!
+ Performs the current operations. Returns a hash of pointers to the performed operation
+ objects and their results. The result is a boolean value.
+*/
+QHash<Operation *, bool> ConcurrentOperationRunner::run()
+{
+ reset();
+
+ QEventLoop loop;
+ for (auto &operation : qAsConst(*m_operations)) {
+ auto futureWatcher = new QFutureWatcher<bool>();
+ m_operationWatchers.insert(operation, futureWatcher);
+
+ connect(futureWatcher, &QFutureWatcher<bool>::finished,
+ this, &ConcurrentOperationRunner::onOperationfinished);
+
+ futureWatcher->setFuture(QtConcurrent::run(m_threadPool,
+ [this, operation] { return runOperation(operation); }));
+ }
+
+ if (!m_operationWatchers.isEmpty()) {
+ connect(this, &ConcurrentOperationRunner::finished, &loop, &QEventLoop::quit);
+ loop.exec();
+ }
+
+ return m_results;
+}
+
+/*!
+ Cancels operations pending for an asynchronous run.
+
+ \note This does not stop already running operations, which
+ should provide a separate mechanism for canceling.
+*/
+void ConcurrentOperationRunner::cancel()
+{
+ for (auto &watcher : m_operationWatchers)
+ watcher->cancel();
+}
+
+/*!
+ \internal
+
+ Invoked when the execution of the \a operation has started. Adds console
+ output trace for the operation.
+*/
+void ConcurrentOperationRunner::onOperationStarted(Operation *operation)
+{
+ ConcurrentOperationTracer tracer(operation);
+
+ switch (m_type) {
+ case Operation::Backup:
+ tracer.trace(QLatin1String("backup"));
+ break;
+ case Operation::Perform:
+ tracer.trace(QLatin1String("perform"));
+ break;
+ case Operation::Undo:
+ tracer.trace(QLatin1String("undo"));
+ break;
+ default:
+ Q_ASSERT(!"Unexpected operation type");
+ }
+}
+
+/*!
+ \internal
+
+ Invoked when the execution of a single operation finishes. Adds the result
+ of the operation to the return hash of \c ConcurrentOperationRunner::run().
+*/
+void ConcurrentOperationRunner::onOperationfinished()
+{
+ auto watcher = static_cast<QFutureWatcher<bool> *>(sender());
+
+ Operation *op = m_operationWatchers.key(watcher);
+ if (!watcher->isCanceled()) {
+ try {
+ // Catch transferred exceptions
+ m_results.insert(op, watcher->future().result());
+ } catch (const Error &e) {
+ qCritical() << "Caught exception:" << e.message();
+ m_results.insert(op, false);
+ } catch (const QUnhandledException &) {
+ qCritical() << "Caught unhandled exception in:" << Q_FUNC_INFO;
+ m_results.insert(op, false);
+ }
+ ++m_completedOperations;
+ emit progressChanged(m_completedOperations, m_totalOperations);
+
+ } else {
+ // Remember also operations canceled before execution
+ m_results.insert(op, false);
+ }
+
+ delete m_operationWatchers.take(op);
+
+ // All finished
+ if (m_operationWatchers.isEmpty())
+ emit finished();
+}
+
+/*!
+ \internal
+
+ Runs \a operation. Returns \c true on success, \c false otherwise.
+*/
+bool ConcurrentOperationRunner::runOperation(Operation *const operation)
+{
+ emit operationStarted(operation);
+
+ switch (m_type) {
+ case Operation::Backup:
+ operation->backup();
+ return true;
+ case Operation::Perform:
+ return operation->performOperation();
+ case Operation::Undo:
+ return operation->undoOperation();
+ default:
+ Q_ASSERT(!"Unexpected operation type");
+ }
+ return false;
+}
+
+/*!
+ \internal
+
+ Clears previous results and deletes remaining operation watchers.
+*/
+void ConcurrentOperationRunner::reset()
+{
+ qDeleteAll(m_operationWatchers);
+ m_operationWatchers.clear();
+ m_results.clear();
+
+ m_completedOperations = 0;
+}
diff --git a/src/libs/installer/concurrentoperationrunner.h b/src/libs/installer/concurrentoperationrunner.h
new file mode 100644
index 000000000..436a2baef
--- /dev/null
+++ b/src/libs/installer/concurrentoperationrunner.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef CONCURRENTOPERATIONRUNNER_H
+#define CONCURRENTOPERATIONRUNNER_H
+
+#include "qinstallerglobal.h"
+
+#include <QObject>
+#include <QHash>
+#include <QFutureWatcher>
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT ConcurrentOperationRunner : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ConcurrentOperationRunner)
+
+public:
+ explicit ConcurrentOperationRunner(QObject *parent = nullptr);
+ explicit ConcurrentOperationRunner(OperationList *operations,
+ const Operation::OperationType type, QObject *parent = nullptr);
+ ~ConcurrentOperationRunner();
+
+ void setOperations(OperationList *operations);
+ void setType(const Operation::OperationType type);
+ void setMaxThreadCount(int count);
+
+ QHash<Operation *, bool> run();
+
+signals:
+ void operationStarted(QInstaller::Operation *operation);
+ void progressChanged(const int completed, const int total);
+ void finished();
+
+public slots:
+ void cancel();
+
+private slots:
+ void onOperationStarted(QInstaller::Operation *operation);
+ void onOperationfinished();
+
+private:
+ bool runOperation(Operation *const operation);
+ void reset();
+
+private:
+ int m_completedOperations;
+ int m_totalOperations;
+
+ QHash<Operation *, QFutureWatcher<bool> *> m_operationWatchers;
+ QHash<Operation *, bool> m_results;
+
+ OperationList *m_operations;
+ Operation::OperationType m_type;
+
+ QThreadPool *const m_threadPool;
+};
+
+} // namespace QInstaller
+
+#endif // CONCURRENTOPERATIONRUNNER_H
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index 61efe98a8..7bf816b5f 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -41,6 +41,7 @@ static const QLatin1String scScript("script");
static const QLatin1String scAllUsersStartMenuProgramsPath("AllUsersStartMenuProgramsPath");
static const QLatin1String scUserStartMenuProgramsPath("UserStartMenuProgramsPath");
static const QLatin1String scUILanguage("UILanguage");
+static const QLatin1String scUpdatesXML("Updates.xml");
static const QLatin1String scName("Name");
static const QLatin1String scVersion("Version");
@@ -57,7 +58,14 @@ static const QLatin1String scReleaseDate("ReleaseDate");
static const QLatin1String scDescription("Description");
static const QLatin1String scDisplayName("DisplayName");
static const QLatin1String scTreeName("TreeName");
+static const QLatin1String scAutoTreeName("AutoTreeName");
static const QLatin1String scDependencies("Dependencies");
+static const QLatin1String scAlias("Alias");
+static const QLatin1String scRequiredAliases("RequiredAliases");
+static const QLatin1String scRequiredComponents("RequiredComponents");
+static const QLatin1String scOptionalAliases("OptionalAliases");
+static const QLatin1String scOptionalComponents("OptionalComponents");
+static const QLatin1String scLocalDependencies("LocalDependencies");
static const QLatin1String scAutoDependOn("AutoDependOn");
static const QLatin1String scNewComponent("NewComponent");
static const QLatin1String scRepositories("Repositories");
@@ -68,12 +76,68 @@ static const QLatin1String scUncompressedSizeSum("UncompressedSizeSum");
static const QLatin1String scRequiresAdminRights("RequiresAdminRights");
static const QLatin1String scOfflineBinaryName("OfflineBinaryName");
static const QLatin1String scSHA1("SHA1");
+static const QLatin1String scMetadataName("MetadataName");
static const QLatin1String scContentSha1("ContentSha1");
+static const QLatin1String scCheckSha1CheckSum("CheckSha1CheckSum");
+
+static const char * const scClearCacheHint = QT_TR_NOOP(
+ "This may be solved by restarting the application after clearing the cache from:");
+
+// symbols
+static const QLatin1String scCaretSymbol("^");
+static const QLatin1String scCommaWithSpace(", ");
+static const QLatin1String scBr("<br>");
// constants used throughout the components class
static const QLatin1String scVirtual("Virtual");
static const QLatin1String scSortingPriority("SortingPriority");
static const QLatin1String scCheckable("Checkable");
+static const QLatin1String scScriptTag("Script");
+static const QLatin1String scInstalled("Installed");
+static const QLatin1String scUpdateText("UpdateText");
+static const QLatin1String scUninstalled("Uninstalled");
+static const QLatin1String scCurrentState("CurrentState");
+static const QLatin1String scForcedInstallation("ForcedInstallation");
+static const QLatin1String scExpandedByDefault("ExpandedByDefault");
+static const QLatin1String scUnstable("Unstable");
+static const QLatin1String scTargetDirPlaceholder("@TargetDir@");
+static const QLatin1String scTargetDirPlaceholderWithArg("@TargetDir@%1");
+static const QLatin1String scLastUpdateDate("LastUpdateDate");
+static const QLatin1String scInstallDate("InstallDate");
+static const QLatin1String scUserInterfaces("UserInterfaces");
+static const QLatin1String scTranslations("Translations");
+static const QLatin1String scLicenses("Licenses");
+static const QLatin1String scLicensesValue("licenses");
+static const QLatin1String scLicense("License");
+static const QLatin1String scOperations("Operations");
+static const QLatin1String scInstallScript("installScript");
+static const QLatin1String scPostLoadScript("postLoadScript");
+static const QLatin1String scComponent("Component");
+static const QLatin1String scComponentSmall("component");
+static const QLatin1String scRetranslateUi("retranslateUi");
+static const QLatin1String scEn("en");
+static const QLatin1String scIfw_("ifw_");
+static const QLatin1String scFile("file");
+static const QLatin1String scContent("content");
+static const QLatin1String scExtract("Extract");
+static const QLatin1String scSha1("sha1");
+static const QLatin1String scCreateOperationsForPath("createOperationsForPath");
+static const QLatin1String scCreateOperationsForArchive("createOperationsForArchive");
+static const QLatin1String scCreateOperations("createOperations");
+static const QLatin1String scBeginInstallation("beginInstallation");
+static const QLatin1String scMinimumProgress("MinimumProgress");
+static const QLatin1String scDelete("Delete");
+static const QLatin1String scCopy("Copy");
+static const QLatin1String scMkdir("Mkdir");
+static const QLatin1String scIsDefault("isDefault");
+static const QLatin1String scAdmin("admin");
+static const QLatin1String scTwoArgs("%1/%2/");
+static const QLatin1String scThreeArgs("%1/%2/%3");
+static const QLatin1String scComponentScriptTest("var component = installer.componentByName('%1'); component.name;");
+static const QLatin1String scInstallerPrefix("installer://");
+static const QLatin1String scInstallerPrefixWithOneArgs("installer://%1/");
+static const QLatin1String scInstallerPrefixWithTwoArgs("installer://%1/%2");
+static const QLatin1String scLocalesArgs("%1%2_%3.%4");
// constants used throughout the settings and package manager core class
static const QLatin1String scTitle("Title");
@@ -82,6 +146,8 @@ static const QLatin1String scRunProgram("RunProgram");
static const QLatin1String scRunProgramArguments("RunProgramArguments");
static const QLatin1String scStartMenuDir("StartMenuDir");
static const QLatin1String scRemoveTargetDir("RemoveTargetDir");
+static const QLatin1String scLocalCacheDir("LocalCacheDir");
+static const QLatin1String scPersistentLocalCache("PersistentLocalCache");
static const QLatin1String scRunProgramDescription("RunProgramDescription");
static const QLatin1String scTargetConfigurationFile("TargetConfigurationFile");
static const QLatin1String scAllowNonAsciiCharacters("AllowNonAsciiCharacters");
@@ -91,6 +157,7 @@ static const QLatin1String scRemoteRepositories("RemoteRepositories");
static const QLatin1String scRepositoryCategories("RepositoryCategories");
static const QLatin1String scRepositorySettingsPageVisible("RepositorySettingsPageVisible");
static const QLatin1String scAllowSpaceInPath("AllowSpaceInPath");
+static const QLatin1String scAllowRepositoriesForOfflineInstaller("AllowRepositoriesForOfflineInstaller");
static const QLatin1String scWizardStyle("WizardStyle");
static const QLatin1String scStyleSheet("StyleSheet");
static const QLatin1String scTitleColor("TitleColor");
@@ -113,7 +180,15 @@ static const QLatin1String scBanner("Banner");
static const QLatin1String scLogo("Logo");
static const QLatin1String scBackground("Background");
static const QLatin1String scPageListPixmap("PageListPixmap");
+static const QLatin1String scAliasDefinitionsFile("AliasDefinitionsFile");
const char scRelocatable[] = "@RELOCATABLE_PATH@";
+
+static const QStringList scMetaElements = {
+ QLatin1String("Script"),
+ QLatin1String("Licenses"),
+ QLatin1String("UserInterfaces"),
+ QLatin1String("Translations")
+};
}
namespace CommandLineOptions {
@@ -145,6 +220,8 @@ static const QLatin1String scSearchShort("se");
static const QLatin1String scSearchLong("search");
static const QLatin1String scCreateOfflineShort("co");
static const QLatin1String scCreateOfflineLong("create-offline");
+static const QLatin1String scClearCacheShort("cc");
+static const QLatin1String scClearCacheLong("clear-cache");
static const QLatin1String scPurgeShort("pr");
static const QLatin1String scPurgeLong("purge");
@@ -206,6 +283,9 @@ static const QLatin1String scNoDefaultInstallationShort("nd");
static const QLatin1String scNoDefaultInstallationLong("no-default-installations");
static const QLatin1String scFilterPackagesShort("fp");
static const QLatin1String scFilterPackagesLong("filter-packages");
+static const QLatin1String scLocalCachePathShort("cp");
+static const QLatin1String scLocalCachePathLong("cache-path");
+static const QLatin1String scTypeLong("type");
// Developer options
static const QLatin1String scScriptShort("s");
@@ -216,6 +296,10 @@ static const QLatin1String scStartClientShort("sc");
static const QLatin1String scStartClientLong("start-client");
static const QLatin1String scSquishPortShort("q");
static const QLatin1String scSquishPortLong("squish-port");
+static const QLatin1String scMaxConcurrentOperationsShort("mco");
+static const QLatin1String scMaxConcurrentOperationsLong("max-concurrent-operations");
+static const QLatin1String scCleanupUpdate("cleanup-update");
+static const QLatin1String scCleanupUpdateOnly("cleanup-update-only");
// Deprecated options, provided only for backward compatibility
static const QLatin1String scDeprecatedUpdater("updater");
@@ -238,7 +322,9 @@ static const QStringList scCommandLineInterfaceOptions = {
scCreateOfflineShort,
scCreateOfflineLong,
scPurgeShort,
- scPurgeLong
+ scPurgeLong,
+ scClearCacheShort,
+ scClearCacheLong
};
} // namespace CommandLineOptions
diff --git a/src/libs/installer/consumeoutputoperation.cpp b/src/libs/installer/consumeoutputoperation.cpp
index 7b1b22946..e9b8d1295 100644
--- a/src/libs/installer/consumeoutputoperation.cpp
+++ b/src/libs/installer/consumeoutputoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -81,19 +81,7 @@ bool ConsumeOutputOperation::performOperation()
return false;
}
- QString executablePath = arguments().at(1);
- QFileInfo executable(executablePath);
-#ifdef Q_OS_WIN
- if (!executable.exists() && executable.suffix().isEmpty())
- executable = QFileInfo(executablePath + QLatin1String(".exe"));
-#endif
-
- if (!executable.exists() || !executable.isExecutable()) {
- setError(UserDefinedError);
- setErrorString(tr("File \"%1\" does not exist or is not an executable binary.").arg(
- QDir::toNativeSeparators(executable.absoluteFilePath())));
- return false;
- }
+ QString executable = arguments().at(1);
QByteArray executableOutput;
@@ -103,17 +91,17 @@ bool ConsumeOutputOperation::performOperation()
int waitCount = 0;
while (executableOutput.isEmpty() && waitCount < 3) {
QProcess process;
- process.start(executable.absoluteFilePath(), processArguments, QIODevice::ReadOnly);
+ process.start(executable, processArguments, QIODevice::ReadOnly);
if (process.waitForFinished(10000)) {
if (process.exitStatus() == QProcess::CrashExit) {
- qCWarning(QInstaller::lcInstallerInstallLog) << executable.absoluteFilePath()
+ qCWarning(QInstaller::lcInstallerInstallLog) << executable
<< processArguments << "crashed with exit code"
<< process.exitCode() << "standard output: "
<< process.readAllStandardOutput() << "error output: "
<< process.readAllStandardError();
setError(UserDefinedError);
- setErrorString(tr("Running \"%1\" resulted in a crash.").arg(
- QDir::toNativeSeparators(executable.absoluteFilePath())));
+ setErrorString(tr("Failed to run command: \"%1\": %2").arg(
+ QDir::toNativeSeparators(executable), process.errorString()));
return false;
}
executableOutput.append(process.readAllStandardOutput());
@@ -124,7 +112,7 @@ bool ConsumeOutputOperation::performOperation()
uiDetachedWait(waitTimeInMilliSeconds);
}
if (process.state() > QProcess::NotRunning ) {
- qCWarning(QInstaller::lcInstallerInstallLog) << executable.absoluteFilePath()
+ qCWarning(QInstaller::lcInstallerInstallLog) << executable
<< "process is still running, need to kill it.";
process.kill();
}
@@ -132,9 +120,9 @@ bool ConsumeOutputOperation::performOperation()
}
if (executableOutput.isEmpty()) {
qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot get any query output from executable"
- << executable.absoluteFilePath();
+ << executable;
}
- core->setValue(installerKeyName, QString::fromLocal8Bit(executableOutput));
+ core->setValue(installerKeyName, QString::fromLocal8Bit(executableOutput.trimmed()));
return true;
}
diff --git a/src/libs/installer/consumeoutputoperation.h b/src/libs/installer/consumeoutputoperation.h
index a1f8a09ff..05f6425f3 100644
--- a/src/libs/installer/consumeoutputoperation.h
+++ b/src/libs/installer/consumeoutputoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT ConsumeOutputOperation : public Operation
public:
explicit ConsumeOutputOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
private:
};
diff --git a/src/libs/installer/copydirectoryoperation.cpp b/src/libs/installer/copydirectoryoperation.cpp
index a2ef2cf5a..c0fec0649 100644
--- a/src/libs/installer/copydirectoryoperation.cpp
+++ b/src/libs/installer/copydirectoryoperation.cpp
@@ -153,7 +153,7 @@ bool CopyDirectoryOperation::performOperation()
bool CopyDirectoryOperation::undoOperation()
{
- if (parseUndoOperationArguments().count() > 0)
+ if (skipUndoOperation())
return true;
if (!checkArgumentCount(2))
diff --git a/src/libs/installer/copydirectoryoperation.h b/src/libs/installer/copydirectoryoperation.h
index f934f8b91..2e96144d1 100644
--- a/src/libs/installer/copydirectoryoperation.h
+++ b/src/libs/installer/copydirectoryoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -42,10 +42,10 @@ class INSTALLER_EXPORT CopyDirectoryOperation : public QObject, public Operation
public:
explicit CopyDirectoryOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/copyfiletask.cpp b/src/libs/installer/copyfiletask.cpp
index 72b28d896..856feda01 100644
--- a/src/libs/installer/copyfiletask.cpp
+++ b/src/libs/installer/copyfiletask.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -112,7 +112,7 @@ void CopyFileTask::doTask(QFutureInterface<FileTaskResult> &fi)
observer.addSample(read);
observer.timerEvent(nullptr);
observer.addBytesTransfered(read);
- observer.addCheckSumData(buffer.data(), read);
+ observer.addCheckSumData(buffer.left(read));
fi.setProgressValueAndText(observer.progressValue(), observer.progressText());
}
diff --git a/src/libs/installer/copyfiletask.h b/src/libs/installer/copyfiletask.h
index cad3b6fcd..0f06ba871 100644
--- a/src/libs/installer/copyfiletask.h
+++ b/src/libs/installer/copyfiletask.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -45,7 +45,7 @@ public:
explicit CopyFileTask(const QString &source);
CopyFileTask(const QString &source, const QString &target);
- void doTask(QFutureInterface<FileTaskResult> &fi);
+ void doTask(QFutureInterface<FileTaskResult> &fi) override;
};
} // namespace QInstaller
diff --git a/src/libs/installer/createdesktopentryoperation.cpp b/src/libs/installer/createdesktopentryoperation.cpp
index 1a56c193c..a19fd773a 100644
--- a/src/libs/installer/createdesktopentryoperation.cpp
+++ b/src/libs/installer/createdesktopentryoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,7 @@
#include "globals.h"
#include "adminauthorization.h"
#include "remoteclient.h"
+#include "packagemanagercore.h"
#include <QDir>
#include <QFile>
@@ -60,11 +61,11 @@ QString CreateDesktopEntryOperation::absoluteFileName()
QStringList XDG_DATA_HOME = QString::fromLocal8Bit(qgetenv("XDG_DATA_HOME"))
.split(QLatin1Char(':'),
- QString::SkipEmptyParts);
+ Qt::SkipEmptyParts);
XDG_DATA_HOME.push_back(QDir::home().absoluteFilePath(QLatin1String(".local/share"))); // default user-specific path
- if (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive())
+ if (packageManager() && packageManager()->hasAdminRights())
XDG_DATA_HOME.push_front(QLatin1String("/usr/local/share")); // default system-wide path
const QStringList directories = XDG_DATA_HOME;
@@ -151,15 +152,16 @@ bool CreateDesktopEntryOperation::performOperation()
setDefaultFilePermissions(filename, DefaultFilePermissions::Executable);
- QTextStream stream(&file);
- stream.setCodec("UTF-8");
- stream << QLatin1String("[Desktop Entry]") << endl;
+ QString outString;
+ QTextStream stream(&outString);
+ stream << QLatin1String("[Desktop Entry]") << Qt::endl;
// Type=Application\nExec=qtcreator\nPath=...
const QStringList pairs = values.split(QLatin1Char('\n'));
for (QStringList::const_iterator it = pairs.begin(); it != pairs.end(); ++it)
- stream << *it << endl;
+ stream << *it << Qt::endl;
+ file.write(outString.toUtf8());
return true;
}
diff --git a/src/libs/installer/createdesktopentryoperation.h b/src/libs/installer/createdesktopentryoperation.h
index 793d1db16..be3b088b2 100644
--- a/src/libs/installer/createdesktopentryoperation.h
+++ b/src/libs/installer/createdesktopentryoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,10 +40,10 @@ public:
explicit CreateDesktopEntryOperation(PackageManagerCore *core);
~CreateDesktopEntryOperation();
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
QString absoluteFileName();
};
diff --git a/src/libs/installer/createlinkoperation.cpp b/src/libs/installer/createlinkoperation.cpp
index 3f29367b6..65ff8fc5d 100644
--- a/src/libs/installer/createlinkoperation.cpp
+++ b/src/libs/installer/createlinkoperation.cpp
@@ -88,7 +88,7 @@ bool CreateLinkOperation::undoOperation()
return false;
}
- return !QFileInfo(linkPath).exists();
+ return !QFileInfo::exists(linkPath);
}
bool CreateLinkOperation::testOperation()
diff --git a/src/libs/installer/createlinkoperation.h b/src/libs/installer/createlinkoperation.h
index 2e4ece9aa..b864f0e34 100644
--- a/src/libs/installer/createlinkoperation.h
+++ b/src/libs/installer/createlinkoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT CreateLinkOperation : public Operation
public:
explicit CreateLinkOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
}
diff --git a/src/libs/installer/createlocalrepositoryoperation.cpp b/src/libs/installer/createlocalrepositoryoperation.cpp
index 576e4fa3d..286cc9b5b 100644
--- a/src/libs/installer/createlocalrepositoryoperation.cpp
+++ b/src/libs/installer/createlocalrepositoryoperation.cpp
@@ -34,7 +34,7 @@
#include "fileio.h"
#include "fileutils.h"
#include "copydirectoryoperation.h"
-#include "lib7zarchive.h"
+#include "archivefactory.h"
#include "packagemanagercore.h"
#include "productkeycheck.h"
#include "constants.h"
@@ -124,12 +124,16 @@ static QString createArchive(const QString repoPath, const QString &sourceDir, c
QFile archive(repoPath + fileName);
- Lib7zArchive archiveFile(archive.fileName());
- if (!(archiveFile.open(QIODevice::WriteOnly) && archiveFile.create(QStringList() << sourceDir))) {
+ QScopedPointer<AbstractArchive> archiveFile(ArchiveFactory::instance().create(archive.fileName()));
+ if (!archiveFile) {
+ throw Error(CreateLocalRepositoryOperation::tr("Unsupported archive \"%1\": no handler "
+ "registered for file suffix \"%2\".").arg(archive.fileName(), QFileInfo(archive.fileName()).suffix()));
+ }
+ if (!(archiveFile->open(QIODevice::WriteOnly) && archiveFile->create(QStringList() << sourceDir))) {
throw Error(CreateLocalRepositoryOperation::tr("Cannot create archive \"%1\": %2")
- .arg(QDir::toNativeSeparators(archive.fileName()), archiveFile.errorString()));
+ .arg(QDir::toNativeSeparators(archive.fileName()), archiveFile->errorString()));
}
- archiveFile.close();
+ archiveFile->close();
removeFiles(sourceDir, helper); // cleanup the files we compressed
if (!archive.rename(sourceDir + fileName)) {
throw Error(CreateLocalRepositoryOperation::tr("Cannot move file \"%1\" to \"%2\": %3")
@@ -374,7 +378,7 @@ bool CreateLocalRepositoryOperation::performOperation()
bool CreateLocalRepositoryOperation::undoOperation()
{
- if (parseUndoOperationArguments().count() > 0)
+ if (skipUndoOperation())
return true;
if (!checkArgumentCount(2))
diff --git a/src/libs/installer/createlocalrepositoryoperation.h b/src/libs/installer/createlocalrepositoryoperation.h
index 275d7a409..c4b9264bc 100644
--- a/src/libs/installer/createlocalrepositoryoperation.h
+++ b/src/libs/installer/createlocalrepositoryoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -43,10 +43,10 @@ class INSTALLER_EXPORT CreateLocalRepositoryOperation : public QObject, public O
public:
explicit CreateLocalRepositoryOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
signals:
void progressChanged(double progress);
diff --git a/src/libs/installer/createshortcutoperation.cpp b/src/libs/installer/createshortcutoperation.cpp
index 57f901c2f..894b5843b 100644
--- a/src/libs/installer/createshortcutoperation.cpp
+++ b/src/libs/installer/createshortcutoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -110,6 +110,7 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
IUnknown *iunkn = nullptr;
if (fileName.toLower().startsWith(QLatin1String("http:"))
+ || fileName.toLower().startsWith(QLatin1String("https:"))
|| fileName.toLower().startsWith(QLatin1String("ftp:"))) {
IUniformResourceLocator *iurl = nullptr;
if (FAILED(CoCreateInstance(CLSID_InternetShortcut, nullptr, CLSCTX_INPROC_SERVER,
@@ -176,6 +177,7 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
Q_UNUSED(linkName)
Q_UNUSED(iconPath)
Q_UNUSED(iconId)
+ Q_UNUSED(description)
return true;
#endif
}
diff --git a/src/libs/installer/createshortcutoperation.h b/src/libs/installer/createshortcutoperation.h
index 9bf9ebdcb..e8276e976 100644
--- a/src/libs/installer/createshortcutoperation.h
+++ b/src/libs/installer/createshortcutoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT CreateShortcutOperation : public Operation
public:
explicit CreateShortcutOperation(PackageManagerCore *core = nullptr);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
private:
void ensureOptionalArgumentsRead();
diff --git a/src/libs/installer/customcombobox.cpp b/src/libs/installer/customcombobox.cpp
new file mode 100644
index 000000000..998364fe4
--- /dev/null
+++ b/src/libs/installer/customcombobox.cpp
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "customcombobox.h"
+
+#include <QStylePainter>
+
+using namespace QInstaller;
+
+CustomComboBox::CustomComboBox(QWidget *parent)
+ : QComboBox(parent)
+{
+}
+
+void CustomComboBox::paintEvent(QPaintEvent *e)
+{
+ if (currentIndex() < 0 && !placeholderText().isEmpty()) {
+ QStylePainter painter(this);
+ painter.setPen(palette().color(QPalette::Text));
+ QStyleOptionComboBox opt;
+ initStyleOption(&opt);
+ painter.drawComplexControl(QStyle::CC_ComboBox, opt);
+ opt.palette.setBrush(QPalette::ButtonText, opt.palette.placeholderText());
+ opt.currentText = placeholderText();
+ painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
+ } else {
+ QComboBox::paintEvent(e);
+ }
+}
diff --git a/src/libs/installer/customcombobox.h b/src/libs/installer/customcombobox.h
new file mode 100644
index 000000000..e022da5a8
--- /dev/null
+++ b/src/libs/installer/customcombobox.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef CUSTOMCOMBOBOX_H
+#define CUSTOMCOMBOBOX_H
+
+#include <QComboBox>
+
+namespace QInstaller {
+
+class CustomComboBox : public QComboBox
+{
+ Q_OBJECT
+public:
+ CustomComboBox(QWidget *parent = nullptr);
+
+protected:
+ void paintEvent(QPaintEvent *e) override;
+};
+
+} // namespace QInstaller
+
+#endif // CUSTOMCOMBOBOX_H
diff --git a/src/libs/installer/directoryguard.cpp b/src/libs/installer/directoryguard.cpp
index 9c97130a4..014d213d7 100644
--- a/src/libs/installer/directoryguard.cpp
+++ b/src/libs/installer/directoryguard.cpp
@@ -28,6 +28,7 @@
#include "directoryguard.h"
+#include "fileutils.h"
#include "globals.h"
#include "errors.h"
@@ -92,8 +93,7 @@ QStringList DirectoryGuard::tryCreate()
toCreate = QDir(p);
}
- QDir dir(m_path);
- m_created = dir.mkpath(m_path);
+ m_created = QInstaller::createDirectoryWithParents(m_path);
if (!m_created) {
throw Error(QCoreApplication::translate("DirectoryGuard",
"Cannot create directory \"%1\".").arg(QDir::toNativeSeparators(m_path)));
diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp
index 4d17ef4a2..65eead1f9 100644
--- a/src/libs/installer/downloadarchivesjob.cpp
+++ b/src/libs/installer/downloadarchivesjob.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -44,10 +44,12 @@ using namespace QInstaller;
using namespace KDUpdater;
+static constexpr uint scMaxRetries = 5;
+
/*!
Creates a new DownloadArchivesJob with parent \a core.
*/
-DownloadArchivesJob::DownloadArchivesJob(PackageManagerCore *core)
+DownloadArchivesJob::DownloadArchivesJob(PackageManagerCore *core, const QString &objectName)
: Job(core)
, m_core(core)
, m_downloader(nullptr)
@@ -58,8 +60,10 @@ DownloadArchivesJob::DownloadArchivesJob(PackageManagerCore *core)
, m_progressChangedTimerId(0)
, m_totalSizeToDownload(0)
, m_totalSizeDownloaded(0)
+ , m_retryCount(scMaxRetries)
{
setCapabilities(Cancelable);
+ setObjectName(objectName);
}
/*!
@@ -75,7 +79,7 @@ DownloadArchivesJob::~DownloadArchivesJob()
Sets the \a archives to download. The first value of each pair contains the file name to register
the file in the installer's internal file system, the second one the source url.
*/
-void DownloadArchivesJob::setArchivesToDownload(const QList<QPair<QString, QString> > &archives)
+void DownloadArchivesJob::setArchivesToDownload(const QList<PackageManagerCore::DownloadItem> &archives)
{
m_archivesToDownload = archives;
m_archivesToDownloadCount = archives.count();
@@ -111,17 +115,17 @@ void DownloadArchivesJob::doCancel()
void DownloadArchivesJob::fetchNextArchiveHash()
{
- if (m_core->testChecksum()) {
+ if (m_archivesToDownload.isEmpty()) {
+ emitFinished();
+ return;
+ }
+
+ if (m_archivesToDownload.first().checkSha1CheckSum) {
if (m_canceled) {
finishWithError(tr("Canceled"));
return;
}
- if (m_archivesToDownload.isEmpty()) {
- emitFinished();
- return;
- }
-
if (m_downloader)
m_downloader->deleteLater();
@@ -146,6 +150,7 @@ void DownloadArchivesJob::finishedHashDownload()
QFile sha1HashFile(m_downloader->downloadedFileName());
if (sha1HashFile.open(QFile::ReadOnly)) {
+ emit hashDownloadReady(m_downloader->downloadedFileName());
m_currentHash = sha1HashFile.readAll();
fetchNextArchive();
} else {
@@ -280,25 +285,32 @@ void DownloadArchivesJob::registerFile()
{
Q_ASSERT(m_downloader != nullptr);
- if (m_canceled)
+ if (m_canceled || m_archivesToDownload.isEmpty())
return;
- if (m_core->testChecksum() && m_currentHash != m_downloader->sha1Sum().toHex()) {
+ if (m_archivesToDownload.first().checkSha1CheckSum && m_currentHash != m_downloader->sha1Sum().toHex()) {
//TODO: Maybe we should try to download the file again automatically
const QMessageBox::Button res =
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("DownloadError"), tr("Download Error"), tr("Hash verification while "
- "downloading failed. This is a temporary error, please retry."),
- QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Cancel);
-
- // If run from command line instance, do not continue if hash verification failed.
- // Same download is tried again and again causing infinite loop if hash not
- // fixed to repositories.
- if (res == QMessageBox::Cancel || m_core->isCommandLineInstance()) {
- finishWithError(tr("Cannot verify Hash"));
+ "downloading failed. This is a temporary error, please retry.\n\n"
+ "Expected: %1 \nDownloaded: %2").arg(QString::fromLatin1(m_currentHash), QString::fromLatin1(m_downloader->sha1Sum().toHex())),
+ QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Retry);
+
+ if (res == QMessageBox::Cancel) {
+ finishWithError(tr("Cannot verify Hash\nExpected: %1 \nDownloaded: %2")
+ .arg(QString::fromLatin1(m_currentHash), QString::fromLatin1(m_downloader->sha1Sum().toHex())));
return;
}
+ // When using command line instance, only retry a number of times to avoid
+ // infinite loop in case the automatic answer for the messagebox is "Retry"
+ if (m_core->isCommandLineInstance() && (--m_retryCount == 0)) {
+ finishWithError(tr("Retry count (%1) exceeded").arg(scMaxRetries));
+ return;
+ }
} else {
+ m_retryCount = scMaxRetries;
+
++m_archivesDownloaded;
m_totalSizeDownloaded += QFile(m_downloader->downloadedFileName()).size();
if (m_progressChangedTimerId) {
@@ -307,9 +319,11 @@ void DownloadArchivesJob::registerFile()
emit progressChanged(double(m_archivesDownloaded) / m_archivesToDownloadCount);
}
- const QPair<QString, QString> pair = m_archivesToDownload.takeFirst();
- BinaryFormatEngineHandler::instance()->registerResource(pair.first,
+ const PackageManagerCore::DownloadItem item = m_archivesToDownload.takeFirst();
+ BinaryFormatEngineHandler::instance()->registerResource(item.fileName,
m_downloader->downloadedFileName());
+
+ emit fileDownloadReady(m_downloader->downloadedFileName());
}
fetchNextArchiveHash();
}
@@ -327,14 +341,21 @@ void DownloadArchivesJob::downloadFailed(const QString &error)
const QMessageBox::StandardButton b =
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("archiveDownloadError"), tr("Download Error"), tr("Cannot download archive %1: %2")
- .arg(m_archivesToDownload.first().second, error), QMessageBox::Retry | QMessageBox::Cancel);
+ .arg(m_archivesToDownload.first().sourceUrl, error), QMessageBox::Retry | QMessageBox::Cancel,
+ QMessageBox::Retry);
+
+ if (b == QMessageBox::Retry) {
+ // When using command line instance, only retry a number of times to avoid
+ // infinite loop in case the automatic answer for the messagebox is "Retry"
+ if (m_core->isCommandLineInstance() && (--m_retryCount == 0)) {
+ finishWithError(tr("Retry count (%1) exceeded").arg(scMaxRetries));
+ return;
+ }
- // Do not call fetchNextArchiveHash when using command line instance,
- // installer tries to download the same archive causing infinite loop
- if (b == QMessageBox::Retry && !m_core->isCommandLineInstance())
QMetaObject::invokeMethod(this, "fetchNextArchiveHash", Qt::QueuedConnection);
- else
+ } else {
downloadCanceled();
+ }
}
void DownloadArchivesJob::finishWithError(const QString &error)
@@ -350,13 +371,13 @@ void DownloadArchivesJob::finishWithError(const QString &error)
KDUpdater::FileDownloader *DownloadArchivesJob::setupDownloader(const QString &suffix, const QString &queryString)
{
KDUpdater::FileDownloader *downloader = nullptr;
- const QFileInfo fi = QFileInfo(m_archivesToDownload.first().first);
+ const QFileInfo fi = QFileInfo(m_archivesToDownload.first().fileName);
const Component *const component = m_core->componentByName(PackageManagerCore::checkableName(QFileInfo(fi.path()).fileName()));
if (component) {
QString fullQueryString;
if (!queryString.isEmpty())
fullQueryString = QLatin1String("?") + queryString;
- const QUrl url(m_archivesToDownload.first().second + suffix + fullQueryString);
+ const QUrl url(m_archivesToDownload.first().sourceUrl + suffix + fullQueryString);
const QString &scheme = url.scheme();
downloader = FileDownloaderFactory::instance().create(scheme, this);
diff --git a/src/libs/installer/downloadarchivesjob.h b/src/libs/installer/downloadarchivesjob.h
index bd764e01c..5155c881a 100644
--- a/src/libs/installer/downloadarchivesjob.h
+++ b/src/libs/installer/downloadarchivesjob.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,7 +30,7 @@
#define DOWNLOADARCHIVESJOB_H
#include "job.h"
-
+#include "packagemanagercore.h"
#include <QtCore/QPair>
#include <QtCore/QElapsedTimer>
@@ -45,18 +45,17 @@ namespace KDUpdater {
namespace QInstaller {
class MessageBoxHandler;
-class PackageManagerCore;
class DownloadArchivesJob : public Job
{
Q_OBJECT
public:
- explicit DownloadArchivesJob(PackageManagerCore *core);
+ explicit DownloadArchivesJob(PackageManagerCore *core, const QString &objectName);
~DownloadArchivesJob();
int numberOfDownloads() const { return m_archivesDownloaded; }
- void setArchivesToDownload(const QList<QPair<QString, QString> > &archives);
+ void setArchivesToDownload(const QList<PackageManagerCore::DownloadItem> &archives);
void setExpectedTotalSize(quint64 total);
Q_SIGNALS:
@@ -64,10 +63,13 @@ Q_SIGNALS:
void outputTextChanged(const QString &progress);
void downloadStatusChanged(const QString &status);
+ void hashDownloadReady(const QString &localPath);
+ void fileDownloadReady(const QString &localPath);
+
protected:
- void doStart();
- void doCancel();
- void timerEvent(QTimerEvent *event);
+ void doStart() override;
+ void doCancel() override;
+ void timerEvent(QTimerEvent *event) override;
public Q_SLOTS:
void onDownloadStatusChanged(const QString &status);
@@ -91,7 +93,7 @@ private:
int m_archivesDownloaded;
int m_archivesToDownloadCount;
- QList<QPair<QString, QString> > m_archivesToDownload;
+ QList<PackageManagerCore::DownloadItem> m_archivesToDownload;
bool m_canceled;
QByteArray m_currentHash;
@@ -101,6 +103,8 @@ private:
quint64 m_totalSizeToDownload;
quint64 m_totalSizeDownloaded;
QElapsedTimer m_totalDownloadSpeedTimer;
+
+ uint m_retryCount;
};
} // namespace QInstaller
diff --git a/src/libs/installer/downloadfiletask.cpp b/src/libs/installer/downloadfiletask.cpp
index d9f1e3432..a959677a9 100644
--- a/src/libs/installer/downloadfiletask.cpp
+++ b/src/libs/installer/downloadfiletask.cpp
@@ -1,7 +1,7 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,6 +30,7 @@
#include "downloadfiletask_p.h"
#include "globals.h"
+#include "productkeycheck.h"
#include <QCoreApplication>
#include <QDir>
@@ -197,7 +198,7 @@ void Downloader::onReadyRead()
data.observer->addSample(read);
data.observer->addBytesTransfered(read);
- data.observer->addCheckSumData(buffer.data(), read);
+ data.observer->addCheckSumData(buffer.left(read));
int progress = m_finished * 100;
for (const auto &pair : m_downloads)
@@ -227,8 +228,8 @@ void Downloader::onFinished(QNetworkReply *reply)
QNetworkReply *const redirectReply = startDownload(taskItem);
foreach (const QUrl &redirect, redirects)
- m_redirects.insertMulti(redirectReply, redirect);
- m_redirects.insertMulti(redirectReply, url);
+ m_redirects.insert(redirectReply, redirect);
+ m_redirects.insert(redirectReply, url);
m_downloads.erase(reply);
m_redirects.remove(reply);
@@ -246,7 +247,7 @@ void Downloader::onFinished(QNetworkReply *reply)
if (!ba.isEmpty()) {
data.observer->addSample(ba.size());
data.observer->addBytesTransfered(ba.size());
- data.observer->addCheckSumData(ba.data(), ba.size());
+ data.observer->addCheckSumData(ba);
}
const QByteArray expectedCheckSum = data.taskItem.value(TaskRole::Checksum).toByteArray();
@@ -269,7 +270,7 @@ void Downloader::onFinished(QNetworkReply *reply)
}
}
-void Downloader::onError(QNetworkReply::NetworkError error)
+void Downloader::errorOccurred(QNetworkReply::NetworkError error)
{
QNetworkReply *const reply = qobject_cast<QNetworkReply *>(sender());
@@ -286,6 +287,10 @@ void Downloader::onError(QNetworkReply::NetworkError error)
if (data.taskItem.source().contains(QLatin1String("Updates.xml"), Qt::CaseInsensitive)) {
qCWarning(QInstaller::lcServer) << QString::fromLatin1("Network error while downloading '%1': %2.").arg(
data.taskItem.source(), reply->errorString());
+ } else if (data.taskItem.source().contains(QLatin1String("_meta"), Qt::CaseInsensitive)) {
+ QString errorString = tr("Network error while downloading '%1': %2.").arg(data.taskItem.source(), reply->errorString());
+ errorString.append(ProductKeyCheck::instance()->additionalMetaDownloadWarning());
+ m_futureInterface->reportException(TaskException(errorString));
} else {
m_futureInterface->reportException(
TaskException(tr("Network error while downloading '%1': %2.").arg(
@@ -395,14 +400,17 @@ QNetworkReply *Downloader::startDownload(const FileTaskItem &item)
.arg(source.toString(), source.errorString())));
return 0;
}
+ QNetworkRequest request(source);
+ request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
+ request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
- QNetworkReply *reply = m_nam.get(QNetworkRequest(source));
+ QNetworkReply *reply = m_nam.get(request);
std::unique_ptr<Data> data(new Data(item));
m_downloads[reply] = std::move(data);
connect(reply, &QIODevice::readyRead, this, &Downloader::onReadyRead);
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
- SLOT(onError(QNetworkReply::NetworkError)));
+ connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this,
+ SLOT(errorOccurred(QNetworkReply::NetworkError)));
#ifndef QT_NO_SSL
connect(reply, &QNetworkReply::sslErrors, this, &Downloader::onSslErrors);
#endif
diff --git a/src/libs/installer/downloadfiletask.h b/src/libs/installer/downloadfiletask.h
index 21908549d..f50d4c0ff 100644
--- a/src/libs/installer/downloadfiletask.h
+++ b/src/libs/installer/downloadfiletask.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -63,8 +63,8 @@ public:
FileTaskItem taskItem() const { return m_fileTaskItem; }
void setFileTaskItem(const FileTaskItem &item) { m_fileTaskItem = item; }
- void raise() const { throw *this; }
- AuthenticationRequiredException *clone() const {
+ void raise() const override { throw *this; }
+ AuthenticationRequiredException *clone() const override {
return new AuthenticationRequiredException(*this); }
private:
@@ -98,7 +98,7 @@ public:
void setAuthenticator(const QAuthenticator &authenticator);
void setProxyFactory(KDUpdater::FileDownloaderProxyFactory *factory);
- void doTask(QFutureInterface<FileTaskResult> &fi);
+ void doTask(QFutureInterface<FileTaskResult> &fi) override;
private:
friend class Downloader;
diff --git a/src/libs/installer/downloadfiletask_p.h b/src/libs/installer/downloadfiletask_p.h
index 3dfce27b4..4750d5134 100644
--- a/src/libs/installer/downloadfiletask_p.h
+++ b/src/libs/installer/downloadfiletask_p.h
@@ -86,7 +86,7 @@ private slots:
void doDownload();
void onReadyRead();
void onFinished(QNetworkReply *reply);
- void onError(QNetworkReply::NetworkError error);
+ void errorOccurred(QNetworkReply::NetworkError error);
void onSslErrors(const QList<QSslError> &sslErrors);
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
diff --git a/src/libs/installer/elevatedexecuteoperation.cpp b/src/libs/installer/elevatedexecuteoperation.cpp
index fb1778fe0..87810211e 100644
--- a/src/libs/installer/elevatedexecuteoperation.cpp
+++ b/src/libs/installer/elevatedexecuteoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -35,7 +35,7 @@
#include <QtCore/QDebug>
#include <QtCore/QProcessEnvironment>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtCore/QThread>
using namespace QInstaller;
@@ -65,10 +65,12 @@ public:
private:
bool needsRerunWithReplacedVariables(QStringList &arguments, const OperationType type);
+ void setErrorMessage(const QString &message);
-
+private:
QProcessWrapper *process;
bool showStandardError;
+ QString m_customErrorMessage;
};
ElevatedExecuteOperation::ElevatedExecuteOperation(PackageManagerCore *core)
@@ -120,13 +122,12 @@ int ElevatedExecuteOperation::Private::run(QStringList &arguments, const Operati
args.removeAll(workingDirectoryArgument);
}
- QString customErrorMessage;
QStringList filteredCustomErrorMessage = args.filter(QLatin1String("errormessage="),
Qt::CaseInsensitive);
if (!filteredCustomErrorMessage.isEmpty()) {
QString customErrorMessageArgument = filteredCustomErrorMessage.at(0);
- customErrorMessage = customErrorMessageArgument;
- customErrorMessage.replace(QLatin1String("errormessage="), QString(), Qt::CaseInsensitive);
+ m_customErrorMessage = customErrorMessageArgument;
+ m_customErrorMessage.replace(QLatin1String("errormessage="), QString(), Qt::CaseInsensitive);
args.removeAll(customErrorMessageArgument);
}
@@ -137,9 +138,10 @@ int ElevatedExecuteOperation::Private::run(QStringList &arguments, const Operati
QList< int > allowedExitCodes;
- QRegExp re(QLatin1String("^\\{((-?\\d+,)*-?\\d+)\\}$"));
- if (re.exactMatch(args.first())) {
- const QStringList numbers = re.cap(1).split(QLatin1Char(','));
+ static const QRegularExpression re(QLatin1String("^\\{((-?\\d+,)*-?\\d+)\\}$"));
+ const QRegularExpressionMatch match = re.match(args.first());
+ if (match.hasMatch()) {
+ const QStringList numbers = match.captured(1).split(QLatin1Char(','));
for(QStringList::const_iterator it = numbers.constBegin(); it != numbers.constEnd(); ++it)
allowedExitCodes.push_back(it->toInt());
args.pop_front();
@@ -156,7 +158,8 @@ int ElevatedExecuteOperation::Private::run(QStringList &arguments, const Operati
const bool success = QProcessWrapper::startDetached(args.front(), args.mid(1));
if (!success) {
q->setError(UserDefinedError);
- q->setErrorString(tr("Cannot start detached: \"%1\"").arg(callstr));
+ setErrorMessage(tr("Cannot start detached: \"%1\"").arg(callstr));
+
returnValue = Error;
}
return returnValue;
@@ -201,8 +204,7 @@ int ElevatedExecuteOperation::Private::run(QStringList &arguments, const Operati
int returnValue = NoError;
if (!success) {
q->setError(UserDefinedError);
- //TODO: pass errorString() through the wrapper */
- q->setErrorString(tr("Cannot start: \"%1\": %2").arg(callstr,
+ setErrorMessage(tr("Cannot start: \"%1\": %2").arg(callstr,
process->errorString()));
if (!needsRerunWithReplacedVariables(arguments, type)) {
returnValue = Error;
@@ -220,30 +222,25 @@ int ElevatedExecuteOperation::Private::run(QStringList &arguments, const Operati
q->setValue(QLatin1String("ExitCode"), process->exitCode());
- if (process->exitStatus() == QProcessWrapper::CrashExit) {
- q->setError(UserDefinedError);
- q->setErrorString(tr("Program crashed: \"%1\"").arg(callstr));
- returnValue = Error;
- }
+ if (success) {
+ const QByteArray standardErrorOutput = process->readAllStandardError();
+ // in error case it would be useful to see something in verbose output
+ if (!standardErrorOutput.isEmpty())
+ qCWarning(QInstaller::lcInstallerInstallLog).noquote() << standardErrorOutput;
- if (!allowedExitCodes.contains(process->exitCode()) && returnValue != NeedsRerun) {
- if (!needsRerunWithReplacedVariables(arguments, type)) {
+ if (process->exitStatus() == QProcessWrapper::CrashExit) {
q->setError(UserDefinedError);
- if (customErrorMessage.isEmpty()) {
- q->setErrorString(tr("Execution failed (Unexpected exit code: %1): \"%2\"")
+ setErrorMessage(tr("Program crashed: \"%1\"").arg(callstr));
+ returnValue = Error;
+ } else if (!allowedExitCodes.contains(process->exitCode()) && returnValue != NeedsRerun) {
+ if (!needsRerunWithReplacedVariables(arguments, type)) {
+ q->setError(UserDefinedError);
+ setErrorMessage(tr("Execution failed (Unexpected exit code: %1): \"%2\"")
.arg(QString::number(process->exitCode()), callstr));
+ returnValue = Error;
} else {
- q->setErrorString(customErrorMessage);
+ returnValue = NeedsRerun;
}
-
- QByteArray standardErrorOutput = process->readAllStandardError();
- // in error case it would be useful to see something in verbose output
- if (!standardErrorOutput.isEmpty())
- qCWarning(QInstaller::lcInstallerInstallLog).noquote() << standardErrorOutput;
-
- returnValue = Error;
- } else {
- returnValue = NeedsRerun;
}
}
Q_ASSERT(process);
@@ -276,6 +273,13 @@ bool ElevatedExecuteOperation::Private::needsRerunWithReplacedVariables(QStringL
return rerun;
}
+void ElevatedExecuteOperation::Private::setErrorMessage(const QString &message)
+{
+ if (m_customErrorMessage.isEmpty())
+ q->setErrorString(message);
+ else
+ q->setErrorString(m_customErrorMessage);
+}
/*!
Cancels the ElevatedExecuteOperation. This methods tries to terminate the process
gracefully by calling QProcessWrapper::terminate. After 10 seconds, the process gets killed.
diff --git a/src/libs/installer/elevatedexecuteoperation.h b/src/libs/installer/elevatedexecuteoperation.h
index 470d3e506..69224f99f 100644
--- a/src/libs/installer/elevatedexecuteoperation.h
+++ b/src/libs/installer/elevatedexecuteoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -47,10 +47,10 @@ public:
explicit ElevatedExecuteOperation(PackageManagerCore *core);
~ElevatedExecuteOperation();
- void backup() Q_DECL_OVERRIDE;
- bool performOperation() Q_DECL_OVERRIDE;
- bool undoOperation() Q_DECL_OVERRIDE;
- bool testOperation() Q_DECL_OVERRIDE;
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
Q_SIGNALS:
void cancelProcess();
diff --git a/src/libs/installer/environmentvariablesoperation.cpp b/src/libs/installer/environmentvariablesoperation.cpp
index 2f55172e1..94cd1e36f 100644
--- a/src/libs/installer/environmentvariablesoperation.cpp
+++ b/src/libs/installer/environmentvariablesoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,6 +30,7 @@
#include "qsettingswrapper.h"
#include <stdlib.h>
+#include <QDir>
#include "environment.h"
#include "globals.h"
@@ -110,6 +111,12 @@ bool handleRegExpandSz(const QString &regPath, const QString &name,
}
}
}
+#else
+ Q_UNUSED(regPath)
+ Q_UNUSED(name)
+ Q_UNUSED(value)
+ Q_UNUSED(errorString)
+ Q_UNUSED(error)
#endif
return setAsExpandSZ;
}
@@ -122,7 +129,7 @@ UpdateOperation::Error writeSetting(const QString &regPath,
QString *oldValue)
{
oldValue->clear();
- SettingsType registry(regPath, QSettingsWrapper::NativeFormat);
+ SettingsType registry(regPath, QSettings::NativeFormat);
if (!registry.isWritable()) {
*errorString = UpdateOperation::tr("Registry path %1 is not writable.").arg(regPath);
return UpdateOperation::UserDefinedError;
@@ -156,17 +163,17 @@ UpdateOperation::Error undoSetting(const QString &regPath,
{
QString actual;
{
- SettingsType registry(regPath, QSettingsWrapper::NativeFormat);
+ SettingsType registry(regPath, QSettings::NativeFormat);
actual = registry.value(name).toString();
}
if (actual != value)
{
- //For unknown reason paths with @TargetDir@ variable get modified
- //so that Windows file separators get replaced with unix style separators,
- //fix separators before matching to actual value in register
+ //Ignore the separators
+ static const QRegularExpression regex(QLatin1String("(\\\\|/)"));
QString tempValue = value;
- QString fixedValue = tempValue.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ QString fixedValue = tempValue.replace(regex, QDir::separator());
+ actual = actual.replace(regex, QDir::separator());
if (actual != fixedValue) //key changed, don't undo
return UpdateOperation::UserDefinedError;
diff --git a/src/libs/installer/environmentvariablesoperation.h b/src/libs/installer/environmentvariablesoperation.h
index 3c5252bc6..dea2d40c7 100644
--- a/src/libs/installer/environmentvariablesoperation.h
+++ b/src/libs/installer/environmentvariablesoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT EnvironmentVariableOperation : public Operation
public:
explicit EnvironmentVariableOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
}
diff --git a/src/libs/installer/errors.h b/src/libs/installer/errors.h
index 117eb5119..e8f2ee914 100644
--- a/src/libs/installer/errors.h
+++ b/src/libs/installer/errors.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,23 +31,21 @@
#include <QtCore/QDebug>
#include <QtCore/QString>
-
-#include <stdexcept>
+#include <QtCore/QException>
namespace QInstaller {
-class Error : public std::exception
+class Error : public QException
{
public:
- Error()
- {}
+ Error() = default;
explicit Error(const QString &message)
: m_message(message)
{}
- virtual ~Error() throw()
- {}
+ void raise() const override { throw *this; }
+ Error *clone() const override { return new Error(*this); }
QString message() const { return m_message; }
diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp
index 7660dadb0..b00a67190 100644
--- a/src/libs/installer/extractarchiveoperation.cpp
+++ b/src/libs/installer/extractarchiveoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,6 +30,7 @@
#include "constants.h"
#include "globals.h"
+#include "fileguard.h"
#include <QEventLoop>
#include <QThreadPool>
@@ -45,14 +46,14 @@ namespace QInstaller {
*/
/*!
- \typedef QInstaller::Backup
+ \typedef QInstaller::ExtractArchiveOperation::Backup
Synonym for QPair<QString, QString>. Contains a pair
of an original and a generated backup filename for a file.
*/
/*!
- \typedef QInstaller::BackupFiles
+ \typedef QInstaller::ExtractArchiveOperation::BackupFiles
Synonym for QVector<Backup>.
*/
@@ -65,13 +66,64 @@ namespace QInstaller {
ExtractArchiveOperation::ExtractArchiveOperation(PackageManagerCore *core)
: UpdateOperation(core)
+ , m_totalEntries(0)
{
setName(QLatin1String("Extract"));
+ setGroup(OperationGroup::Unpack);
}
void ExtractArchiveOperation::backup()
{
- // we need to backup on the fly...
+ if (!checkArgumentCount(2))
+ return;
+
+ const QStringList args = arguments();
+ const QString archivePath = args.at(0);
+ const QString targetDir = args.at(1);
+
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create(archivePath));
+ if (!archive) {
+ setError(UserDefinedError);
+ setErrorString(tr("Unsupported archive \"%1\": no handler registered for file suffix \"%2\".")
+ .arg(archivePath, QFileInfo(archivePath).suffix()));
+ return;
+ }
+
+ if (!(archive->open(QIODevice::ReadOnly) && archive->isSupported())) {
+ setError(UserDefinedError);
+ setErrorString(tr("Cannot open archive \"%1\" for reading: %2")
+ .arg(archivePath, archive->errorString()));
+ return;
+ }
+ const QVector<ArchiveEntry> entries = archive->list();
+ if (entries.isEmpty()) {
+ setError(UserDefinedError);
+ setErrorString(tr("Error while reading contents of archive \"%1\": %2")
+ .arg(archivePath, archive->errorString()));
+ return;
+ }
+
+ const bool hasAdminRights = (packageManager() && packageManager()->hasAdminRights());
+ const bool canCreateSymLinks = QInstaller::canCreateSymbolicLinks();
+ bool needsAdminRights = false;
+
+ for (auto &entry : entries) {
+ const QString completeFilePath = targetDir + QDir::separator() + entry.path;
+ if (!entry.isDirectory) {
+ // Ignore failed backups, existing files are overwritten when extracting.
+ // Should the backups be used on rollback too, this may not be the
+ // desired behavior anymore.
+ prepareForFile(completeFilePath);
+ }
+ if (!hasAdminRights && !canCreateSymLinks && entry.isSymbolicLink)
+ needsAdminRights = true;
+ }
+ m_totalEntries = entries.size();
+ if (needsAdminRights)
+ setValue(QLatin1String("admin"), true);
+
+ // Show something was done
+ emit progressChanged(scBackupProgressPart);
}
bool ExtractArchiveOperation::performOperation()
@@ -88,7 +140,7 @@ bool ExtractArchiveOperation::performOperation()
connect(&callback, &Callback::progressChanged, this, &ExtractArchiveOperation::progressChanged);
- Worker *worker = new Worker(archivePath, targetDir, &callback);
+ Worker *worker = new Worker(archivePath, targetDir, m_totalEntries, &callback);
connect(worker, &Worker::finished, &receiver, &Receiver::workerFinished,
Qt::QueuedConnection);
@@ -126,10 +178,15 @@ bool ExtractArchiveOperation::performOperation()
QString installDir = targetDir;
// If we have package manager in use (normal installer run) then use
// TargetDir for saving filenames, otherwise those would be saved to
- // extracted folder.
- if (packageManager())
- installDir = packageManager()->value(scTargetDir);
+ // extracted folder. Also initialize installerbasebinary which we use later
+ // to check if the extracted file in question is the maintenancetool itself.
+ QString installerBaseBinary;
+ if (PackageManagerCore *core = packageManager()) {
+ installDir = core->value(scTargetDir);
+ installerBaseBinary = core->toNativeSeparators(core->replaceVariables(core->installerBaseBinary()));
+ }
const QString resourcesPath = installDir + QLatin1Char('/') + QLatin1String("installerResources");
+
QString fileDirectory = resourcesPath + QLatin1Char('/') + archivePath.section(QLatin1Char('/'), 1, 1,
QString::SectionSkipEmpty) + QLatin1Char('/');
QString archiveFileName = archivePath.section(QLatin1Char('/'), 2, 2, QString::SectionSkipEmpty);
@@ -140,10 +197,7 @@ bool ExtractArchiveOperation::performOperation()
QFileInfo targetDirectoryInfo(fileDirectory);
- QDir dir(targetDirectoryInfo.absolutePath());
- if (!dir.exists()) {
- dir.mkpath(targetDirectoryInfo.absolutePath());
- }
+ QInstaller::createDirectoryWithParents(targetDirectoryInfo.absolutePath());
setDefaultFilePermissions(resourcesPath, DefaultFilePermissions::Executable);
setDefaultFilePermissions(targetDirectoryInfo.absolutePath(), DefaultFilePermissions::Executable);
@@ -152,9 +206,17 @@ bool ExtractArchiveOperation::performOperation()
setDefaultFilePermissions(file.fileName(), DefaultFilePermissions::NonExecutable);
QDataStream out (&file);
for (int i = 0; i < files.count(); ++i) {
+ if (!installerBaseBinary.isEmpty() && files[i].startsWith(installerBaseBinary)) {
+ // Do not write installerbase binary filename to extracted files. Installer binary
+ // is maintenance tool program, the binary is removed elsewhere
+ // when we do full uninstall.
+ files.clear();
+ break;
+ }
files[i] = replacePath(files.at(i), installDir, QLatin1String(scRelocatable));
}
- out << files;
+ if (!files.isEmpty())
+ out << files;
setValue(QLatin1String("files"), file.fileName());
file.close();
} else {
@@ -164,7 +226,7 @@ bool ExtractArchiveOperation::performOperation()
// TODO: Use backups for rollback, too? Doesn't work for uninstallation though.
// delete all backups we can delete right now, remember the rest
- foreach (const QInstaller::Backup &i, callback.backupFiles())
+ foreach (const Backup &i, m_backupFiles)
deleteFileNowOrLater(i.second);
if (!receiver.success()) {
@@ -192,10 +254,14 @@ bool ExtractArchiveOperation::undoOperation()
if (!readDataFileContents(targetDir, &files))
return false;
}
- startUndoProcess(files);
+ if (!files.isEmpty())
+ startUndoProcess(files);
if (!useStringListType)
deleteDataFile(m_relocatedDataFileName);
+ // Remove the installerResources directory if it is empty.
+ QDir(targetDir).rmdir(QLatin1String("installerResources"));
+
return true;
}
@@ -207,6 +273,9 @@ void ExtractArchiveOperation::startUndoProcess(const QStringList &files)
connect(thread, &WorkerThread::progressChanged, this,
&ExtractArchiveOperation::progressChanged);
+ const QFileInfo archive(arguments().at(0));
+ emit outputTextChanged(tr("Removing files extracted from \"%1\"").arg(archive.fileName()));
+
QEventLoop loop;
connect(thread, &QThread::finished, &loop, &QEventLoop::quit, Qt::QueuedConnection);
thread->start();
@@ -231,11 +300,58 @@ void ExtractArchiveOperation::deleteDataFile(const QString &fileName)
}
}
+QString ExtractArchiveOperation::generateBackupName(const QString &fn)
+{
+ const QString bfn = fn + QLatin1String(".tmpUpdate");
+ QString res = bfn;
+ int i = 0;
+ while (QFile::exists(res))
+ res = bfn + QString::fromLatin1(".%1").arg(i++);
+ return res;
+}
+
+bool ExtractArchiveOperation::prepareForFile(const QString &filename)
+{
+ if (!QFile::exists(filename))
+ return true;
+
+ FileGuardLocker locker(filename, FileGuard::globalObject());
+
+ const QString backup = generateBackupName(filename);
+ QFile f(filename);
+ const bool renamed = f.rename(backup);
+ if (f.exists() && !renamed) {
+ qCritical("Cannot rename %s to %s: %s", qPrintable(filename), qPrintable(backup),
+ qPrintable(f.errorString()));
+ return false;
+ }
+ m_backupFiles.append(qMakePair(filename, backup));
+ return true;
+}
+
bool ExtractArchiveOperation::testOperation()
{
return true;
}
+quint64 ExtractArchiveOperation::sizeHint()
+{
+ if (!checkArgumentCount(2))
+ return UpdateOperation::sizeHint();
+
+ if (hasValue(QLatin1String("sizeHint")))
+ return value(QLatin1String("sizeHint")).toULongLong();
+
+ const QString archivePath = arguments().at(0);
+ const quint64 compressedSize = QFileInfo(archivePath).size();
+
+ setValue(QLatin1String("sizeHint"), QString::number(compressedSize));
+
+ // A rough estimate of how much time it takes to extract this archive. Other
+ // affecting parameters are the archive format, compression filter and -level.
+ return compressedSize;
+}
+
bool ExtractArchiveOperation::readDataFileContents(QString &targetDir, QStringList *resultList)
{
const QString filePath = value(QLatin1String("files")).toString();
diff --git a/src/libs/installer/extractarchiveoperation.h b/src/libs/installer/extractarchiveoperation.h
index 7fc008887..b1a696788 100644
--- a/src/libs/installer/extractarchiveoperation.h
+++ b/src/libs/installer/extractarchiveoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -43,10 +43,12 @@ class INSTALLER_EXPORT ExtractArchiveOperation : public QObject, public Operatio
public:
explicit ExtractArchiveOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
+
+ quint64 sizeHint() override;
bool readDataFileContents(QString &targetDir, QStringList *resultList);
@@ -58,13 +60,21 @@ private:
void startUndoProcess(const QStringList &files);
void deleteDataFile(const QString &fileName);
-private:
- QString m_relocatedDataFileName;
+ QString generateBackupName(const QString &fn);
+ bool prepareForFile(const QString &filename);
private:
+ typedef QPair<QString, QString> Backup;
+ typedef QVector<Backup> BackupFiles;
+
class Callback;
class Worker;
class Receiver;
+
+private:
+ QString m_relocatedDataFileName;
+ BackupFiles m_backupFiles;
+ quint64 m_totalEntries;
};
}
diff --git a/src/libs/installer/extractarchiveoperation_p.h b/src/libs/installer/extractarchiveoperation_p.h
index 706187eb7..24614de39 100644
--- a/src/libs/installer/extractarchiveoperation_p.h
+++ b/src/libs/installer/extractarchiveoperation_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -33,12 +33,20 @@
#include "fileutils.h"
#include "archivefactory.h"
#include "packagemanagercore.h"
+#include "remoteclient.h"
+#include "adminauthorization.h"
+#include "utils.h"
+#include "errors.h"
+#include "loggingutils.h"
#include <QRunnable>
#include <QThread>
namespace QInstaller {
+constexpr double scBackupProgressPart = 0.1;
+constexpr double scPerformProgressPart = (1 - scBackupProgressPart);
+
class WorkerThread : public QThread
{
Q_OBJECT
@@ -52,24 +60,45 @@ public:
setObjectName(QLatin1String("ExtractArchive"));
}
- void run()
+ void run() override
{
Q_ASSERT(m_op != 0);
+ QStringList directories;
+
int removedCounter = 0;
foreach (const QString &file, m_files) {
removedCounter++;
const QFileInfo fi(file);
- emit currentFileChanged(QDir::toNativeSeparators(file));
+ if (LoggingHandler::instance().verboseLevel() == LoggingHandler::Detailed)
+ emit currentFileChanged(QDir::toNativeSeparators(file));
emit progressChanged(double(removedCounter) / m_files.count());
if (fi.isFile() || fi.isSymLink()) {
m_op->deleteFileNowOrLater(fi.absoluteFilePath());
} else if (fi.isDir()) {
- removeSystemGeneratedFiles(file);
- fi.dir().rmdir(file); // directory may not exist
+ directories.append(file);
}
}
+
+ std::sort(directories.begin(), directories.end(), [](const QString &lhs, const QString &rhs) {
+ // Doesn't match the original creation order, nor will the sorted list be a logical
+ // directory tree. Only requirement is that subdirectories get removed first.
+ const int lhsParts = QDir::fromNativeSeparators(lhs)
+ .split(QLatin1Char('/'), Qt::SkipEmptyParts).size();
+ const int rhsParts = QDir::fromNativeSeparators(rhs)
+ .split(QLatin1Char('/'), Qt::SkipEmptyParts).size();
+
+ if (lhsParts == rhsParts)
+ return lhs < rhs;
+
+ return lhsParts > rhsParts;
+ });
+
+ for (auto &directory : qAsConst(directories)) {
+ removeSystemGeneratedFiles(directory);
+ QDir(directory).rmdir(directory); // directory may not exist
+ }
}
signals:
@@ -81,53 +110,21 @@ private:
ExtractArchiveOperation *m_op;
};
-typedef QPair<QString, QString> Backup;
-typedef QVector<Backup> BackupFiles;
-
class ExtractArchiveOperation::Callback : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Callback)
public:
- Callback() = default;
-
- BackupFiles backupFiles() const
- {
- return m_backupFiles;
- }
+ Callback()
+ : m_lastProgressPercentage(0)
+ {}
QStringList extractedFiles() const
{
return m_extractedFiles;
}
- static QString generateBackupName(const QString &fn)
- {
- const QString bfn = fn + QLatin1String(".tmpUpdate");
- QString res = bfn;
- int i = 0;
- while (QFile::exists(res))
- res = bfn + QString::fromLatin1(".%1").arg(i++);
- return res;
- }
-
- bool prepareForFile(const QString &filename)
- {
- if (!QFile::exists(filename))
- return true;
- const QString backup = generateBackupName(filename);
- QFile f(filename);
- const bool renamed = f.rename(backup);
- if (f.exists() && !renamed) {
- qCritical("Cannot rename %s to %s: %s", qPrintable(filename), qPrintable(backup),
- qPrintable(f.errorString()));
- return false;
- }
- m_backupFiles.append(qMakePair(filename, backup));
- return true;
- }
-
Q_SIGNALS:
void progressChanged(double progress);
@@ -139,12 +136,20 @@ public Q_SLOTS:
void onCompletedChanged(quint64 completed, quint64 total)
{
- emit progressChanged(double(completed) / total);
+ const double currentProgress = double(completed) / total
+ * scPerformProgressPart + scBackupProgressPart;
+
+ const int currentProgressPercentage = qRound(currentProgress * 100);
+ if (currentProgressPercentage > m_lastProgressPercentage) {
+ // Emit only full percentage changes
+ m_lastProgressPercentage = currentProgressPercentage;
+ emit progressChanged(currentProgress);
+ }
}
private:
- BackupFiles m_backupFiles;
QStringList m_extractedFiles;
+ int m_lastProgressPercentage;
};
class ExtractArchiveOperation::Worker : public QObject
@@ -153,10 +158,10 @@ class ExtractArchiveOperation::Worker : public QObject
Q_DISABLE_COPY(Worker)
public:
- Worker(const QString &archivePath, const QString &targetDir, Callback *callback)
+ Worker(const QString &archivePath, const QString &targetDir, quint64 totalEntries, Callback *callback)
: m_archivePath(archivePath)
, m_targetDir(targetDir)
- , m_canceled(false)
+ , m_totalEntries(totalEntries)
, m_callback(callback)
{}
@@ -166,7 +171,6 @@ Q_SIGNALS:
public Q_SLOTS:
void run()
{
- m_canceled = false;
m_archive.reset(ArchiveFactory::instance().create(m_archivePath));
if (!m_archive) {
emit finished(false, tr("Could not create handler object for archive \"%1\": \"%2\".")
@@ -177,29 +181,13 @@ public Q_SLOTS:
connect(m_archive.get(), &AbstractArchive::currentEntryChanged, m_callback, &Callback::onCurrentEntryChanged);
connect(m_archive.get(), &AbstractArchive::completedChanged, m_callback, &Callback::onCompletedChanged);
- if (!(m_archive->open(QIODevice::ReadOnly) && m_archive->isSupported())) {
+ if (!m_archive->open(QIODevice::ReadOnly)) {
emit finished(false, tr("Cannot open archive \"%1\" for reading: %2").arg(m_archivePath,
m_archive->errorString()));
return;
}
- const QVector<ArchiveEntry> entries = m_archive->list();
- if (entries.isEmpty()) {
- emit finished(false, tr("Error while reading contents of archive \"%1\": %2").arg(m_archivePath,
- m_archive->errorString()));
- return;
- }
- for (auto &entry : entries) {
- QString completeFilePath = m_targetDir + QDir::separator() + entry.path;
- if (!entry.isDirectory && !m_callback->prepareForFile(completeFilePath)) {
- emit finished(false, tr("Cannot prepare for file \"%1\"").arg(completeFilePath));
- return;
- }
- }
- if (m_canceled) {
- // For large archives the reading takes some time, and the user might have
- // canceled before we start the actual extracting.
- emit finished(false, tr("Extract for archive \"%1\" canceled.").arg(m_archivePath));
- } else if (!m_archive->extract(m_targetDir, entries.size())) {
+
+ if (!m_archive->extract(m_targetDir, m_totalEntries)) {
emit finished(false, tr("Error while extracting archive \"%1\": %2").arg(m_archivePath,
m_archive->errorString()));
} else {
@@ -214,11 +202,9 @@ public Q_SLOTS:
switch (status) {
case PackageManagerCore::Canceled:
- m_canceled = true;
m_archive->cancel();
break;
case PackageManagerCore::Failure:
- m_canceled = true;
m_archive->cancel();
break;
default: // ignore all other status values
@@ -229,8 +215,8 @@ public Q_SLOTS:
private:
QString m_archivePath;
QString m_targetDir;
+ quint64 m_totalEntries;
QScopedPointer<AbstractArchive> m_archive;
- bool m_canceled;
Callback *m_callback;
};
diff --git a/src/libs/installer/fakestopprocessforupdateoperation.cpp b/src/libs/installer/fakestopprocessforupdateoperation.cpp
index 36892eac7..bdd8625eb 100644
--- a/src/libs/installer/fakestopprocessforupdateoperation.cpp
+++ b/src/libs/installer/fakestopprocessforupdateoperation.cpp
@@ -31,6 +31,8 @@
#include "messageboxhandler.h"
#include "packagemanagercore.h"
+#include <QDir>
+
using namespace KDUpdater;
using namespace QInstaller;
@@ -68,7 +70,7 @@ bool FakeStopProcessForUpdateOperation::undoOperation()
return false;
}
- QStringList processes = arguments().at(0).split(QLatin1Char(','), QString::SkipEmptyParts);
+ QStringList processes = arguments().at(0).split(QLatin1Char(','), Qt::SkipEmptyParts);
for (int i = processes.count() - 1; i >= 0; --i) {
if (!core->isProcessRunning(processes.at(i)))
processes.removeAt(i);
@@ -79,11 +81,11 @@ bool FakeStopProcessForUpdateOperation::undoOperation()
if (processes.count() == 1) {
setError(UpdateOperation::UserDefinedError, tr("This process should be stopped before "
- "continuing: %1").arg(processes.first()));
+ "continuing: %1").arg(QDir::toNativeSeparators(processes.first())));
} else {
const QString sep = QString::fromWCharArray(L"\n \u2022 "); // Unicode bullet
setError(UpdateOperation::UserDefinedError, tr("These processes should be stopped before "
- "continuing: %1").arg(sep + processes.join(sep)));
+ "continuing: %1").arg(sep + QDir::toNativeSeparators(processes.join(sep))));
}
return false;
}
diff --git a/src/libs/installer/fakestopprocessforupdateoperation.h b/src/libs/installer/fakestopprocessforupdateoperation.h
index 6fd5da44b..546c6e95c 100644
--- a/src/libs/installer/fakestopprocessforupdateoperation.h
+++ b/src/libs/installer/fakestopprocessforupdateoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,10 +40,10 @@ class INSTALLER_EXPORT FakeStopProcessForUpdateOperation : public QObject, publi
public:
explicit FakeStopProcessForUpdateOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
}
diff --git a/src/libs/installer/fileguard.cpp b/src/libs/installer/fileguard.cpp
new file mode 100644
index 000000000..1f5fb46b7
--- /dev/null
+++ b/src/libs/installer/fileguard.cpp
@@ -0,0 +1,120 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "fileguard.h"
+
+#include <QTimer>
+
+using namespace QInstaller;
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::FileGuard
+ \brief The \c FileGuard class provides basic access serialization for file paths.
+
+ This class keeps a list of file paths that are locked from mutual
+ access. Attempting to lock them from another thread will fail until the
+ the locked path name is released.
+*/
+
+Q_GLOBAL_STATIC(FileGuard, globalFileGuard)
+
+/*!
+ Attempts to lock \a path. Returns \c true if the lock could be
+ acquired, \c false if another thread has already locked the path.
+*/
+bool FileGuard::tryLock(const QString &path)
+{
+ QMutexLocker _(&m_mutex);
+ if (path.isEmpty())
+ return false;
+
+ if (m_paths.contains(path))
+ return false;
+
+ m_paths.append(path);
+ return true;
+}
+
+/*!
+ Unlocks \a path.
+*/
+void FileGuard::release(const QString &path)
+{
+ QMutexLocker _(&m_mutex);
+ m_paths.removeOne(path);
+}
+
+/*!
+ Returns the application global instance.
+*/
+FileGuard *FileGuard::globalObject()
+{
+ return globalFileGuard;
+}
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::FileGuardLocker
+ \brief The \c FileGuardLocker class locks a file path and releases it on destruction.
+
+ A convenience class for locking a file path using the resource acquisition
+ is initialization (RAII) programming idiom.
+*/
+
+/*!
+ Constructs the object and attempts to lock \a path with \a guard. If the lock is already
+ held by another thread, this method will wait for it to become available.
+*/
+FileGuardLocker::FileGuardLocker(const QString &path, FileGuard *guard)
+ : m_path(path)
+ , m_guard(guard)
+{
+ if (!m_guard->tryLock(m_path)) {
+ QTimer timer;
+ QEventLoop loop;
+
+ QObject::connect(&timer, &QTimer::timeout, [&]() {
+ if (m_guard->tryLock(m_path))
+ loop.quit();
+ });
+
+ timer.start(100);
+ loop.exec();
+ }
+}
+
+/*!
+ Destructs the object and unlocks the locked file path.
+*/
+FileGuardLocker::~FileGuardLocker()
+{
+ m_guard->release(m_path);
+}
+
+
diff --git a/src/libs/installer/fileguard.h b/src/libs/installer/fileguard.h
new file mode 100644
index 000000000..a2f96a16e
--- /dev/null
+++ b/src/libs/installer/fileguard.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef FILEGUARD_H
+#define FILEGUARD_H
+
+#include "qinstallerglobal.h"
+
+#include <QMutex>
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT FileGuard
+{
+public:
+ FileGuard() = default;
+
+ bool tryLock(const QString &path);
+ void release(const QString &path);
+
+ static FileGuard *globalObject();
+
+private:
+ QMutex m_mutex;
+ QStringList m_paths;
+};
+
+class INSTALLER_EXPORT FileGuardLocker
+{
+public:
+ explicit FileGuardLocker(const QString &path, FileGuard *guard);
+ ~FileGuardLocker();
+
+private:
+ QString m_path;
+ FileGuard *m_guard;
+};
+
+} // namespace QInstaller
+
+#endif // FILEGUARD_H
diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp
index 8c015a1c2..044eeb34f 100644
--- a/src/libs/installer/fileutils.cpp
+++ b/src/libs/installer/fileutils.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -66,54 +66,62 @@ using namespace QInstaller;
/*!
\inmodule QtInstallerFramework
- \class QInstaller::TempDirDeleter
+ \class QInstaller::TempPathDeleter
\internal
*/
// -- TempDirDeleter
-TempDirDeleter::TempDirDeleter(const QString &path)
+TempPathDeleter::TempPathDeleter(const QString &path)
{
m_paths.insert(path);
}
-TempDirDeleter::TempDirDeleter(const QStringList &paths)
- : m_paths(paths.toSet())
+TempPathDeleter::TempPathDeleter(const QStringList &paths)
+ : m_paths(QSet<QString>(paths.begin(), paths.end()))
{
}
-TempDirDeleter::~TempDirDeleter()
+TempPathDeleter::~TempPathDeleter()
{
releaseAndDeleteAll();
}
-QStringList TempDirDeleter::paths() const
+QStringList TempPathDeleter::paths() const
{
- return m_paths.toList();
+ return m_paths.values();
}
-void TempDirDeleter::add(const QString &path)
+void TempPathDeleter::add(const QString &path)
{
m_paths.insert(path);
}
-void TempDirDeleter::add(const QStringList &paths)
+void TempPathDeleter::add(const QStringList &paths)
{
- m_paths += paths.toSet();
+ m_paths += QSet<QString>(paths.begin(), paths.end());
}
-void TempDirDeleter::releaseAndDeleteAll()
+void TempPathDeleter::releaseAndDeleteAll()
{
foreach (const QString &path, m_paths)
releaseAndDelete(path);
}
-void TempDirDeleter::releaseAndDelete(const QString &path)
+void TempPathDeleter::releaseAndDelete(const QString &path)
{
if (m_paths.contains(path)) {
try {
m_paths.remove(path);
- removeDirectory(path);
+ if (QFileInfo(path).isDir()) {
+ removeDirectory(path);
+ return;
+ }
+ QFile file(path);
+ if (file.exists() && !file.remove()) {
+ throw Error(QCoreApplication::translate("QInstaller",
+ "Cannot remove file \"%1\": %2").arg(file.fileName(), file.errorString()));
+ }
} catch (const Error &e) {
qCritical() << Q_FUNC_INFO << "Exception caught:" << e.message();
} catch (...) {
@@ -363,7 +371,7 @@ bool QInstaller::setDefaultFilePermissions(QFile *file, DefaultFilePermissions p
void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &targetDir)
{
Q_ASSERT(QFileInfo(sourceDir).isDir());
- Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
+ Q_ASSERT(!QFileInfo::exists(targetDir) || QFileInfo(targetDir).isDir());
if (!QDir().mkpath(targetDir)) {
throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\".")
.arg(QDir::toNativeSeparators(targetDir)));
@@ -394,7 +402,7 @@ void QInstaller::copyDirectoryContents(const QString &sourceDir, const QString &
void QInstaller::moveDirectoryContents(const QString &sourceDir, const QString &targetDir)
{
Q_ASSERT(QFileInfo(sourceDir).isDir());
- Q_ASSERT(!QFileInfo(targetDir).exists() || QFileInfo(targetDir).isDir());
+ Q_ASSERT(!QFileInfo::exists(targetDir) || QFileInfo(targetDir).isDir());
if (!QDir().mkpath(targetDir)) {
throw Error(QCoreApplication::translate("QInstaller", "Cannot create directory \"%1\".")
.arg(QDir::toNativeSeparators(targetDir)));
@@ -449,26 +457,82 @@ void QInstaller::mkpath(const QString &path)
/*!
\internal
+ Creates directory \a path including all parent directories. Return \c true on
+ success, \c false otherwise.
+
+ On Windows \c QDir::mkpath() doesn't check if the leading directories were created
+ elsewhere (i.e. in another thread) after the initial check that the given path
+ requires creating also parent directories, and returns \c false.
+
+ On Unix platforms this case is handled different by QFileSystemEngine though,
+ which checks for \c EEXIST error code in case any of the recursive directories
+ could not be created.
+
+ Compared to \c QInstaller::mkpath() and \c QDir::mkpath() this function checks if
+ each parent directory to-be-created were created elsewhere.
+*/
+bool QInstaller::createDirectoryWithParents(const QString &path)
+{
+ if (path.isEmpty())
+ return false;
+
+ QFileInfo dirInfo(path);
+ if (dirInfo.exists() && dirInfo.isDir())
+ return true;
+
+ // bail out if we are at the root directory
+ if (dirInfo.isRoot())
+ return false;
+
+ QDir dir(path);
+ if (dir.exists() || dir.mkdir(path))
+ return true;
+
+ // mkdir failed, try to create the parent directory
+ if (!createDirectoryWithParents(dirInfo.absolutePath()))
+ return false;
+
+ // now try again
+ if (dir.exists() || dir.mkdir(path))
+ return true;
+
+ // directory may be have also been created elsewhere
+ return (dirInfo.exists() && dirInfo.isDir());
+}
+
+/*!
+ \internal
+
Generates and returns a temporary file name. The name can start with
a template \a templ.
*/
QString QInstaller::generateTemporaryFileName(const QString &templ)
{
- static const QLatin1String staticPart("%1.tmp.XXXXXX");
-
- QTemporaryFile f;
- if (!templ.isEmpty())
- f.setFileTemplate(QString(staticPart).arg(templ));
-
- if (!f.open()) {
- if (!templ.isEmpty()) {
- throw Error(QCoreApplication::translate("QInstaller",
- "Cannot open temporary file for template %1: %2").arg(templ, f.errorString()));
- } else {
+ if (templ.isEmpty()) {
+ QTemporaryFile f;
+ if (!f.open()) {
throw Error(QCoreApplication::translate("QInstaller",
"Cannot open temporary file: %1").arg(f.errorString()));
}
+ return f.fileName();
}
+
+ static const QString characters = QLatin1String("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
+ QString suffix;
+ for (int i = 0; i < 5; ++i)
+ suffix += characters[QRandomGenerator::global()->generate() % characters.length()];
+
+ const QString tmp = QLatin1String("%1.tmp.%2.%3");
+ int count = 1;
+ while (QFile::exists(tmp.arg(templ, suffix).arg(count)))
+ ++count;
+
+ QFile f(tmp.arg(templ, suffix).arg(count));
+ if (!f.open(QIODevice::WriteOnly)) {
+ throw Error(QCoreApplication::translate("QInstaller",
+ "Cannot open temporary file for template %1: %2").arg(templ, f.errorString()));
+ }
+ f.remove();
return f.fileName();
}
@@ -670,7 +734,7 @@ quint64 QInstaller::fileSize(const QFileInfo &info)
bool QInstaller::isInBundle(const QString &path, QString *bundlePath)
{
#ifdef Q_OS_MACOS
- QFileInfo fi = QFileInfo(path).absoluteFilePath();
+ QFileInfo fi(QFileInfo(path).absoluteFilePath());
while (!fi.isRoot()) {
if (fi.isBundle()) {
if (bundlePath)
@@ -689,16 +753,24 @@ bool QInstaller::isInBundle(const QString &path, QString *bundlePath)
/*!
Replaces the path \a before with the path \a after at the beginning of \a path and returns
the replaced path. If \a before cannot be found in \a path, the original value is returned.
+ If \a cleanPath is \c true, path is returned with directory separators normalized (that is,
+ platform-native separators converted to "/") and redundant ones removed, and "."s and ".."s
+ resolved (as far as possible). If \a cleanPath is \c false, path is returned as such. Default
+ value is \c true.
*/
-QString QInstaller::replacePath(const QString &path, const QString &before, const QString &after)
+QString QInstaller::replacePath(const QString &path, const QString &before, const QString &after, bool cleanPath)
{
if (path.isEmpty() || before.isEmpty())
return path;
QString pathToPatch = QDir::cleanPath(path);
const QString pathToReplace = QDir::cleanPath(before);
- if (pathToPatch.startsWith(pathToReplace))
- return QDir::cleanPath(after) + pathToPatch.mid(pathToReplace.size());
+ if (pathToPatch.startsWith(pathToReplace)) {
+ if (cleanPath)
+ return QDir::cleanPath(after) + pathToPatch.mid(pathToReplace.size());
+ else
+ return after + path.mid(before.size());
+ }
return path;
}
@@ -792,8 +864,8 @@ void QInstaller::copyConfigChildElements(QDomDocument &dom, const QDomNodeList &
// Filename may also contain a path relative to source directory but we
// copy it strictly into target directory without extra paths
- const QString newName = domElement.text()
- .replace(QRegExp(QLatin1String("\\\\|/|\\.|:")), QLatin1String("_"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/|\\.|:"));
+ const QString newName = domElement.text().replace(regex, QLatin1String("_"));
const QString targetFile = targetDir + QDir::separator() + newName;
const QFileInfo elementFileInfo = QFileInfo(sourceDir, domElement.text());
diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h
index ac3f95098..3c995937c 100644
--- a/src/libs/installer/fileutils.h
+++ b/src/libs/installer/fileutils.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -49,12 +49,12 @@ enum DefaultFilePermissions {
Executable = 0x7755
};
-class INSTALLER_EXPORT TempDirDeleter
+class INSTALLER_EXPORT TempPathDeleter
{
public:
- explicit TempDirDeleter(const QString &path);
- explicit TempDirDeleter(const QStringList &paths = QStringList());
- ~TempDirDeleter();
+ explicit TempPathDeleter(const QString &path);
+ explicit TempPathDeleter(const QStringList &paths = QStringList());
+ ~TempPathDeleter();
QStringList paths() const;
@@ -65,7 +65,7 @@ public:
void releaseAndDelete(const QString &path);
private:
- Q_DISABLE_COPY(TempDirDeleter)
+ Q_DISABLE_COPY(TempPathDeleter)
QSet<QString> m_paths;
};
@@ -89,11 +89,15 @@ private:
void INSTALLER_EXPORT mkdir(const QString &path);
void INSTALLER_EXPORT mkpath(const QString &path);
+ bool INSTALLER_EXPORT createDirectoryWithParents(const QString &path);
+#ifdef Q_OS_MACOS
+ void INSTALLER_EXPORT mkalias(const QString &path, const QString &alias);
+#endif
quint64 INSTALLER_EXPORT fileSize(const QFileInfo &info);
bool INSTALLER_EXPORT isInBundle(const QString &path, QString *bundlePath = 0);
- QString replacePath(const QString &path, const QString &pathBefore, const QString &pathAfter);
+ QString replacePath(const QString &path, const QString &pathBefore, const QString &pathAfter, bool cleanPath = true);
void replaceHighDpiImage(QString &imagePath);
void INSTALLER_EXPORT trimmedCopyConfigData(const QString &source, const QString &target, const QStringList &elementsToRemoveTags);
diff --git a/src/libs/installer/fileutils_mac.mm b/src/libs/installer/fileutils_mac.mm
new file mode 100644
index 000000000..d3792d510
--- /dev/null
+++ b/src/libs/installer/fileutils_mac.mm
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "fileutils.h"
+
+#include "errors.h"
+
+#include <QCoreApplication>
+
+#include <objc/objc.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSError.h>>
+
+namespace QInstaller {
+
+/*!
+ \internal
+
+ Creates a bookmark variant of Finder alias from target \a path to \a alias.
+ Throws \c Error on failure.
+*/
+void mkalias(const QString &path, const QString &alias)
+{
+ NSURL *targetUrl = [NSURL fileURLWithPath:path.toNSString()];
+ NSURL *aliasUrl = [NSURL fileURLWithPath:alias.toNSString()];
+
+ NSError *error = nil;
+ NSData *data = [targetUrl bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile
+ includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
+
+ if (data != nil) {
+ BOOL success = [NSURL writeBookmarkData:data toURL:aliasUrl
+ options:NSURLBookmarkCreationSuitableForBookmarkFile error:&error];
+ if (success == NO) {
+ throw Error(QCoreApplication::translate("QInstaller",
+ "Cannot create alias from \"%1\" to \"%2\": %3.")
+ .arg(path, alias, QString::fromNSString(error.localizedDescription))
+ );
+ }
+ } else {
+ throw Error(QCoreApplication::translate("QInstaller",
+ "Could not get bookmark from URL \"%1\": %2.").arg(
+ QString::fromNSString(targetUrl.absoluteString),
+ QString::fromNSString(error.localizedDescription)
+ )
+ );
+ }
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/genericdatacache.cpp b/src/libs/installer/genericdatacache.cpp
new file mode 100644
index 000000000..a1e31ccfe
--- /dev/null
+++ b/src/libs/installer/genericdatacache.cpp
@@ -0,0 +1,695 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "genericdatacache.h"
+
+#include "errors.h"
+#include "fileutils.h"
+#include "globals.h"
+#include "metadata.h"
+#include "updater.h"
+
+#include <QDir>
+#include <QDirIterator>
+#include <QtConcurrent>
+
+namespace QInstaller {
+
+static const QLatin1String scManifestFile("manifest.json");
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::CacheableItem
+ \brief The CacheableItem is a pure virtual class that defines an interface for
+ a type suited for storage with the \l{GenericDataCache} class.
+*/
+
+/*!
+ \fn QInstaller::CacheableItem::path() const
+
+ Returns the path of this item. A subclass may override this method.
+*/
+
+/*!
+ \fn QInstaller::CacheableItem::setPath(const QString &path)
+
+ Sets the path of the item to \a path. A subclass may override this method.
+*/
+
+/*!
+ \fn QInstaller::CacheableItem::checksum() const
+
+ Returns the checksum of this item. A subclass must implement this method.
+*/
+
+/*!
+ \fn QInstaller::CacheableItem::isValid() const
+
+ Returns \c true if this item is valid, \c false otherwise.
+ A subclass must implement this method.
+*/
+
+/*!
+ \fn QInstaller::CacheableItem::isActive() const
+
+ Returns \c true if this item is an actively used cache item, \c false otherwise.
+ This information is used as a hint for filtering obsolete entries, an active item
+ can never be obsolete.
+
+ A subclass must implement this method.
+*/
+
+/*!
+ \fn QInstaller::CacheableItem::obsoletes(CacheableItem *other)
+
+ Returns \c true if the calling item obsoletes \a other item, \c false otherwise.
+ This method is used for filtering obsolete entries from the cache.
+
+ A subclass must implement this method.
+*/
+
+/*!
+ Virtual destructor for \c CacheableItem.
+*/
+CacheableItem::~CacheableItem()
+{
+}
+
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::GenericDataCache
+ \brief The GenericDataCache is a template class for a checksum based storage
+ of items on disk.
+
+ GenericDataCache\<T\> manages a cache storage for a set \l{path()}, which contains
+ a subdirectory for each registered item. An item of type \c T should implement
+ methods declared in the \l{CacheableItem} interface. The GenericDataCache\<T\> class can
+ still be explicitly specialized to use the derived type as a template argument, to
+ allow retrieving items as the derived type without casting.
+
+ Each cache has a manifest file in its root directory, which lists the version
+ and wrapped type of the cache, and all its items. The file is updated automatically
+ when the cache object is destructed, or it can be updated periodically by
+ calling \l{sync()}.
+*/
+
+/*!
+ \enum GenericDataCache::RegisterMode
+ This enum holds the possible values for modes of registering items to cache.
+
+ \value Copy
+ The contents of the item are copied to the cache.
+ \value Move
+ The contents of the item are move to the cache.
+*/
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::GenericDataCache()
+
+ Constructs a new empty cache. The cache is invalid until set with a
+ path and initialized.
+*/
+template <typename T>
+GenericDataCache<T>::GenericDataCache()
+ : m_version(QLatin1String("1.0.0"))
+ , m_invalidated(true)
+{
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::GenericDataCache(const QString &path, const QString &type, const QString &version)
+
+ Constructs a cache to \a path with the given \a type and \a version.
+ The cache is initialized automatically.
+*/
+template <typename T>
+GenericDataCache<T>::GenericDataCache(const QString &path, const QString &type,
+ const QString &version)
+ : m_path(path)
+ , m_type(type)
+ , m_version(version)
+ , m_invalidated(true)
+{
+ initialize();
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::~GenericDataCache()
+
+ Deletes the cache object. Item contents on disk are kept.
+*/
+template <typename T>
+GenericDataCache<T>::~GenericDataCache()
+{
+ if (m_invalidated)
+ return;
+
+ toDisk();
+ invalidate();
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::setType(const QString &type)
+
+ Sets the name of the wrapped type to \a type. This is used for determining if an
+ existing cache holds items of the same type. Trying to load cached items with mismatching
+ type results in discarding the old items. Optional.
+*/
+template<typename T>
+void GenericDataCache<T>::setType(const QString &type)
+{
+ QMutexLocker _(&m_mutex);
+ m_type = type;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::setVersion(const QString &version)
+
+ Sets the version of the cache to \a version. Loading from a cache with different
+ expected version discards the old items. The version property defaults to \c{1.0.0}.
+*/
+template<typename T>
+void GenericDataCache<T>::setVersion(const QString &version)
+{
+ QMutexLocker _(&m_mutex);
+ m_version = version;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::initialize()
+
+ Initializes a cache. Creates a new directory for the path configured for
+ this cache if it does not exist, and loads any previously cached items from
+ the directory. The cache directory is locked for access by this process only.
+ Returns \c true on success, \c false otherwise.
+*/
+template <typename T>
+bool GenericDataCache<T>::initialize()
+{
+ QMutexLocker _(&m_mutex);
+ Q_ASSERT(m_items.isEmpty());
+
+ if (m_path.isEmpty()) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot initialize cache with empty path."));
+ return false;
+ }
+
+ QDir directory(m_path);
+ if (!directory.exists() && !directory.mkpath(m_path)) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot create directory \"%1\" for cache.").arg(m_path));
+ return false;
+ }
+
+ if (m_lock && !m_lock->unlock()) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot initialize cache: %1").arg(m_lock->errorString()));
+ return false;
+ }
+
+ m_lock.reset(new KDUpdater::LockFile(m_path + QLatin1String("/cache.lock")));
+ if (!m_lock->lock()) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot initialize cache: %1").arg(m_lock->errorString()));
+ return false;
+ }
+
+ if (!fromDisk())
+ return false;
+
+ m_invalidated = false;
+ return true;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::clear()
+
+ Removes all items from the cache and deletes their contents on disk. If
+ the cache directory becomes empty, it is also deleted. The cache becomes
+ invalid after this action, even in case of error while clearing. In that
+ case already deleted items will be lost. Returns \c true on success,
+ \c false otherwise.
+*/
+template <typename T>
+bool GenericDataCache<T>::clear()
+{
+ QMutexLocker _(&m_mutex);
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot clear invalidated cache."));
+ return false;
+ }
+
+ QFile manifestFile(m_path + QDir::separator() + scManifestFile);
+ if (manifestFile.exists() && !manifestFile.remove()) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove manifest file: %1").arg(manifestFile.errorString()));
+ invalidate();
+ return false;
+ }
+
+ bool success = true;
+ for (T *item : qAsConst(m_items)) {
+ try {
+ QInstaller::removeDirectory(item->path());
+ } catch (const Error &e) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Error while clearing cache: %1").arg(e.message()));
+ success = false;
+ }
+ }
+
+ invalidate();
+ QDir().rmdir(m_path);
+ return success;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::sync()
+
+ Synchronizes the contents of the cache to its manifest file. Returns \c true
+ if the manifest file was updates successfully, \c false otherwise.
+*/
+template<typename T>
+bool GenericDataCache<T>::sync()
+{
+ QMutexLocker _(&m_mutex);
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot synchronize invalidated cache."));
+ return false;
+ }
+ return toDisk();
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::isValid() const
+
+ Returns \c true if the cache is valid, \c false otherwise. A cache is considered
+ valid when it is initialized to a set path.
+*/
+template<typename T>
+bool GenericDataCache<T>::isValid() const
+{
+ QMutexLocker _(&m_mutex);
+ return !m_invalidated;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::errorString() const
+
+ Returns a string representing the last error with the cache.
+*/
+template<typename T>
+QString GenericDataCache<T>::errorString() const
+{
+ QMutexLocker _(&m_mutex);
+ return m_error;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::path() const
+
+ Returns the path of the cache on disk.
+*/
+template <typename T>
+QString GenericDataCache<T>::path() const
+{
+ QMutexLocker _(&m_mutex);
+ return m_path;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::setPath(const QString &path)
+
+ Sets a new \a path for the cache and invalidates current items. Saves the information
+ of the old cache to its manifest file.
+*/
+template <typename T>
+void GenericDataCache<T>::setPath(const QString &path)
+{
+ QMutexLocker _(&m_mutex);
+ if (!m_invalidated)
+ toDisk();
+
+ m_path = path;
+ invalidate();
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::items() const
+
+ Returns a list of cached items.
+*/
+template <typename T>
+QList<T *> GenericDataCache<T>::items() const
+{
+ QMutexLocker _(&m_mutex);
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot retrieve items from invalidated cache."));
+ return QList<T *>();
+ }
+ return m_items.values();
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::itemByChecksum(const QByteArray &checksum) const
+
+ Returns an item that matches the \a checksum or \c nullptr in case
+ no such item is cached.
+*/
+template <typename T>
+T *GenericDataCache<T>::itemByChecksum(const QByteArray &checksum) const
+{
+ QMutexLocker _(&m_mutex);
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot retrieve item from invalidated cache."));
+ return nullptr;
+ }
+ return m_items.value(checksum);
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::itemByPath(const QString &path) const
+
+ Returns an item from the \a path or \c nullptr in case no such item
+ is cached. Depending on the size of the cache, this can be much
+ slower than retrieving an item with \l{itemByChecksum()}.
+*/
+template <typename T>
+T *GenericDataCache<T>::itemByPath(const QString &path) const
+{
+ QMutexLocker _(&m_mutex);
+ auto it = std::find_if(m_items.constBegin(), m_items.constEnd(),
+ [&](T *item) {
+ return (QDir::fromNativeSeparators(path) == QDir::fromNativeSeparators(item->path()));
+ }
+ );
+ if (it != m_items.constEnd())
+ return it.value();
+
+ return nullptr;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::registerItem(T *item, bool replace, RegisterMode mode)
+
+ Registers the \a item to the cache. If \a replace is set to \c true,
+ the new \a item replaces a previous item with the same checksum.
+
+ The cache takes ownership of the object pointed by \a item. The contents of the
+ item are copied or moved to the cache with a subdirectory name that matches the checksum
+ of the item. The \a mode decides how the contents of the item are registered, either by
+ copying or moving.
+
+ Returns \c true on success or \c false if the item could not be registered.
+*/
+template <typename T>
+bool GenericDataCache<T>::registerItem(T *item, bool replace, RegisterMode mode)
+{
+ QMutexLocker _(&m_mutex);
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot register item to invalidated cache."));
+ return false;
+ }
+ if (!item) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot register null item."));
+ return false;
+ }
+ if (!item->isValid()) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot register invalid item with checksum %1").arg(QLatin1String(item->checksum())));
+ return false;
+ }
+ if (m_items.contains(item->checksum())) {
+ if (replace) {// replace existing item including contents on disk
+ remove(item->checksum());
+ } else {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot register item with checksum %1. An item with the same checksum "
+ "already exists in cache.").arg(QLatin1String(item->checksum())));
+ return false;
+ }
+ }
+
+ const QString newPath = m_path + QDir::separator() + QString::fromLatin1(item->checksum());
+ try {
+ // A directory is in the way but it isn't registered to the current cache, remove.
+ QDir dir;
+ if (dir.exists(newPath))
+ QInstaller::removeDirectory(newPath);
+
+ switch (mode) {
+ case Copy:
+ QInstaller::copyDirectoryContents(item->path(), newPath);
+ break;
+ case Move:
+ // First, try moving the top level directory
+ if (!dir.rename(item->path(), newPath)) {
+ qCDebug(lcDeveloperBuild) << "Failed to rename directory" << item->path()
+ << "to" << newPath << ". Trying again.";
+ // If that does not work, fallback to moving the contents one by one
+ QInstaller::moveDirectoryContents(item->path(), newPath);
+ }
+ break;
+ default:
+ throw Error(QCoreApplication::translate("GenericDataCache",
+ "Unknown register mode selected!"));
+ }
+ } catch (const Error &e) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Error while copying item to path \"%1\": %2").arg(newPath, e.message()));
+ return false;
+ }
+
+ item->setPath(newPath);
+ if (item->isValid()) {
+ m_items.insert(item->checksum(), item);
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::removeItem(const QByteArray &checksum)
+
+ Removes the item specified by \a checksum from the cache and deletes the
+ contents of the item from disk. Returns \c true if the item
+ was removed successfully, \c false otherwise.
+*/
+template <typename T>
+bool GenericDataCache<T>::removeItem(const QByteArray &checksum)
+{
+ QMutexLocker _(&m_mutex);
+ return remove(checksum);
+}
+
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::obsoleteItems() const
+
+ Returns items considered obsolete from the cache.
+*/
+template<typename T>
+QList<T *> GenericDataCache<T>::obsoleteItems() const
+{
+ QMutexLocker _(&m_mutex);
+ const QList<T *> obsoletes = QtConcurrent::blockingFiltered(m_items.values(),
+ [&](T *item1) {
+ if (item1->isActive()) // We can skip the iteration for active entries
+ return false;
+
+ for (T *item2 : qAsConst(m_items)) {
+ if (item2->obsoletes(item1))
+ return true;
+ }
+ return false;
+ }
+ );
+ return obsoletes;
+}
+
+/*!
+ \internal
+
+ Marks the cache invalid and clears all items. The contents
+ on disk are not deleted. Releases the lock file of the cache.
+*/
+template <typename T>
+void GenericDataCache<T>::invalidate()
+{
+ if (!m_items.isEmpty()) {
+ qDeleteAll(m_items);
+ m_items.clear();
+ }
+ if (m_lock && !m_lock->unlock()) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Error while invalidating cache: %1").arg(m_lock->errorString()));
+ }
+ m_invalidated = true;
+}
+
+/*!
+ \internal
+
+ Sets the current error string to \a error and prints it as a warning to the console.
+*/
+template <typename T>
+void GenericDataCache<T>::setErrorString(const QString &error) const
+{
+ m_error = error;
+ qCWarning(QInstaller::lcInstallerInstallLog) << error;
+}
+
+/*!
+ \internal
+
+ Reads the manifest file of the cache if one exists, and populates the internal
+ hash from the file contents. Returns \c true if the manifests was read successfully
+ or if the reading was omitted. This is the case if the file does not exist yet, or
+ the type or version of the manifest does not match the current cache object. In case
+ of mismatch the old items are not restored. Returns \c false otherwise.
+*/
+template<typename T>
+bool GenericDataCache<T>::fromDisk()
+{
+ QFile manifestFile(m_path + QDir::separator() + scManifestFile);
+ if (!manifestFile.exists()) // Not yet created
+ return true;
+
+ if (!manifestFile.open(QIODevice::ReadOnly)) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot open manifest file: %1").arg(manifestFile.errorString()));
+ return false;
+ }
+
+ const QByteArray manifestData = manifestFile.readAll();
+ const QJsonDocument manifestJsonDoc(QJsonDocument::fromJson(manifestData));
+ const QJsonObject docJsonObject = manifestJsonDoc.object();
+
+ const QJsonValue type = docJsonObject.value(QLatin1String("type"));
+ if (type.toString() != m_type) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Discarding existing items from cache of type:"
+ << type.toString() << ". New type:" << m_type;
+ return true;
+ }
+
+ const QJsonValue version = docJsonObject.value(QLatin1String("version"));
+ if (KDUpdater::compareVersion(version.toString(), m_version) != 0) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Discarding existing items from cache with version:"
+ << version.toString() << ". New version:" << m_version;
+ return true;
+ }
+
+ const QJsonArray itemsJsonArray = docJsonObject.value(QLatin1String("items")).toArray();
+ for (const auto &itemJsonValue : itemsJsonArray) {
+ const QString checksum = itemJsonValue.toString();
+
+ std::unique_ptr<T> item(new T(m_path + QDir::separator() + checksum));
+ m_items.insert(checksum.toLatin1(), item.release());
+
+ // The cache directory may contain other entries (unrelated directories or
+ // invalid old cache items) which we don't care about, unless registering
+ // a new entry requires overwriting them.
+ }
+ return true;
+}
+
+/*!
+ \internal
+
+ Writes the manifest file with the contents of the internal item hash.
+ Returns \c true on success, \c false otherwise.
+*/
+template<typename T>
+bool GenericDataCache<T>::toDisk()
+{
+ QFile manifestFile(m_path + QDir::separator() + scManifestFile);
+ if (!manifestFile.open(QIODevice::WriteOnly)) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot open manifest file: %1").arg(manifestFile.errorString()));
+ return false;
+ }
+
+ QJsonArray itemsJsonArray;
+ const QList<QByteArray> keys = m_items.keys();
+ for (const QByteArray &key : keys)
+ itemsJsonArray.append(QJsonValue(QLatin1String(key)));
+
+ QJsonObject docJsonObject;
+ docJsonObject.insert(QLatin1String("items"), itemsJsonArray);
+ docJsonObject.insert(QLatin1String("version"), m_version);
+ if (!m_type.isEmpty())
+ docJsonObject.insert(QLatin1String("type"), m_type);
+
+ QJsonDocument manifestJsonDoc;
+ manifestJsonDoc.setObject(docJsonObject);
+ if (manifestFile.write(manifestJsonDoc.toJson()) == -1) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot write contents for manifest file: %1").arg(manifestFile.errorString()));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+*/
+template<typename T>
+bool GenericDataCache<T>::remove(const QByteArray &checksum)
+{
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove item from invalidated cache."));
+ return false;
+ }
+ QScopedPointer<T> item(m_items.take(checksum));
+ if (!item) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove item specified by checksum %1: no such item exists.").arg(QLatin1String(checksum)));
+ return false;
+ }
+
+ try {
+ QInstaller::removeDirectory(item->path());
+ } catch (const Error &e) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Error while removing directory \"%1\": %2").arg(item->path(), e.message()));
+ return false;
+ }
+ return true;
+}
+
+template class GenericDataCache<Metadata>;
+
+} // namespace QInstaller
diff --git a/src/libs/installer/genericdatacache.h b/src/libs/installer/genericdatacache.h
new file mode 100644
index 000000000..94085502c
--- /dev/null
+++ b/src/libs/installer/genericdatacache.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef GENERICDATACACHE_H
+#define GENERICDATACACHE_H
+
+#include "installer_global.h"
+#include "lockfile.h"
+
+#include <QHash>
+#include <QMutex>
+#include <QScopedPointer>
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT CacheableItem
+{
+public:
+ CacheableItem() = default;
+ explicit CacheableItem(const QString &path)
+ : m_path(path)
+ {}
+ virtual ~CacheableItem() = 0;
+
+ virtual QString path() const { return m_path; }
+ virtual void setPath(const QString &path) { m_path = path; }
+
+ virtual QByteArray checksum() const = 0;
+ virtual bool isValid() const = 0;
+
+ virtual bool isActive() const = 0;
+ virtual bool obsoletes(CacheableItem *other) = 0;
+
+private:
+ QString m_path;
+};
+
+template <typename T>
+class INSTALLER_EXPORT GenericDataCache
+{
+public:
+ enum RegisterMode {
+ Copy = 0,
+ Move = 1
+ };
+
+ GenericDataCache();
+ explicit GenericDataCache(const QString &path, const QString &type, const QString &version);
+ virtual ~GenericDataCache();
+
+ void setType(const QString &type);
+ void setVersion(const QString &version);
+
+ bool initialize();
+ bool clear();
+ bool sync();
+
+ bool isValid() const;
+ QString errorString() const;
+
+ QString path() const;
+ void setPath(const QString &path);
+
+ QList<T *> items() const;
+ T *itemByChecksum(const QByteArray &checksum) const;
+ T *itemByPath(const QString &path) const;
+
+ bool registerItem(T *item, bool replace = false, RegisterMode mode = Copy);
+ bool removeItem(const QByteArray &checksum);
+
+ QList<T *> obsoleteItems() const;
+
+private:
+ void invalidate();
+ void setErrorString(const QString &error) const;
+
+ bool fromDisk();
+ bool toDisk();
+
+ bool remove(const QByteArray &checksum);
+
+private:
+ QScopedPointer<KDUpdater::LockFile> m_lock;
+ mutable QMutex m_mutex;
+
+ QHash<QByteArray, T *> m_items;
+ QString m_path;
+ QString m_type;
+ QString m_version;
+ mutable QString m_error;
+
+ bool m_invalidated;
+};
+
+} // namespace QInstaller
+
+#endif // GENERICDATACACHE_H
diff --git a/src/libs/installer/globals.cpp b/src/libs/installer/globals.cpp
index adf1d2f6e..3fd084768 100644
--- a/src/libs/installer/globals.cpp
+++ b/src/libs/installer/globals.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,6 +30,14 @@
#include "globals.h"
+#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
+#include <termios.h>
+#include <unistd.h>
+#elif defined(Q_OS_WIN)
+#include <conio.h>
+#endif
+#include <iostream>
+
const char IFW_SERVER[] = "ifw.server";
const char IFW_INSTALLER_INSTALLLOG[] = "ifw.installer.installlog";
const char IFW_DEVELOPER_BUILD[] = "ifw.developer.build";
@@ -60,6 +68,12 @@ namespace QInstaller
\internal
*/
+/*!
+ \fn inline QInstaller::splitStringWithComma(const QString &value())
+ Splits \a value into substrings wherever comma occurs, and returns the list of those strings.
+ \internal
+*/
+
Q_LOGGING_CATEGORY(lcServer, IFW_SERVER)
Q_LOGGING_CATEGORY(lcInstallerInstallLog, IFW_INSTALLER_INSTALLLOG)
Q_LOGGING_CATEGORY(lcProgressIndicator, IFW_PROGRESS_INDICATOR)
@@ -72,17 +86,19 @@ QStringList loggingCategories()
{
static QStringList categories = QStringList()
<< QLatin1String(IFW_INSTALLER_INSTALLLOG)
- << QLatin1String(IFW_SERVER);
+ << QLatin1String(IFW_SERVER)
+ << QLatin1String(IFW_DEVELOPER_BUILD)
+ << QLatin1String("js");
return categories;
}
-Q_GLOBAL_STATIC_WITH_ARGS(QRegExp, staticCommaRegExp, (QLatin1String("(, |,)")));
+Q_GLOBAL_STATIC_WITH_ARGS(QRegularExpression, staticCommaRegExp, (QLatin1String("(, |,)")));
/*!
\internal
*/
-QRegExp commaRegExp()
+QRegularExpression commaRegExp()
{
return *staticCommaRegExp();
}
@@ -111,5 +127,52 @@ QString enumToString(const QMetaObject& metaObject, const char *enumerator, int
return value;
}
+void askForCredentials(QString *username, QString *password, const QString &usernameTitle, const QString &passwordTitle)
+{
+ std::string usernameStdStr;
+ std::string passwordStdStr;
+
+ std::cout << qPrintable(usernameTitle);
+ std::cin >> usernameStdStr;
+
+ std::cout << qPrintable(passwordTitle);
+#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
+ termios oldTerm;
+ termios term;
+
+ // Turn off echoing
+ tcgetattr(STDIN_FILENO, &oldTerm);
+ term = oldTerm;
+ term.c_lflag &= ~ECHO;
+ tcsetattr(STDIN_FILENO, TCSANOW, &term);
+
+ std::cin >> passwordStdStr;
+
+ // Clear input buffer
+ std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+
+ // Restore old attributes
+ tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
+#elif defined(Q_OS_WIN)
+ char ch;
+ while ((ch = _getch()) != '\r') { // Return key
+ if (ch == '\b') { // Backspace key
+ if (!passwordStdStr.empty())
+ passwordStdStr.pop_back();
+ } else {
+ passwordStdStr.push_back(ch);
+ }
+ }
+ // Clear input buffer
+ int c;
+ while ((c = getchar()) != '\n' && c != EOF);
+
+#endif
+ std::cout << "\n";
+
+ *username = username->fromStdString(usernameStdStr);
+ *password = password->fromStdString(passwordStdStr);
+}
+
} // namespace QInstaller
diff --git a/src/libs/installer/globals.h b/src/libs/installer/globals.h
index b22331e2c..2d119048b 100644
--- a/src/libs/installer/globals.h
+++ b/src/libs/installer/globals.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,7 +30,7 @@
#include "installer_global.h"
-#include <QRegExp>
+#include <QRegularExpression>
#include <QLoggingCategory>
namespace QInstaller {
@@ -43,11 +43,24 @@ INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcDeveloperBuild)
QStringList INSTALLER_EXPORT loggingCategories();
-QRegExp INSTALLER_EXPORT commaRegExp();
+QRegularExpression INSTALLER_EXPORT commaRegExp();
+inline QStringList splitStringWithComma(const QString &value) {
+ if (!value.isEmpty())
+ return value.split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+ return QStringList();
+}
QString htmlToString(const QString &html);
QString enumToString(const QMetaObject& metaObject, const char *enumerator, int key);
+template <typename T, template<typename> typename C>
+QSet<T> toQSet(const C<T> &container)
+{
+ return QSet<T>(container.begin(), container.end());
+}
+
+void askForCredentials(QString *username, QString *password, const QString &usernameTitle, const QString &passwordTitle);
+
} // QInstaller
#endif // GLOBALS_H
diff --git a/src/libs/installer/globalsettingsoperation.cpp b/src/libs/installer/globalsettingsoperation.cpp
index dc085f4b6..6ca50f96f 100644
--- a/src/libs/installer/globalsettingsoperation.cpp
+++ b/src/libs/installer/globalsettingsoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -77,7 +77,7 @@ bool GlobalSettingsOperation::performOperation()
bool GlobalSettingsOperation::undoOperation()
{
- if (parseUndoOperationArguments().count() > 0)
+ if (skipUndoOperation())
return true;
const QStringList args = parsePerformOperationArguments();
@@ -128,7 +128,7 @@ QSettingsWrapper *GlobalSettingsOperation::setup(QString *key, QString *value, c
const QString &filename = arguments.at(0);
*key = arguments.at(1);
*value = arguments.at(2);
- return new QSettingsWrapper(filename, QSettingsWrapper::NativeFormat);
+ return new QSettingsWrapper(filename, QSettings::NativeFormat);
}
return nullptr;
diff --git a/src/libs/installer/globalsettingsoperation.h b/src/libs/installer/globalsettingsoperation.h
index fe5d14edb..473497614 100644
--- a/src/libs/installer/globalsettingsoperation.h
+++ b/src/libs/installer/globalsettingsoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,10 +40,10 @@ class INSTALLER_EXPORT GlobalSettingsOperation : public Operation
public:
explicit GlobalSettingsOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
private:
QSettingsWrapper *setup(QString *key, QString *value, const QStringList &args);
diff --git a/src/libs/installer/graph.h b/src/libs/installer/graph.h
index 5f330e69b..49da9c2ed 100644
--- a/src/libs/installer/graph.h
+++ b/src/libs/installer/graph.h
@@ -63,7 +63,7 @@ public:
QList<T> edges(const T &node) const
{
- return m_graph.value(node).toList();
+ return m_graph.value(node).values();
}
void addEdge(const T &node, const T &edge)
diff --git a/src/libs/installer/init.cpp b/src/libs/installer/init.cpp
index 4aa65296f..f47040d93 100644
--- a/src/libs/installer/init.cpp
+++ b/src/libs/installer/init.cpp
@@ -49,7 +49,9 @@
#include "consumeoutputoperation.h"
#include "loggingutils.h"
+#ifdef IFW_LIB7Z
#include "lib7z_facade.h"
+#endif
#include "updateoperationfactory.h"
#include "filedownloaderfactory.h"
@@ -72,8 +74,9 @@ static void initResources()
*/
void QInstaller::init()
{
+#ifdef IFW_LIB7Z
Lib7z::initSevenZ();
-
+#endif
#if defined(QT_STATIC)
::initResources();
#endif
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index ed7d739ed..ff7a0eed2 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -4,7 +4,6 @@ INCLUDEPATH += . ..
CONFIG += staticlib
-include(../7zip/7zip.pri)
include(../kdtools/kdtools.pri)
include(../ifwtools/ifwtools.pri)
include(../../../installerfw.pri)
@@ -40,17 +39,27 @@ QT += \
widgets \
core-private \
qml-private
-win32:QT += winextras
+
+win32:lessThan(QT_MAJOR_VERSION, 6):QT += winextras
+
+greaterThan(QT_MAJOR_VERSION, 5):QT += core5compat
HEADERS += packagemanagercore.h \
aspectratiolabel.h \
+ calculatorbase.h \
+ componentalias.h \
componentsortfilterproxymodel.h \
+ concurrentoperationrunner.h \
+ genericdatacache.h \
loggingutils.h \
+ metadata.h \
+ metadatacache.h \
packagemanagercore_p.h \
packagemanagergui.h \
binaryformat.h \
binaryformatengine.h \
binaryformatenginehandler.h \
+ fileguard.h \
repository.h \
utils.h \
errors.h \
@@ -91,7 +100,6 @@ HEADERS += packagemanagercore.h \
constants.h \
packagemanagerproxyfactory.h \
createlocalrepositoryoperation.h \
- lib7z_facade.h \
link.h \
createlinkoperation.h \
packagemanagercoredata.h \
@@ -105,7 +113,6 @@ HEADERS += packagemanagercore.h \
copyfiletask.h \
downloadfiletask.h \
downloadfiletask_p.h \
- unziptask.h \
observer.h \
runextensions.h \
metadatajob.h \
@@ -132,27 +139,31 @@ HEADERS += packagemanagercore.h \
keepaliveobject.h \
systeminfo.h \
packagesource.h \
- lib7z_guid.h \
- lib7z_create.h \
- lib7z_extract.h \
- lib7z_list.h \
repositorycategory.h \
componentselectionpage_p.h \
commandlineparser.h \
commandlineparser_p.h \
abstractarchive.h \
directoryguard.h \
- lib7zarchive.h \
- archivefactory.h
+ archivefactory.h \
+ operationtracer.h \
+ customcombobox.h
SOURCES += packagemanagercore.cpp \
abstractarchive.cpp \
archivefactory.cpp \
aspectratiolabel.cpp \
+ calculatorbase.cpp \
+ componentalias.cpp \
+ concurrentoperationrunner.cpp \
directoryguard.cpp \
- lib7zarchive.cpp \
+ fileguard.cpp \
componentsortfilterproxymodel.cpp \
+ genericdatacache.cpp \
loggingutils.cpp \
+ metadata.cpp \
+ metadatacache.cpp \
+ operationtracer.cpp \
packagemanagercore_p.cpp \
packagemanagergui.cpp \
binaryformat.cpp \
@@ -194,7 +205,6 @@ SOURCES += packagemanagercore.cpp \
permissionsettings.cpp \
packagemanagerproxyfactory.cpp \
createlocalrepositoryoperation.cpp \
- lib7z_facade.cpp \
link.cpp \
createlinkoperation.cpp \
packagemanagercoredata.cpp \
@@ -205,7 +215,6 @@ SOURCES += packagemanagercore.cpp \
abstractfiletask.cpp \
copyfiletask.cpp \
downloadfiletask.cpp \
- unziptask.cpp \
observer.cpp \
metadatajob.cpp \
protocol.cpp \
@@ -227,7 +236,10 @@ SOURCES += packagemanagercore.cpp \
packagesource.cpp \
repositorycategory.cpp \
componentselectionpage_p.cpp \
- commandlineparser.cpp
+ commandlineparser.cpp \
+ customcombobox.cpp
+
+macos:SOURCES += fileutils_mac.mm
FORMS += proxycredentialsdialog.ui \
serverauthenticationdialog.ui
@@ -251,11 +263,26 @@ CONFIG(libarchive) {
LIBS += -llibarchive
}
-LIBS += -l7z
+CONFIG(lzmasdk) {
+ include(../3rdparty/7zip/7zip.pri)
+
+ HEADERS += lib7z_facade.h \
+ lib7z_guid.h \
+ lib7z_create.h \
+ lib7z_extract.h \
+ lib7z_list.h \
+ lib7zarchive.h
+
+ SOURCES += lib7z_facade.cpp \
+ lib7zarchive.cpp
+
+ LIBS += -l7z
+ win32:LIBS += -loleaut32 -luser32
+}
+
win32 {
SOURCES += adminauthorization_win.cpp sysinfo_win.cpp
- LIBS += -loleaut32 -luser32 # 7zip
LIBS += -ladvapi32 -lpsapi # kdtools
LIBS += -lole32 -lshell32 # createshortcutoperation
diff --git a/src/libs/installer/installer_global.h b/src/libs/installer/installer_global.h
index ea6865042..285eff910 100644
--- a/src/libs/installer/installer_global.h
+++ b/src/libs/installer/installer_global.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,4 +40,10 @@
# define INSTALLER_EXPORT
#endif
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+typedef uint hashValue;
+#else
+typedef size_t hashValue;
+#endif
+
#endif //INSTALLER_GLOBAL_H
diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp
index 363837dd1..4c53824af 100644
--- a/src/libs/installer/installercalculator.cpp
+++ b/src/libs/installer/installercalculator.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,12 +29,12 @@
#include "installercalculator.h"
#include "component.h"
+#include "componentalias.h"
+#include "componentmodel.h"
#include "packagemanagercore.h"
#include "settings.h"
#include <globals.h>
-#include <QDebug>
-
namespace QInstaller {
/*!
@@ -43,140 +43,188 @@ namespace QInstaller {
\internal
*/
-InstallerCalculator::InstallerCalculator(const QList<Component *> &allComponents)
- : m_allComponents(allComponents)
+InstallerCalculator::InstallerCalculator(PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash)
+ : CalculatorBase(core)
+ , m_autoDependencyComponentHash(autoDependencyComponentHash)
{
}
-void InstallerCalculator::insertInstallReason(Component *component,
- InstallReasonType installReason, const QString &referencedComponentName)
+InstallerCalculator::~InstallerCalculator()
{
- // keep the first reason
- if (m_toInstallComponentIdReasonHash.contains(component->name()))
- return;
- m_toInstallComponentIdReasonHash.insert(component->name(),
- qMakePair(installReason, referencedComponentName));
}
-InstallerCalculator::InstallReasonType InstallerCalculator::installReasonType(Component *c) const
+bool InstallerCalculator::solve()
{
- return m_toInstallComponentIdReasonHash.value(c->name(),
- qMakePair(InstallerCalculator::Selected, QString())).first;
-}
+ if (!solve(m_core->aliasesMarkedForInstallation()))
+ return false;
-QString InstallerCalculator::installReasonReferencedComponent(Component *component) const
-{
- return m_toInstallComponentIdReasonHash.value(component->name(),
- qMakePair(InstallerCalculator::Selected, QString())).second;
+ // Subtract components added by aliases
+ QList<Component *> components = m_core->componentsMarkedForInstallation();
+ for (auto *component : qAsConst(m_resolvedComponents))
+ components.removeAll(component);
+
+ return solve(components);
}
-QString InstallerCalculator::installReason(Component *component) const
+QString InstallerCalculator::resolutionText(Component *component) const
{
- InstallerCalculator::InstallReasonType reason = installReasonType(component);
+ const Resolution reason = resolutionType(component);
switch (reason) {
- case Automatic:
+ case Resolution::Automatic:
return QCoreApplication::translate("InstallerCalculator",
"Components added as automatic dependencies:");
- case Dependent:
+ case Resolution::Dependent:
return QCoreApplication::translate("InstallerCalculator", "Components added as "
- "dependency for \"%1\":").arg(installReasonReferencedComponent(component));
- case Resolved:
+ "dependency for \"%1\":").arg(referencedComponent(component));
+ case Resolution::Resolved:
return QCoreApplication::translate("InstallerCalculator",
"Components that have resolved dependencies:");
- case Selected:
+ case Resolution::Selected:
return QCoreApplication::translate("InstallerCalculator",
"Selected components without dependencies:");
+ case Resolution::Alias:
+ return QCoreApplication::translate("InstallerCalculator",
+ "Components selected by alias \"%1\":").arg(referencedComponent(component));
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid install resolution detected!");
}
return QString();
}
-QList<Component*> InstallerCalculator::orderedComponentsToInstall() const
-{
- return m_orderedComponentsToInstall;
-}
-
-QString InstallerCalculator::componentsToInstallError() const
-{
- return m_componentsToInstallError;
-}
-
-void InstallerCalculator::realAppendToInstallComponents(Component *component, const QString &version)
-{
- if (!component->isInstalled(version) || component->updateRequested()) {
- m_orderedComponentsToInstall.append(component);
- m_toInstallComponentIds.insert(component->name());
- }
-}
-
-QString InstallerCalculator::recursionError(Component *component)
-{
- return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component \"%1\" "
- "already added with reason: \"%2\"").arg(component->name(), installReason(component));
-}
-
-bool InstallerCalculator::appendComponentsToInstall(const QList<Component *> &components)
+bool InstallerCalculator::solve(const QList<Component *> &components)
{
if (components.isEmpty())
return true;
QList<Component*> notAppendedComponents; // for example components with unresolved dependencies
- foreach (Component *component, components){
+ for (Component *component : qAsConst(components)){
+ if (!component)
+ continue;
if (m_toInstallComponentIds.contains(component->name())) {
const QString errorMessage = recursionError(component);
qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage;
- m_componentsToInstallError.append(errorMessage);
+ m_errorString.append(errorMessage);
Q_ASSERT_X(!m_toInstallComponentIds.contains(component->name()), Q_FUNC_INFO,
qPrintable(errorMessage));
return false;
}
- if (component->dependencies().isEmpty())
- realAppendToInstallComponents(component);
+ if (component->currentDependencies().isEmpty())
+ addComponentForInstall(component);
else
notAppendedComponents.append(component);
}
- foreach (Component *component, notAppendedComponents) {
- if (!appendComponentToInstall(component))
+ for (Component *component : qAsConst(notAppendedComponents)) {
+ if (!solveComponent(component))
return false;
}
- QList<Component *> foundAutoDependOnList;
// All regular dependencies are resolved. Now we are looking for auto depend on components.
- foreach (Component *component, m_allComponents) {
- // If a components is already installed or is scheduled for installation, no need to check
- // for auto depend installation.
- if ((!component->isInstalled() || component->updateRequested())
- && !m_toInstallComponentIds.contains(component->name())) {
- // If we figure out a component requests auto installation, keep it to resolve
- // their dependencies as well.
- if (component->isAutoDependOn(m_toInstallComponentIds)) {
- foundAutoDependOnList.append(component);
- insertInstallReason(component, InstallerCalculator::Automatic);
- }
+ QSet<Component *> foundAutoDependOnList = autodependencyComponents();
+ if (!foundAutoDependOnList.isEmpty())
+ return solve(foundAutoDependOnList.values());
+
+ return true;
+}
+
+bool InstallerCalculator::solve(const QList<ComponentAlias *> &aliases)
+{
+ if (aliases.isEmpty())
+ return true;
+
+ QList<ComponentAlias *> notAppendedAliases; // Aliases that require other aliases
+ for (auto *alias : aliases) {
+ if (!alias)
+ continue;
+
+ if (m_toInstallComponentAliases.contains(alias->name())) {
+ const QString errorMessage = QCoreApplication::translate("InstallerCalculator",
+ "Recursion detected, component alias \"%1\" already added.").arg(alias->name());
+ qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage;
+ m_errorString.append(errorMessage);
+
+ Q_ASSERT_X(!m_toInstallComponentAliases.contains(alias->name()), Q_FUNC_INFO,
+ qPrintable(errorMessage));
+
+ return false;
+ }
+
+ if (alias->aliases().isEmpty()) {
+ if (!addComponentsFromAlias(alias))
+ return false;
+ } else {
+ notAppendedAliases.append(alias);
}
}
- if (!foundAutoDependOnList.isEmpty())
- return appendComponentsToInstall(foundAutoDependOnList);
+ for (auto *alias : qAsConst(notAppendedAliases)) {
+ if (!solveAlias(alias))
+ return false;
+ }
+
return true;
}
-bool InstallerCalculator::appendComponentToInstall(Component *component, const QString &version)
+void InstallerCalculator::addComponentForInstall(Component *component, const QString &version)
+{
+ if (!m_componentsForAutodepencencyCheck.contains(component))
+ m_componentsForAutodepencencyCheck.append(component);
+
+ if (!component->isInstalled(version) || (m_core->isUpdater() && component->isUpdateAvailable())) {
+ m_resolvedComponents.append(component);
+ m_toInstallComponentIds.insert(component->name());
+ }
+}
+
+bool InstallerCalculator::addComponentsFromAlias(ComponentAlias *alias)
+{
+ QList<Component *> componentsToAdd;
+ for (auto *component : alias->components()) {
+ if (m_toInstallComponentIds.contains(component->name()))
+ continue; // Already added
+
+ componentsToAdd.append(component);
+ // Updates the model, so that we also check the descendant
+ // components when calculating components to install
+ updateCheckState(component, Qt::Checked);
+ insertResolution(component, Resolution::Alias, alias->name());
+ }
+
+ m_toInstallComponentAliases.insert(alias->name());
+ return solve(componentsToAdd);
+}
+
+QString InstallerCalculator::recursionError(Component *component) const
+{
+ return QCoreApplication::translate("InstallerCalculator", "Recursion detected, component \"%1\" "
+ "already added with reason: \"%2\"").arg(component->name(), resolutionText(component));
+}
+
+bool InstallerCalculator::updateCheckState(Component *component, Qt::CheckState state)
+{
+ ComponentModel *currentModel = m_core->isUpdater()
+ ? m_core->updaterComponentModel()
+ : m_core->defaultComponentModel();
+
+ const QModelIndex &idx = currentModel->indexFromComponentName(component->treeName());
+ return currentModel->setData(idx, state, Qt::CheckStateRole);
+}
+
+bool InstallerCalculator::solveComponent(Component *component, const QString &version)
{
- QSet<QString> allDependencies = component->dependencies().toSet();
+ const QStringList dependenciesList = component->currentDependencies();
QString requiredDependencyVersion = version;
- foreach (const QString &dependencyComponentName, allDependencies) {
+ for (const QString &dependencyComponentName : dependenciesList) {
// PackageManagerCore::componentByName returns 0 if dependencyComponentName contains a
// version which is not available
- Component *dependencyComponent =
- PackageManagerCore::componentByName(dependencyComponentName, m_allComponents);
+ Component *dependencyComponent = m_core->componentByName(dependencyComponentName);
if (!dependencyComponent) {
const QString errorMessage = QCoreApplication::translate("InstallerCalculator",
"Cannot find missing dependency \"%1\" for \"%2\".").arg(dependencyComponentName,
component->name());
qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage;
- m_componentsToInstallError.append(errorMessage);
+ m_errorString.append(errorMessage);
if (component->packageManagerCore()->settings().allowUnstableComponents()) {
component->setUnstable(Component::UnstableError::MissingDependency, errorMessage);
continue;
@@ -191,11 +239,13 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q
PackageManagerCore::parseNameAndVersion(dependencyComponentName, &requiredName, &requiredVersion);
if (!requiredVersion.isEmpty() &&
!dependencyComponent->value(scInstalledVersion).isEmpty()) {
- QRegExp compEx(QLatin1String("([<=>]+)(.*)"));
- const QString installedVersion = compEx.exactMatch(dependencyComponent->value(scInstalledVersion)) ?
- compEx.cap(2) : dependencyComponent->value(scInstalledVersion);
+ static const QRegularExpression compEx(QLatin1String("^([<=>]+)(.*)$"));
+ QRegularExpressionMatch match = compEx.match(dependencyComponent->value(scInstalledVersion));
+ const QString installedVersion = match.hasMatch()
+ ? match.captured(2) : dependencyComponent->value(scInstalledVersion);
- requiredVersion = compEx.exactMatch(requiredVersion) ? compEx.cap(2) : requiredVersion;
+ match = compEx.match(requiredVersion);
+ requiredVersion = match.hasMatch() ? match.captured(2) : requiredVersion;
if (KDUpdater::compareVersion(requiredVersion, installedVersion) >= 1 ) {
isUpdateRequired = true;
@@ -212,27 +262,75 @@ bool InstallerCalculator::appendComponentToInstall(Component *component, const Q
if (m_visitedComponents.value(component).contains(dependencyComponent)) {
const QString errorMessage = recursionError(component);
qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage;
- m_componentsToInstallError = errorMessage;
+ m_errorString = errorMessage;
Q_ASSERT_X(!m_visitedComponents.value(component).contains(dependencyComponent),
Q_FUNC_INFO, qPrintable(errorMessage));
return false;
}
m_visitedComponents[component].insert(dependencyComponent);
-
// add needed dependency components to the next run
- insertInstallReason(dependencyComponent, InstallerCalculator::Dependent,
+ insertResolution(dependencyComponent, Resolution::Dependent,
component->name());
- if (!appendComponentToInstall(dependencyComponent, requiredDependencyVersion))
+ if (!solveComponent(dependencyComponent, requiredDependencyVersion))
return false;
}
}
if (!m_toInstallComponentIds.contains(component->name())) {
- realAppendToInstallComponents(component, requiredDependencyVersion);
- insertInstallReason(component, InstallerCalculator::Resolved);
+ addComponentForInstall(component, requiredDependencyVersion);
+ insertResolution(component, Resolution::Resolved);
}
return true;
}
+bool InstallerCalculator::solveAlias(ComponentAlias *alias)
+{
+ for (auto *requiredAlias : alias->aliases()) {
+ if (!solveAlias(requiredAlias))
+ return false;
+ }
+
+ if (m_toInstallComponentAliases.contains(alias->name()))
+ return true;
+
+ return addComponentsFromAlias(alias);
+}
+
+QSet<Component *> InstallerCalculator::autodependencyComponents()
+{
+ // All regular dependencies are resolved. Now we are looking for auto depend on components.
+ // m_componentsForAutodepencencyCheck is a list of recently calculated components to be installed
+ // (normal components and regular dependencies components), and we check possible installable auto
+ // dependency components based on that list.
+ QSet<Component *> foundAutoDependOnList;
+ for (const Component *component : qAsConst(m_componentsForAutodepencencyCheck)) {
+ if (!m_autoDependencyComponentHash.contains(component->name())
+ || (m_core->isUpdater() && !component->updateRequested()))
+ continue;
+ for (const QString& autoDependency : m_autoDependencyComponentHash.value(component->name())) {
+ // If a components is already installed or is scheduled for installation, no need to check
+ // for auto depend installation.
+ if (m_toInstallComponentIds.contains(autoDependency)) {
+ continue;
+ }
+ Component *autoDependComponent = m_core->componentByName(autoDependency);
+ if (!autoDependComponent)
+ continue;
+ if ((!autoDependComponent->isInstalled()
+ || (m_core->isUpdater() && autoDependComponent->isUpdateAvailable()))
+ && !m_toInstallComponentIds.contains(autoDependComponent->name())) {
+ // One of the components autodependons is requested for install, check if there
+ // are other autodependencies as well
+ if (autoDependComponent->isAutoDependOn(m_toInstallComponentIds)) {
+ foundAutoDependOnList.insert(autoDependComponent);
+ insertResolution(autoDependComponent, Resolution::Automatic);
+ }
+ }
+ }
+ }
+ m_componentsForAutodepencencyCheck.clear();
+ return foundAutoDependOnList;
+}
+
} // namespace QInstaller
diff --git a/src/libs/installer/installercalculator.h b/src/libs/installer/installercalculator.h
index b2d05bdbe..e542dc664 100644
--- a/src/libs/installer/installercalculator.h
+++ b/src/libs/installer/installercalculator.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,6 +29,8 @@
#define INSTALLERCALCULATOR_H
#include "installer_global.h"
+#include "qinstallerglobal.h"
+#include "calculatorbase.h"
#include <QHash>
#include <QList>
@@ -38,48 +40,41 @@
namespace QInstaller {
class Component;
+class ComponentAlias;
+class PackageManagerCore;
-class INSTALLER_EXPORT InstallerCalculator
+class INSTALLER_EXPORT InstallerCalculator : public CalculatorBase
{
public:
- InstallerCalculator(const QList<Component *> &allComponents);
+ InstallerCalculator(PackageManagerCore *core, const AutoDependencyHash &autoDependencyComponentHash);
+ ~InstallerCalculator();
- enum InstallReasonType
- {
- Automatic, // "Component(s) added as automatic dependencies"
- Dependent, // "Added as dependency for %1."
- Resolved, // "Component(s) that have resolved Dependencies"
- Selected // "Selected Component(s) without Dependencies"
- };
+ bool solve();
+ bool solve(const QList<Component *> &components) override;
+ bool solve(const QList<ComponentAlias *> &aliases);
- InstallReasonType installReasonType(Component *component) const;
- QString installReasonReferencedComponent(Component *component) const;
- QString installReason(Component *component) const;
- QList<Component*> orderedComponentsToInstall() const;
- QString componentsToInstallError() const;
-
- bool appendComponentsToInstall(const QList<Component*> &components);
+ QString resolutionText(Component *component) const override;
private:
- void insertInstallReason(Component *component,
- InstallReasonType installReasonType,
- const QString &referencedComponentName = QString());
- void realAppendToInstallComponents(Component *component, const QString &version = QString());
- bool appendComponentToInstall(Component *components, const QString &version = QString());
- QString recursionError(Component *component);
+ bool solveComponent(Component *component, const QString &version = QString()) override;
+ bool solveAlias(ComponentAlias *alias);
+
+ void addComponentForInstall(Component *component, const QString &version = QString());
+ bool addComponentsFromAlias(ComponentAlias *alias);
+ QSet<Component *> autodependencyComponents();
+ QString recursionError(Component *component) const;
+
+ bool updateCheckState(Component *component, Qt::CheckState state);
- QList<Component*> m_allComponents;
+private:
QHash<Component*, QSet<Component*> > m_visitedComponents;
+ QList<const Component*> m_componentsForAutodepencencyCheck;
QSet<QString> m_toInstallComponentIds; //for faster lookups
- QString m_componentsToInstallError;
- //calculate installation order variables
- QList<Component*> m_orderedComponentsToInstall;
- //we can't use this reason hash as component id hash, because some reasons are ready before
- //the component is added
- QHash<QString, QPair<InstallReasonType, QString> > m_toInstallComponentIdReasonHash;
+ QSet<QString> m_toInstallComponentAliases;
+ //Helper hash for quicker search for autodependency components
+ AutoDependencyHash m_autoDependencyComponentHash;
};
-}
-
+} // namespace QInstaller
#endif // INSTALLERCALCULATOR_H
diff --git a/src/libs/installer/installiconsoperation.cpp b/src/libs/installer/installiconsoperation.cpp
index cfb5a9536..b21634cd7 100644
--- a/src/libs/installer/installiconsoperation.cpp
+++ b/src/libs/installer/installiconsoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -54,10 +54,10 @@ QString InstallIconsOperation::targetDirectory()
QStringList XDG_DATA_HOME = QString::fromLocal8Bit(qgetenv("XDG_DATA_HOME"))
.split(QLatin1Char(':'),
- QString::SkipEmptyParts);
+ Qt::SkipEmptyParts);
XDG_DATA_HOME.push_back(QDir::home().absoluteFilePath(QLatin1String(".local/share"))); // default user-specific path
- if (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive())
+ if (packageManager() && packageManager()->hasAdminRights())
XDG_DATA_HOME.push_front(QLatin1String("/usr/local/share")); // default system-wide path
QString directory;
diff --git a/src/libs/installer/installiconsoperation.h b/src/libs/installer/installiconsoperation.h
index 7a4d1cc90..e7a8dd871 100644
--- a/src/libs/installer/installiconsoperation.h
+++ b/src/libs/installer/installiconsoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -41,10 +41,10 @@ class INSTALLER_EXPORT InstallIconsOperation : public QObject, public Operation
public:
explicit InstallIconsOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/lib7z_create.h b/src/libs/installer/lib7z_create.h
index 72fc56c81..b908b028f 100644
--- a/src/libs/installer/lib7z_create.h
+++ b/src/libs/installer/lib7z_create.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
@@ -35,9 +35,10 @@
#include <Common/MyCom.h>
#include <7zip/UI/Common/Update.h>
+#include <QStringList>
+
QT_BEGIN_NAMESPACE
class QFileDevice;
-class QStringList;
QT_END_NAMESPACE
namespace Lib7z
diff --git a/src/libs/installer/lib7z_extract.h b/src/libs/installer/lib7z_extract.h
index 384212bb7..6465a8cfc 100644
--- a/src/libs/installer/lib7z_extract.h
+++ b/src/libs/installer/lib7z_extract.h
@@ -1,11 +1,11 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/libs/installer/lib7z_facade.cpp b/src/libs/installer/lib7z_facade.cpp
index 6d1b6a57d..e0d8a53e4 100644
--- a/src/libs/installer/lib7z_facade.cpp
+++ b/src/libs/installer/lib7z_facade.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -37,6 +37,7 @@
#include "lib7z_guid.h"
#include "globals.h"
#include "directoryguard.h"
+#include "fileguard.h"
#ifndef Q_OS_WIN
# include "StdAfx.h"
@@ -362,7 +363,7 @@ static quint32 getUInt32Property(IInArchive *archive, int index, int propId, qui
static QFile::Permissions getPermissions(IInArchive *archive, int index, bool *hasPermissions)
{
quint32 attributes = getUInt32Property(archive, index, kpidAttrib, 0);
- QFile::Permissions permissions = nullptr;
+ QFile::Permissions permissions = QFile::Permissions();
if (attributes & FILE_ATTRIBUTE_UNIX_EXTENSION) {
if (hasPermissions != nullptr)
*hasPermissions = true;
@@ -538,6 +539,7 @@ QVector<File> listArchive(QFileDevice *archive)
f.archiveIndex.setY(item);
f.path = UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/'));
Archive_IsItem_Folder(arch, item, f.isDirectory);
+ Archive_GetItemBoolProp(arch, item, kpidSymLink, f.isSymbolicLink);
f.permissions_enum = getPermissions(arch, item, nullptr);
getDateTimeProperty(arch, item, kpidMTime, &(f.utcTime));
f.uncompressedSize = getUInt64Property(arch, item, kpidSize, 0);
@@ -622,6 +624,11 @@ STDMETHODIMP ExtractCallback::GetStream(UInt32 index, ISequentialOutStream **out
foreach (const QString &directory, directories)
setCurrentFile(directory);
+ QScopedPointer<QInstaller::FileGuardLocker> locker(nullptr);
+ if (!isDir) {
+ locker.reset(new QInstaller::FileGuardLocker(
+ fi.absoluteFilePath(), QInstaller::FileGuard::globalObject()));
+ }
if (!isDir && !prepareForFile(fi.absoluteFilePath()))
return E_FAIL;
diff --git a/src/libs/installer/lib7z_guid.h b/src/libs/installer/lib7z_guid.h
index b79fab958..adc1aa948 100644
--- a/src/libs/installer/lib7z_guid.h
+++ b/src/libs/installer/lib7z_guid.h
@@ -1,11 +1,11 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/libs/installer/lib7z_list.h b/src/libs/installer/lib7z_list.h
index e09c73746..2dec655b1 100644
--- a/src/libs/installer/lib7z_list.h
+++ b/src/libs/installer/lib7z_list.h
@@ -1,11 +1,11 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/libs/installer/lib7zarchive.h b/src/libs/installer/lib7zarchive.h
index 45f352aeb..f73670a4f 100644
--- a/src/libs/installer/lib7zarchive.h
+++ b/src/libs/installer/lib7zarchive.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -45,18 +45,18 @@ public:
explicit Lib7zArchive(QObject *parent = nullptr);
~Lib7zArchive();
- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- void setFilename(const QString &filename) Q_DECL_OVERRIDE;
+ bool open(QIODevice::OpenMode mode) override;
+ void close() override;
+ void setFilename(const QString &filename) override;
- bool extract(const QString &dirPath) Q_DECL_OVERRIDE;
- bool extract(const QString &dirPath, const quint64 totalFiles) Q_DECL_OVERRIDE;
- bool create(const QStringList &data) Q_DECL_OVERRIDE;
- QVector<ArchiveEntry> list() Q_DECL_OVERRIDE;
- bool isSupported() Q_DECL_OVERRIDE;
+ bool extract(const QString &dirPath) override;
+ bool extract(const QString &dirPath, const quint64 totalFiles) override;
+ bool create(const QStringList &data) override;
+ QVector<ArchiveEntry> list() override;
+ bool isSupported() override;
public Q_SLOTS:
- void cancel() Q_DECL_OVERRIDE;
+ void cancel() override;
private:
void listenExtractCallback();
@@ -83,8 +83,8 @@ Q_SIGNALS:
void completedChanged(quint64 completed, quint64 total);
private:
- void setCurrentFile(const QString &filename) Q_DECL_OVERRIDE;
- HRESULT setCompleted(quint64 completed, quint64 total) Q_DECL_OVERRIDE;
+ void setCurrentFile(const QString &filename) override;
+ HRESULT setCompleted(quint64 completed, quint64 total) override;
private:
HRESULT m_state;
diff --git a/src/libs/installer/libarchivearchive.cpp b/src/libs/installer/libarchivearchive.cpp
index d3a79bd40..233a4c28b 100644
--- a/src/libs/installer/libarchivearchive.cpp
+++ b/src/libs/installer/libarchivearchive.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,16 +29,26 @@
#include "libarchivearchive.h"
#include "directoryguard.h"
+#include "fileguard.h"
#include "errors.h"
#include "globals.h"
#include <stdio.h>
+#include <string.h>
#include <QApplication>
#include <QFileInfo>
#include <QDir>
#include <QTimer>
+#ifdef Q_OS_WIN
+#include <locale.h>
+#endif
+
+#if defined(Q_OS_WIN) && !defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
+#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
+#endif
+
namespace QInstaller {
/*!
@@ -59,6 +69,184 @@ namespace QInstaller {
\internal
*/
+namespace ArchiveEntryPaths {
+
+// TODO: it is expected that the filename handling will change in the major
+// version jump to libarchive 4.x, and the *_w methods will disappear.
+
+/*!
+ \internal
+
+ Returns the path name from the archive \a entry as a \c QString. The path is
+ stored internally in a multistring that can contain a combination of a wide
+ character or multibyte string in current locale or unicode string encoded as UTF-8.
+
+ \note The MBS version is expected to be convertable from latin-1 which might
+ not actually be the case, as the encoding depends on the current locale.
+*/
+static QString pathname(archive_entry *const entry)
+{
+ if (!entry)
+ return QString();
+#ifdef Q_OS_WIN
+ if (const wchar_t *path = archive_entry_pathname_w(entry))
+ return QString::fromWCharArray(path);
+#endif
+ if (const char *path = archive_entry_pathname_utf8(entry))
+ return QString::fromUtf8(path);
+
+ return QString::fromLatin1(archive_entry_pathname(entry));
+}
+
+/*!
+ \internal
+
+ Sets the path name for the archive \a entry to \a path. This function
+ tries to update all variants of the string in the internal multistring
+ struct.
+*/
+static void setPathname(archive_entry *const entry, const QString &path)
+{
+ if (!entry)
+ return;
+
+ // Try updating all variants at once, stops on failure
+ if (archive_entry_update_pathname_utf8(entry, path.toUtf8()))
+ return;
+
+ // If that does not work, then set them individually
+ archive_entry_set_pathname(entry, path.toLatin1());
+ archive_entry_set_pathname_utf8(entry, path.toUtf8());
+#ifdef Q_OS_WIN
+ wchar_t *wpath = new wchar_t[path.length() + 1];
+ path.toWCharArray(wpath);
+ wpath[path.length()] = '\0';
+
+ archive_entry_copy_pathname_w(entry, wpath);
+ delete[] wpath;
+#endif
+}
+
+/*!
+ \internal
+
+ Returns the source path on disk from the current archive \a entry as a \c QString.
+ The path is stored internally in a multistring that can contain a combination
+ of a wide character or multibyte string in current locale.
+
+ \note The MBS version is expected to be convertable from UTF-8.
+*/
+static QString sourcepath(archive_entry * const entry)
+{
+ if (!entry)
+ return QString();
+#ifdef Q_OS_WIN
+ if (const wchar_t *path = archive_entry_sourcepath_w(entry))
+ return QString::fromWCharArray(path);
+#endif
+ return QString::fromUtf8(archive_entry_sourcepath(entry));
+}
+
+/*!
+ \internal
+
+ Returns the hardlink path from the current archive \a entry as a \c QString.
+ The path is stored internally in a multistring that can contain a combination of a wide
+ character or multibyte string in current locale or unicode string encoded as UTF-8.
+
+ \note The MBS version is expected to be convertable from latin-1 which might
+ not actually be the case, as the encoding depends on the current locale.
+*/
+static QString hardlink(archive_entry * const entry)
+{
+ if (!entry)
+ return QString();
+#ifdef Q_OS_WIN
+ if (const wchar_t *path = archive_entry_hardlink_w(entry))
+ return QString::fromWCharArray(path);
+#endif
+ if (const char *path = archive_entry_hardlink_utf8(entry))
+ return QString::fromUtf8(path);
+
+ return QString::fromLatin1(archive_entry_hardlink(entry));
+}
+
+/*!
+ \internal
+
+ Sets the hard link path for the archive \a entry to \a path. This function
+ tries to update all variants of the string in the internal multistring
+ struct.
+*/
+static void setHardlink(archive_entry *const entry, const QString &path)
+{
+ if (!entry)
+ return;
+
+ // Try updating all variants at once, stops on failure
+ if (archive_entry_update_hardlink_utf8(entry, path.toUtf8()))
+ return;
+
+ // If that does not work, then set them individually
+ archive_entry_set_hardlink(entry, path.toLatin1());
+ archive_entry_set_hardlink_utf8(entry, path.toUtf8());
+#ifdef Q_OS_WIN
+ wchar_t *wpath = new wchar_t[path.length() + 1];
+ path.toWCharArray(wpath);
+ wpath[path.length()] = '\0';
+
+ archive_entry_copy_hardlink_w(entry, wpath);
+ delete[] wpath;
+#endif
+}
+
+/*!
+ \internal
+
+ Calls a function object or pointer \a func with any number of extra
+ arguments \a args. Returns the return value of the function of type T.
+
+ On Windows, this changes the locale category LC_CTYPE from C to system
+ locale. The original LC_CTYPE is restored after the function call.
+ Currently the locale is unchanged on other platforms.
+*/
+template <typename T, typename F, typename... Args>
+static T callWithSystemLocale(F func, Args... args)
+{
+#ifdef Q_OS_WIN
+ const QByteArray oldLocale = setlocale(LC_CTYPE, "");
+#endif
+ T returnValue = func(std::forward<Args>(args)...);
+#ifdef Q_OS_WIN
+ setlocale(LC_CTYPE, oldLocale.constData());
+#endif
+ return returnValue;
+}
+
+/*!
+ \internal
+
+ Calls a function object or pointer \a func with any number of extra
+ arguments \a args.
+
+ On Windows, this changes the locale category LC_CTYPE from C to system
+ locale. The original LC_CTYPE is restored after the function call.
+ Currently the locale is unchanged on other platforms.
+*/
+template <typename F, typename... Args>
+static void callWithSystemLocale(F func, Args... args)
+{
+#ifdef Q_OS_WIN
+ const QByteArray oldLocale = setlocale(LC_CTYPE, "");
+#endif
+ func(std::forward<Args>(args)...);
+#ifdef Q_OS_WIN
+ setlocale(LC_CTYPE, oldLocale.constData());
+#endif
+}
+
+} // namespace ArchiveEntryPaths
+
/*!
\inmodule QtInstallerFramework
\class QInstaller::ExtractWorker
@@ -88,7 +276,7 @@ void ExtractWorker::extract(const QString &dirPath, const quint64 totalFiles)
LibArchiveArchive::configureReader(reader.get());
LibArchiveArchive::configureDiskWriter(writer.get());
- DirectoryGuard targetDir(QFileInfo(dirPath).absolutePath());
+ DirectoryGuard targetDir(QFileInfo(dirPath).absoluteFilePath());
try {
const QStringList createdDirs = targetDir.tryCreate();
// Make sure that all leading directories created get removed as well
@@ -102,7 +290,8 @@ void ExtractWorker::extract(const QString &dirPath, const quint64 totalFiles)
int status = archive_read_open1(reader.get());
if (status != ARCHIVE_OK) {
m_status = Failure;
- emit finished(QLatin1String(archive_error_string(reader.get())));
+ emit finished(tr("Cannot open archive for reading: %1")
+ .arg(LibArchiveArchive::errorStringWithCode(reader.get())));
return;
}
@@ -111,22 +300,23 @@ void ExtractWorker::extract(const QString &dirPath, const quint64 totalFiles)
emit finished(QLatin1String("Extract canceled."));
return;
}
- status = archive_read_next_header(reader.get(), &entry);
+ status = ArchiveEntryPaths::callWithSystemLocale<int>(archive_read_next_header, reader.get(), &entry);
if (status == ARCHIVE_EOF)
break;
if (status != ARCHIVE_OK) {
m_status = Failure;
- emit finished(QLatin1String(archive_error_string(reader.get())));
+ emit finished(tr("Cannot read entry header: %1")
+ .arg(LibArchiveArchive::errorStringWithCode(reader.get())));
return;
}
- const char *current = archive_entry_pathname(entry);
- const QString outputPath = dirPath + QDir::separator() + QString::fromLocal8Bit(current);
- archive_entry_set_pathname(entry, outputPath.toLocal8Bit());
-
- const char *hardlink = archive_entry_hardlink(entry);
- if (hardlink) {
- const QString hardLinkPath = dirPath + QDir::separator() + QString::fromLocal8Bit(hardlink);
- archive_entry_set_hardlink(entry, hardLinkPath.toLocal8Bit());
+ const QString current = ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::pathname, entry);
+ const QString outputPath = dirPath + QDir::separator() + current;
+ ArchiveEntryPaths::callWithSystemLocale(&ArchiveEntryPaths::setPathname, entry, outputPath);
+
+ const QString hardlink = ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::hardlink, entry);
+ if (!hardlink.isEmpty()) {
+ const QString hardLinkPath = dirPath + QDir::separator() + hardlink;
+ ArchiveEntryPaths::callWithSystemLocale(ArchiveEntryPaths::setHardlink, entry, hardLinkPath);
}
emit currentEntryChanged(outputPath);
@@ -222,25 +412,36 @@ bool ExtractWorker::writeEntry(archive *reader, archive *writer, archive_entry *
size_t size;
int64_t offset;
+ const QString entryPath = ArchiveEntryPaths::callWithSystemLocale
+ <QString>(ArchiveEntryPaths::pathname, entry);
+
+ FileGuardLocker locker(entryPath, FileGuard::globalObject());
+
status = archive_write_header(writer, entry);
if (status != ARCHIVE_OK) {
- emit finished(QLatin1String(archive_error_string(writer)));
+ emit finished(tr("Cannot write entry \"%1\" to disk: %2")
+ .arg(entryPath, LibArchiveArchive::errorStringWithCode(writer)));
return false;
}
forever {
status = archive_read_data_block(reader, &buff, &size, &offset);
- if (status == ARCHIVE_EOF)
- return true;
+ if (status == ARCHIVE_EOF) {
+ status = archive_write_finish_entry(writer);
+ if (status == ARCHIVE_OK)
+ return true;
+ }
if (status != ARCHIVE_OK) {
m_status = Failure;
- emit finished(QLatin1String(archive_error_string(reader)));
+ emit finished(tr("Cannot write entry \"%1\" to disk: %2")
+ .arg(entryPath, LibArchiveArchive::errorStringWithCode(reader)));
return false;
}
status = archive_write_data_block(writer, buff, size, offset);
if (status != ARCHIVE_OK) {
m_status = Failure;
- emit finished(QLatin1String(archive_error_string(writer)));
+ emit finished(tr("Cannot write entry \"%1\" to disk: %2")
+ .arg(entryPath, LibArchiveArchive::errorStringWithCode(writer)));
return false;
}
}
@@ -421,7 +622,7 @@ bool LibArchiveArchive::extract(const QString &dirPath, const quint64 totalFiles
configureReader(reader.get());
configureDiskWriter(writer.get());
- DirectoryGuard targetDir(QFileInfo(dirPath).absolutePath());
+ DirectoryGuard targetDir(QFileInfo(dirPath).absoluteFilePath());
try {
const QStringList createdDirs = targetDir.tryCreate();
// Make sure that all leading directories created get removed as well
@@ -429,32 +630,38 @@ bool LibArchiveArchive::extract(const QString &dirPath, const quint64 totalFiles
emit currentEntryChanged(directory);
int status = archiveReadOpenWithCallbacks(reader.get());
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot open archive for reading: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
forever {
if (m_cancelScheduled)
throw Error(QLatin1String("Extract canceled."));
- status = archive_read_next_header(reader.get(), &entry);
+ status = ArchiveEntryPaths::callWithSystemLocale<int>(archive_read_next_header, reader.get(), &entry);
if (status == ARCHIVE_EOF)
break;
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot read entry header: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
- const char *current = archive_entry_pathname(entry);
- const QString outputPath = dirPath + QDir::separator() + QString::fromLocal8Bit(current);
- archive_entry_set_pathname(entry, outputPath.toLocal8Bit());
+ const QString current = ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::pathname, entry);
+ const QString outputPath = dirPath + QDir::separator() + current;
+ ArchiveEntryPaths::callWithSystemLocale(ArchiveEntryPaths::setPathname, entry, outputPath);
- const char *hardlink = archive_entry_hardlink(entry);
- if (hardlink) {
- const QString hardLinkPath = dirPath + QDir::separator() + QString::fromLocal8Bit(hardlink);
- archive_entry_set_hardlink(entry, hardLinkPath.toLocal8Bit());
+ const QString hardlink = ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::hardlink, entry);
+ if (!hardlink.isEmpty()) {
+ const QString hardLinkPath = dirPath + QDir::separator() + hardlink;
+ ArchiveEntryPaths::callWithSystemLocale(ArchiveEntryPaths::setHardlink, entry, hardLinkPath);
}
emit currentEntryChanged(outputPath);
- if (!writeEntry(reader.get(), writer.get(), entry))
- throw Error(errorString()); // appropriate error string set in writeEntry()
+ if (!writeEntry(reader.get(), writer.get(), entry)) {
+ throw Error(tr("Cannot write entry \"%1\" to disk: %2")
+ .arg(outputPath, errorString())); // appropriate error string set in writeEntry()
+ }
++completed;
emit completedChanged(completed, totalFiles);
@@ -481,43 +688,98 @@ bool LibArchiveArchive::create(const QStringList &data)
QScopedPointer<archive, ScopedPointerWriterDeleter> writer(archive_write_new());
configureWriter(writer.get());
+ QStringList globbedData;
+ for (auto &dataEntry : data) { // Expand glob pattern entries with proper filenames
+ if (!dataEntry.contains(QLatin1Char('*'))) {
+ globbedData.append(dataEntry);
+ continue;
+ }
+ const QFileInfo entryInfo(dataEntry);
+ if (entryInfo.path().contains(QLatin1Char('*'))) {
+ setErrorString(QString::fromLatin1("Invalid argument \"%1\": glob patterns "
+ "are not supported between directory paths.").arg(dataEntry));
+ return false;
+ }
+ const QDir parentDir = entryInfo.dir();
+ const QList<QFileInfo> infoList = parentDir.entryInfoList(QStringList()
+ << entryInfo.fileName(), QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);
+
+ for (auto &info : infoList)
+ globbedData.append(info.absoluteFilePath());
+ }
+
try {
int status;
- if ((status = archive_write_open_filename(writer.get(), m_data->file.fileName().toLocal8Bit())))
- throw Error(QLatin1String(archive_error_string(writer.get())));
+#ifdef Q_OS_WIN
+ QScopedPointer<wchar_t, QScopedPointerArrayDeleter<wchar_t>> fileName_w(
+ new wchar_t[m_data->file.fileName().length() + 1]);
- for (auto &dataEntry : data) {
+ m_data->file.fileName().toWCharArray(fileName_w.get());
+ fileName_w.get()[m_data->file.fileName().length()] = '\0';
+
+ if ((status = archive_write_open_filename_w(writer.get(), fileName_w.get()))) {
+ throw Error(tr("Cannot open file \"%1\" for writing: %2")
+ .arg(m_data->file.fileName(), errorStringWithCode(writer.get())));
+ }
+#else
+ if ((status = archive_write_open_filename(writer.get(), m_data->file.fileName().toUtf8()))) {
+ throw Error(tr("Cannot open file \"%1\" for writing: %2")
+ .arg(m_data->file.fileName(), errorStringWithCode(writer.get())));
+ }
+#endif
+ for (auto &dataEntry : globbedData) {
QScopedPointer<archive, ScopedPointerReaderDeleter> reader(archive_read_disk_new());
configureDiskReader(reader.get());
- if ((status = archive_read_disk_open(reader.get(), dataEntry.toLocal8Bit())))
- throw Error(QLatin1String(archive_error_string(reader.get())));
+#ifdef Q_OS_WIN
+ QScopedPointer<wchar_t, QScopedPointerArrayDeleter<wchar_t>> dataEntry_w(
+ new wchar_t[dataEntry.length() + 1]);
+ dataEntry.toWCharArray(dataEntry_w.get());
+ dataEntry_w.get()[dataEntry.length()] = '\0';
+
+ if ((status = archive_read_disk_open_w(reader.get(), dataEntry_w.get()))) {
+ throw Error(tr("Cannot open file \"%1\" for reading: %2")
+ .arg(dataEntry, errorStringWithCode(reader.get())));
+ }
+#else
+ if ((status = archive_read_disk_open(reader.get(), dataEntry.toUtf8()))) {
+ throw Error(tr("Cannot open file \"%1\" for reading: %2")
+ .arg(dataEntry, errorStringWithCode(reader.get())));
+ }
+#endif
QDir basePath = QFileInfo(dataEntry).dir();
forever {
QScopedPointer<archive_entry, ScopedPointerEntryDeleter> entry(archive_entry_new());
- status = archive_read_next_header2(reader.get(), entry.get());
+ status = ArchiveEntryPaths::callWithSystemLocale<int>(archive_read_next_header2, reader.get(), entry.get());
if (status == ARCHIVE_EOF)
break;
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot read entry header: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
- const QFileInfo fileOrDir(pathWithoutNamespace(QLatin1String(archive_entry_sourcepath(entry.get()))));
+ const QFileInfo fileOrDir(pathWithoutNamespace(
+ ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::sourcepath, entry.get())));
// Set new path name in archive, otherwise we add all directories from absolute path
const QString newPath = basePath.relativeFilePath(fileOrDir.filePath());
- archive_entry_set_pathname(entry.get(), newPath.toLocal8Bit());
+ ArchiveEntryPaths::callWithSystemLocale(ArchiveEntryPaths::setPathname, entry.get(), newPath);
archive_read_disk_descend(reader.get());
status = archive_write_header(writer.get(), entry.get());
- if (status < ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(writer.get())));
-
+ if (status < ARCHIVE_OK) {
+ throw Error(tr("Cannot write entry header for \"%1\": %2")
+ .arg(fileOrDir.filePath(), errorStringWithCode(writer.get())));
+ }
if (fileOrDir.isDir() || archive_entry_size(entry.get()) == 0)
continue; // nothing to copy
- QFile file(pathWithoutNamespace(QLatin1String(archive_entry_sourcepath(entry.get()))));
- if (!file.open(QIODevice::ReadOnly))
- throw Error(file.errorString());
+ QFile file(pathWithoutNamespace(ArchiveEntryPaths::callWithSystemLocale<QString>(
+ ArchiveEntryPaths::sourcepath, entry.get())));
+ if (!file.open(QIODevice::ReadOnly)) {
+ throw Error(tr("Cannot open file \"%1\" for reading: %2")
+ .arg(file.fileName(), file.errorString()));
+ }
QByteArray buffer;
constexpr qint64 blockSize = 4 * 1024;
@@ -554,20 +816,25 @@ QVector<ArchiveEntry> LibArchiveArchive::list()
QVector<ArchiveEntry> entries;
try {
int status = archiveReadOpenWithCallbacks(reader.get());
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot open archive for reading: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
forever {
- status = archive_read_next_header(reader.get(), &entry);
+ status = ArchiveEntryPaths::callWithSystemLocale<int>(archive_read_next_header, reader.get(), &entry);
if (status == ARCHIVE_EOF)
break;
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot read entry header: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
ArchiveEntry archiveEntry;
- archiveEntry.path = QLatin1String(archive_entry_pathname(entry));
- archiveEntry.utcTime = QDateTime::fromTime_t(archive_entry_mtime(entry));
+ archiveEntry.path = ArchiveEntryPaths::callWithSystemLocale<QString>(ArchiveEntryPaths::pathname, entry);
+ archiveEntry.utcTime = QDateTime::fromSecsSinceEpoch(archive_entry_mtime(entry));
archiveEntry.isDirectory = (archive_entry_filetype(entry) == AE_IFDIR);
+ archiveEntry.isSymbolicLink = (archive_entry_filetype(entry) == AE_IFLNK);
archiveEntry.uncompressedSize = archive_entry_size(entry);
archiveEntry.permissions_mode = archive_entry_perm(entry);
@@ -595,8 +862,10 @@ bool LibArchiveArchive::isSupported()
try {
const int status = archiveReadOpenWithCallbacks(reader.get());
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot open archive for reading: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
} catch (const Error &e) {
setErrorString(e.message());
m_data->file.seek(0);
@@ -685,6 +954,7 @@ void LibArchiveArchive::configureReader(archive *archive)
archive_read_support_format_tar(archive);
archive_read_support_format_zip(archive);
+ archive_read_support_format_7zip(archive);
}
/*!
@@ -692,16 +962,25 @@ void LibArchiveArchive::configureReader(archive *archive)
*/
void LibArchiveArchive::configureWriter(archive *archive)
{
- if (QFileInfo(m_data->file.fileName()).suffix() == QLatin1String("zip")) {
- archive_write_set_format_zip(archive);
+ const QString fileName = m_data->file.fileName();
+ if (fileName.endsWith(QLatin1String(".qbsp"), Qt::CaseInsensitive)) {
+ // The Qt board support package file extension is really a 7z.
+ archive_write_set_format_7zip(archive);
} else {
- archive_write_set_format_pax_restricted(archive);
- archive_write_set_format_filter_by_ext(archive, m_data->file.fileName().toLatin1());
+ archive_write_set_format_filter_by_ext(archive, fileName.toUtf8());
}
- const QByteArray options = "compression-level=" + QString::number(compressionLevel()).toLatin1();
- if (archive_write_set_options(archive, options.constData())) { // not fatal
- qCWarning(QInstaller::lcInstallerInstallLog) << "Could not set options" << options
- << "for archive" << m_data->file.fileName() << ":" << archive_error_string(archive);
+
+ const QByteArray charset = "hdrcharset=UTF-8";
+ // not checked as this is ignored on some archive formats like 7z
+ archive_write_set_options(archive, charset);
+
+ if (compressionLevel() == CompressionLevel::Normal)
+ return;
+
+ const QByteArray compression = "compression-level=" + QString::number(compressionLevel()).toLatin1();
+ if (archive_write_set_options(archive, compression.constData())) { // not fatal
+ qCWarning(QInstaller::lcInstallerInstallLog) << "Could not set option" << compression
+ << "for archive" << m_data->file.fileName() << ":" << errorStringWithCode(archive);
}
}
@@ -775,23 +1054,31 @@ bool LibArchiveArchive::writeEntry(archive *reader, archive *writer, archive_ent
size_t size;
int64_t offset;
+ const QString entryPath = ArchiveEntryPaths::callWithSystemLocale
+ <QString>(ArchiveEntryPaths::pathname, entry);
+
+ FileGuardLocker locker(entryPath, FileGuard::globalObject());
+
status = archive_write_header(writer, entry);
if (status != ARCHIVE_OK) {
- setErrorString(QLatin1String(archive_error_string(writer)));
+ setErrorString(errorStringWithCode(writer));
return false;
}
forever {
status = archive_read_data_block(reader, &buff, &size, &offset);
- if (status == ARCHIVE_EOF)
- return true;
+ if (status == ARCHIVE_EOF) {
+ status = archive_write_finish_entry(writer);
+ if (status == ARCHIVE_OK)
+ return true;
+ }
if (status != ARCHIVE_OK) {
- setErrorString(QLatin1String(archive_error_string(reader)));
+ setErrorString(errorStringWithCode(reader));
return false;
}
status = archive_write_data_block(writer, buff, size, offset);
if (status != ARCHIVE_OK) {
- setErrorString(QLatin1String(archive_error_string(writer)));
+ setErrorString(errorStringWithCode(writer));
return false;
}
}
@@ -901,6 +1188,21 @@ QString LibArchiveArchive::pathWithoutNamespace(const QString &path)
}
/*!
+ Returns an error message and a textual representaion of the numeric error code
+ indicating the reason for the most recent error return for the \a archive object.
+*/
+QString LibArchiveArchive::errorStringWithCode(archive *const archive)
+{
+ if (!archive)
+ return QString();
+
+ return QString::fromLatin1("%1: %2.").arg(
+ QLatin1String(archive_error_string(archive)),
+ QLatin1String(strerror(archive_errno(archive)))
+ );
+}
+
+/*!
Returns the number of files in this archive.
*/
quint64 LibArchiveArchive::totalFiles()
@@ -913,15 +1215,19 @@ quint64 LibArchiveArchive::totalFiles()
try {
int status = archiveReadOpenWithCallbacks(reader.get());
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot open archive for reading: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
forever {
- status = archive_read_next_header(reader.get(), &entry);
+ status = ArchiveEntryPaths::callWithSystemLocale<int>(archive_read_next_header, reader.get(), &entry);
if (status == ARCHIVE_EOF)
break;
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ if (status != ARCHIVE_OK) {
+ throw Error(tr("Cannot read entry header: %1")
+ .arg(errorStringWithCode(reader.get())));
+ }
++files;
}
diff --git a/src/libs/installer/libarchivearchive.h b/src/libs/installer/libarchivearchive.h
index 796069ed1..759f99046 100644
--- a/src/libs/installer/libarchivearchive.h
+++ b/src/libs/installer/libarchivearchive.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -99,15 +99,15 @@ public:
explicit LibArchiveArchive(QObject *parent = nullptr);
~LibArchiveArchive();
- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- void setFilename(const QString &filename) Q_DECL_OVERRIDE;
+ bool open(QIODevice::OpenMode mode) override;
+ void close() override;
+ void setFilename(const QString &filename) override;
- bool extract(const QString &dirPath) Q_DECL_OVERRIDE;
- bool extract(const QString &dirPath, const quint64 totalFiles) Q_DECL_OVERRIDE;
- bool create(const QStringList &data) Q_DECL_OVERRIDE;
- QVector<ArchiveEntry> list() Q_DECL_OVERRIDE;
- bool isSupported() Q_DECL_OVERRIDE;
+ bool extract(const QString &dirPath) override;
+ bool extract(const QString &dirPath, const quint64 totalFiles) override;
+ bool create(const QStringList &data) override;
+ QVector<ArchiveEntry> list() override;
+ bool isSupported() override;
void workerExtract(const QString &dirPath, const quint64 totalFiles);
void workerAddDataBlock(const QByteArray buffer);
@@ -128,7 +128,7 @@ Q_SIGNALS:
void workerAboutToCancel();
public Q_SLOTS:
- void cancel() Q_DECL_OVERRIDE;
+ void cancel() override;
private Q_SLOTS:
void onWorkerFinished(const QString &errorString);
@@ -150,6 +150,7 @@ private:
static la_int64_t seekCallback(archive *reader, void *archiveData, la_int64_t offset, int whence);
static QString pathWithoutNamespace(const QString &path);
+ static QString errorStringWithCode(archive *const archive);
quint64 totalFiles();
diff --git a/src/libs/installer/libarchivewrapper.cpp b/src/libs/installer/libarchivewrapper.cpp
index 9fbbeb889..e96cce9a9 100644
--- a/src/libs/installer/libarchivewrapper.cpp
+++ b/src/libs/installer/libarchivewrapper.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -27,6 +27,7 @@
**************************************************************************/
#include "libarchivewrapper.h"
+#include "libarchivewrapper_p.h"
namespace QInstaller {
diff --git a/src/libs/installer/libarchivewrapper.h b/src/libs/installer/libarchivewrapper.h
index c638d10dc..062d53f4a 100644
--- a/src/libs/installer/libarchivewrapper.h
+++ b/src/libs/installer/libarchivewrapper.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,10 +31,11 @@
#include "installer_global.h"
#include "abstractarchive.h"
-#include "libarchivewrapper_p.h"
namespace QInstaller {
+class LibArchiveWrapperPrivate;
+
class INSTALLER_EXPORT LibArchiveWrapper : public AbstractArchive
{
Q_OBJECT
@@ -45,22 +46,22 @@ public:
explicit LibArchiveWrapper(QObject *parent = nullptr);
~LibArchiveWrapper();
- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- void setFilename(const QString &filename) Q_DECL_OVERRIDE;
+ bool open(QIODevice::OpenMode mode) override;
+ void close() override;
+ void setFilename(const QString &filename) override;
- QString errorString() const Q_DECL_OVERRIDE;
+ QString errorString() const override;
- bool extract(const QString &dirPath) Q_DECL_OVERRIDE;
- bool extract(const QString &dirPath, const quint64 totalFiles) Q_DECL_OVERRIDE;
- bool create(const QStringList &data) Q_DECL_OVERRIDE;
- QVector<ArchiveEntry> list() Q_DECL_OVERRIDE;
- bool isSupported() Q_DECL_OVERRIDE;
+ bool extract(const QString &dirPath) override;
+ bool extract(const QString &dirPath, const quint64 totalFiles) override;
+ bool create(const QStringList &data) override;
+ QVector<ArchiveEntry> list() override;
+ bool isSupported() override;
- void setCompressionLevel(const AbstractArchive::CompressionLevel level) Q_DECL_OVERRIDE;
+ void setCompressionLevel(const AbstractArchive::CompressionLevel level) override;
public Q_SLOTS:
- void cancel() Q_DECL_OVERRIDE;
+ void cancel() override;
private:
LibArchiveWrapperPrivate *const d;
diff --git a/src/libs/installer/libarchivewrapper_p.cpp b/src/libs/installer/libarchivewrapper_p.cpp
index 30f81554a..b4325243d 100644
--- a/src/libs/installer/libarchivewrapper_p.cpp
+++ b/src/libs/installer/libarchivewrapper_p.cpp
@@ -41,12 +41,14 @@ namespace QInstaller {
*/
/*!
+ \internal
\fn QInstaller::LibArchiveWrapperPrivate::dataBlockRequested()
Emitted when the server process has requested another data block.
*/
/*!
+ \internal
\fn QInstaller::LibArchiveWrapperPrivate::remoteWorkerFinished()
Emitted when the server process has finished extracting an archive.
@@ -105,7 +107,7 @@ void LibArchiveWrapperPrivate::setFilename(const QString &filename)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveSetFilename), filename, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveSetFilename), filename);
m_lock.unlock();
}
m_archive.setFilename(filename);
@@ -138,13 +140,14 @@ QString LibArchiveWrapperPrivate::errorString() const
*/
bool LibArchiveWrapperPrivate::extract(const QString &dirPath, const quint64 totalFiles)
{
+ const quint64 total = totalFiles ? totalFiles : m_archive.totalFiles();
if (connectToServer()) {
QTimer timer;
connect(&timer, &QTimer::timeout, this, &LibArchiveWrapperPrivate::processSignals);
timer.start();
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveExtract), dirPath, totalFiles);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveExtract), dirPath, total);
m_lock.unlock();
{
QEventLoop loop;
@@ -154,7 +157,7 @@ bool LibArchiveWrapperPrivate::extract(const QString &dirPath, const quint64 tot
timer.stop();
return (workerStatus() == ExtractWorker::Success);
}
- return m_archive.extract(dirPath, totalFiles);
+ return m_archive.extract(dirPath, total);
}
/*!
@@ -202,7 +205,7 @@ void LibArchiveWrapperPrivate::setCompressionLevel(const AbstractArchive::Compre
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveSetCompressionLevel), level, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveSetCompressionLevel), level);
m_lock.unlock();
return;
}
@@ -218,7 +221,7 @@ void LibArchiveWrapperPrivate::cancel()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveCancel));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveCancel));
m_lock.unlock();
return;
}
@@ -353,7 +356,7 @@ void LibArchiveWrapperPrivate::addDataBlock(const QByteArray &buffer)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveAddDataBlock), buffer, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveAddDataBlock), buffer);
m_lock.unlock();
}
}
@@ -366,7 +369,7 @@ void LibArchiveWrapperPrivate::setClientDataAtEnd()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveSetClientDataAtEnd));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveSetClientDataAtEnd));
m_lock.unlock();
}
}
@@ -378,7 +381,7 @@ void LibArchiveWrapperPrivate::setClientFilePosition(qint64 pos)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveSetFilePosition), pos, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveSetFilePosition), pos);
m_lock.unlock();
}
}
diff --git a/src/libs/installer/libarchivewrapper_p.h b/src/libs/installer/libarchivewrapper_p.h
index 4277cd4f9..9e612fab3 100644
--- a/src/libs/installer/libarchivewrapper_p.h
+++ b/src/libs/installer/libarchivewrapper_p.h
@@ -32,7 +32,6 @@
#include "installer_global.h"
#include "remoteobject.h"
#include "libarchivearchive.h"
-#include "lib7zarchive.h"
#include <QTimer>
#include <QReadWriteLock>
diff --git a/src/libs/installer/licenseoperation.cpp b/src/libs/installer/licenseoperation.cpp
index a5a61c71f..0d30ab514 100644
--- a/src/libs/installer/licenseoperation.cpp
+++ b/src/libs/installer/licenseoperation.cpp
@@ -31,6 +31,7 @@
#include "packagemanagercore.h"
#include "settings.h"
#include "fileutils.h"
+#include "globals.h"
#include <QtCore/QDir>
#include <QtCore/QFile>
@@ -56,7 +57,7 @@ void LicenseOperation::backup()
bool LicenseOperation::performOperation()
{
- QVariantMap licenses = value(QLatin1String("licenses")).toMap();
+ QVariantMap licenses = value(scLicensesValue).toMap();
if (licenses.isEmpty()) {
setError(UserDefinedError);
setErrorString(tr("No license files found to copy."));
@@ -80,14 +81,17 @@ bool LicenseOperation::performOperation()
for (QVariantMap::const_iterator it = licenses.constBegin(); it != licenses.constEnd(); ++it) {
QFile file(targetDir + QLatin1Char('/') + it.key());
- if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
setError(UserDefinedError);
setErrorString(tr("Can not write license file \"%1\".").arg(QDir::toNativeSeparators(file.fileName())));
return false;
}
- QTextStream stream(&file);
+ QString outString;
+ QTextStream stream(&outString);
stream << it.value().toString();
+
+ file.write(outString.toUtf8());
}
return true;
@@ -95,11 +99,10 @@ bool LicenseOperation::performOperation()
bool LicenseOperation::undoOperation()
{
- const QVariantMap licenses = value(QLatin1String("licenses")).toMap();
+ const QVariantMap licenses = value(scLicensesValue).toMap();
if (licenses.isEmpty()) {
- setError(UserDefinedError);
- setErrorString(tr("No license files found to delete."));
- return false;
+ qCWarning(QInstaller::lcInstallerInstallLog) << "No license files found to delete.";
+ return true;
}
QString targetDir = arguments().value(0);
diff --git a/src/libs/installer/licenseoperation.h b/src/libs/installer/licenseoperation.h
index 49b885565..6e7743428 100644
--- a/src/libs/installer/licenseoperation.h
+++ b/src/libs/installer/licenseoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT LicenseOperation : public Operation
public:
explicit LicenseOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
} // namespace QInstaller
diff --git a/src/libs/installer/linereplaceoperation.h b/src/libs/installer/linereplaceoperation.h
index d15e11fef..13e764acc 100644
--- a/src/libs/installer/linereplaceoperation.h
+++ b/src/libs/installer/linereplaceoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT LineReplaceOperation : public Operation
public:
explicit LineReplaceOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
} // namespace
diff --git a/src/libs/installer/link.cpp b/src/libs/installer/link.cpp
index ff9f49696..027dac232 100644
--- a/src/libs/installer/link.cpp
+++ b/src/libs/installer/link.cpp
@@ -263,7 +263,7 @@ QString Link::targetPath() const
#ifdef Q_OS_WIN
return readWindowsSymLink(m_path);
#else
- return QFileInfo(m_path).readLink();
+ return QFileInfo(m_path).symLinkTarget();
#endif
}
diff --git a/src/libs/installer/loggingutils.cpp b/src/libs/installer/loggingutils.cpp
index a2b561c53..9a36720dd 100644
--- a/src/libs/installer/loggingutils.cpp
+++ b/src/libs/installer/loggingutils.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,13 +29,14 @@
#include "loggingutils.h"
#include "component.h"
-#include "localpackagehub.h"
+#include "componentalias.h"
#include "globals.h"
#include "fileutils.h"
+#include "packagemanagercore.h"
#include "remoteclient.h"
#include "remotefileengine.h"
-#include <QDomDocument>
+#include <QXmlStreamWriter>
#include <QElapsedTimer>
#include <iostream>
@@ -111,6 +112,7 @@ public:
*/
LoggingHandler::LoggingHandler()
: m_verbLevel(VerbosityLevel::Silent)
+ , m_outputRedirected(false)
{
#if defined(Q_OS_UNIX)
m_outputRedirected = !isatty(fileno(stdout));
@@ -133,6 +135,8 @@ LoggingHandler::~LoggingHandler()
*/
void LoggingHandler::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
+ QMutexLocker _(&m_mutex);
+
// suppress warning from QPA minimal plugin
if (msg.contains(QLatin1String("This plugin does not support propagateSizeHints")))
return;
@@ -250,21 +254,26 @@ bool LoggingHandler::outputRedirected() const
/*!
Prints update information from \a components.
*/
-void LoggingHandler::printUpdateInformation(const QList<Component *> components) const
+void LoggingHandler::printUpdateInformation(const QList<Component *> &components) const
{
- QDomDocument doc;
- QDomElement root = doc.createElement(QLatin1String("updates"));
- doc.appendChild(root);
+ QString output;
+ QXmlStreamWriter stream(&output);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument();
+ stream.writeStartElement(QLatin1String("updates"));
foreach (const Component *component, components) {
- QDomElement update = doc.createElement(QLatin1String("update"));
- update.setAttribute(QLatin1String("name"), component->value(scDisplayName));
- update.setAttribute(QLatin1String("version"), component->value(scVersion));
- update.setAttribute(QLatin1String("size"), component->value(scUncompressedSize));
- update.setAttribute(QLatin1String("id"), component->value(scName));
- root.appendChild(update);
+ stream.writeStartElement(QLatin1String("update"));
+ stream.writeAttribute(QLatin1String("name"), component->value(scDisplayName));
+ stream.writeAttribute(QLatin1String("version"), component->value(scVersion));
+ stream.writeAttribute(QLatin1String("size"), component->value(scUncompressedSize));
+ stream.writeAttribute(QLatin1String("id"), component->value(scName));
+ stream.writeEndElement();
}
- std::cout << qPrintable(doc.toString(4));
+ stream.writeEndElement();
+
+ stream.writeEndDocument();
+ std::cout << qPrintable(output);
}
/*!
@@ -273,28 +282,37 @@ void LoggingHandler::printUpdateInformation(const QList<Component *> components)
*/
void LoggingHandler::printLocalPackageInformation(const QList<KDUpdater::LocalPackage> &packages) const
{
- QDomDocument doc;
- QDomElement root = doc.createElement(QLatin1String("localpackages"));
- doc.appendChild(root);
+ QString output;
+ QXmlStreamWriter stream(&output);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument();
+
+ stream.writeStartElement(QLatin1String("localpackages"));
foreach (KDUpdater::LocalPackage package, packages) {
- QDomElement update = doc.createElement(QLatin1String("package"));
- update.setAttribute(QLatin1String("name"), package.name);
- update.setAttribute(QLatin1String("displayname"), package.title);
- update.setAttribute(QLatin1String("version"), package.version);
+ stream.writeStartElement(QLatin1String("package"));
+ stream.writeAttribute(QLatin1String("name"), package.name);
+ stream.writeAttribute(QLatin1String("displayname"), package.title);
+ stream.writeAttribute(QLatin1String("version"), package.version);
if (verboseLevel() == VerbosityLevel::Detailed) {
- update.setAttribute(QLatin1String("description"), package.description);
- update.setAttribute(QLatin1String("dependencies"), package.dependencies.join(QLatin1Char(',')));
- update.setAttribute(QLatin1String("autoDependencies"), package.autoDependencies.join(QLatin1Char(',')));
- update.setAttribute(QLatin1String("virtual"), package.virtualComp);
- update.setAttribute(QLatin1String("forcedInstallation"), package.forcedInstallation);
- update.setAttribute(QLatin1String("checkable"), package.checkable);
- update.setAttribute(QLatin1String("uncompressedSize"), package.uncompressedSize);
- update.setAttribute(QLatin1String("installDate"), package.installDate.toString());
- update.setAttribute(QLatin1String("lastUpdateDate"), package.lastUpdateDate.toString());
+ stream.writeAttribute(QLatin1String("description"), package.description);
+ stream.writeAttribute(QLatin1String("sortingPriority"), QVariant(package.sortingPriority).toString());
+ stream.writeAttribute(QLatin1String("treeName"), package.treeName.first);
+ stream.writeAttribute(QLatin1String("moveChildren"), QVariant(package.treeName.second).toString());
+ stream.writeAttribute(QLatin1String("dependencies"), package.dependencies.join(QLatin1Char(',')));
+ stream.writeAttribute(QLatin1String("autoDependencies"), package.autoDependencies.join(QLatin1Char(',')));
+ stream.writeAttribute(QLatin1String("virtual"), QVariant(package.virtualComp).toString());
+ stream.writeAttribute(QLatin1String("forcedInstallation"), QVariant(package.forcedInstallation).toString());
+ stream.writeAttribute(QLatin1String("checkable"), QVariant(package.checkable).toString());
+ stream.writeAttribute(QLatin1String("uncompressedSize"), QVariant(package.uncompressedSize).toString());
+ stream.writeAttribute(QLatin1String("installDate"), package.installDate.toString());
+ stream.writeAttribute(QLatin1String("lastUpdateDate"), package.lastUpdateDate.toString());
}
- root.appendChild(update);
+ stream.writeEndElement();
}
- std::cout << qPrintable(doc.toString(4));
+ stream.writeEndElement();
+
+ stream.writeEndDocument();
+ std::cout << qPrintable(output);
}
/*!
@@ -302,43 +320,89 @@ void LoggingHandler::printLocalPackageInformation(const QList<KDUpdater::LocalPa
depending on the current verbosity level. If a package is also present in \a installedPackages,
the installed version will be included in printed information.
*/
-void LoggingHandler::printPackageInformation(const PackagesList &matchedPackages, const LocalPackagesHash &installedPackages) const
+void LoggingHandler::printPackageInformation(const PackagesList &matchedPackages, const LocalPackagesMap &installedPackages) const
{
- QDomDocument doc;
- QDomElement root = doc.createElement(QLatin1String("availablepackages"));
- doc.appendChild(root);
+ QString output;
+ QXmlStreamWriter stream(&output);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument();
+
+ stream.writeStartElement(QLatin1String("availablepackages"));
foreach (Package *package, matchedPackages) {
const QString name = package->data(scName).toString();
- QDomElement update = doc.createElement(QLatin1String("package"));
- update.setAttribute(QLatin1String("name"), name);
- update.setAttribute(QLatin1String("displayname"), package->data(scDisplayName).toString());
- update.setAttribute(QLatin1String("version"), package->data(scVersion).toString());
+ stream.writeStartElement(QLatin1String("package"));
+ stream.writeAttribute(QLatin1String("name"), name);
+ stream.writeAttribute(QLatin1String("displayname"), package->data(scDisplayName).toString());
+ stream.writeAttribute(QLatin1String("version"), package->data(scVersion).toString());
//Check if package already installed
if (installedPackages.contains(name))
- update.setAttribute(QLatin1String("installedVersion"), installedPackages.value(name).version);
+ stream.writeAttribute(QLatin1String("installedVersion"), installedPackages.value(name).version);
if (verboseLevel() == VerbosityLevel::Detailed) {
- update.setAttribute(QLatin1String("description"), package->data(scDescription).toString());
- update.setAttribute(QLatin1String("dependencies"), package->data(scDependencies).toString());
- update.setAttribute(QLatin1String("autoDependencies"), package->data(scAutoDependOn).toString());
- update.setAttribute(QLatin1String("virtual"), package->data(scVirtual).toString());
- update.setAttribute(QLatin1String("forcedInstallation"), package->data(QLatin1String("ForcedInstallation")).toString());
- update.setAttribute(QLatin1String("checkable"), package->data(scCheckable).toString());
- update.setAttribute(QLatin1String("default"), package->data(scDefault).toString());
- update.setAttribute(QLatin1String("essential"), package->data(scEssential).toString());
- update.setAttribute(QLatin1String("forcedUpdate"), package->data(scForcedUpdate).toString());
- update.setAttribute(QLatin1String("compressedsize"), package->data(QLatin1String("CompressedSize")).toString());
- update.setAttribute(QLatin1String("uncompressedsize"), package->data(QLatin1String("UncompressedSize")).toString());
- update.setAttribute(QLatin1String("releaseDate"), package->data(scReleaseDate).toString());
- update.setAttribute(QLatin1String("downloadableArchives"), package->data(scDownloadableArchives).toString());
- update.setAttribute(QLatin1String("licenses"), package->data(QLatin1String("Licenses")).toString());
- update.setAttribute(QLatin1String("script"), package->data(scScript).toString());
- update.setAttribute(QLatin1String("sortingPriority"), package->data(scSortingPriority).toString());
- update.setAttribute(QLatin1String("replaces"), package->data(scReplaces).toString());
- update.setAttribute(QLatin1String("requiresAdminRights"), package->data(scRequiresAdminRights).toString());
+ stream.writeAttribute(QLatin1String("description"), package->data(scDescription).toString());
+ stream.writeAttribute(QLatin1String("treeName"), package->data(scTreeName).value<QPair<QString, bool>>().first);
+ stream.writeAttribute(QLatin1String("moveChildren"), QVariant(package->data(scTreeName).value<QPair<QString, bool>>().second).toString());
+ stream.writeAttribute(QLatin1String("dependencies"), package->data(scDependencies).toString());
+ stream.writeAttribute(QLatin1String("autoDependencies"), package->data(scAutoDependOn).toString());
+ stream.writeAttribute(QLatin1String("virtual"), package->data(scVirtual).toString());
+ stream.writeAttribute(QLatin1String("forcedInstallation"), package->data(QLatin1String("ForcedInstallation")).toString());
+ stream.writeAttribute(QLatin1String("checkable"), package->data(scCheckable).toString());
+ stream.writeAttribute(QLatin1String("default"), package->data(scDefault).toString());
+ stream.writeAttribute(QLatin1String("essential"), package->data(scEssential).toString());
+ stream.writeAttribute(QLatin1String("forcedUpdate"), package->data(scForcedUpdate).toString());
+ stream.writeAttribute(QLatin1String("compressedsize"), package->data(QLatin1String("CompressedSize")).toString());
+ stream.writeAttribute(QLatin1String("uncompressedsize"), package->data(QLatin1String("UncompressedSize")).toString());
+ stream.writeAttribute(QLatin1String("releaseDate"), package->data(scReleaseDate).toString());
+ stream.writeAttribute(QLatin1String("downloadableArchives"), package->data(scDownloadableArchives).toString());
+ stream.writeAttribute(QLatin1String("licenses"), package->data(QLatin1String("Licenses")).toString());
+ stream.writeAttribute(QLatin1String("script"), package->data(scScript).toString());
+ stream.writeAttribute(QLatin1String("sortingPriority"), package->data(scSortingPriority).toString());
+ stream.writeAttribute(QLatin1String("replaces"), package->data(scReplaces).toString());
+ stream.writeAttribute(QLatin1String("requiresAdminRights"), package->data(scRequiresAdminRights).toString());
+ }
+ stream.writeEndElement();
+ }
+ stream.writeEndElement();
+
+ stream.writeEndDocument();
+ std::cout << qPrintable(output);
+}
+
+/*!
+ Prints basic or more detailed information about component \a aliases,
+ depending on the current verbosity level.
+*/
+void LoggingHandler::printAliasInformation(const QList<ComponentAlias *> &aliases)
+{
+ QList<ComponentAlias *> sortedAliases = aliases;
+ std::sort(sortedAliases.begin(), sortedAliases.end(),
+ [](const ComponentAlias *lhs, const ComponentAlias *rhs) {
+ return lhs->name() < rhs->name();
}
- root.appendChild(update);
+ );
+
+ QString output;
+ QTextStream stream(&output);
+
+ stream << Qt::endl;
+ for (auto *alias : qAsConst(sortedAliases)) {
+ stream << "Name: " << alias->name() << Qt::endl;
+ stream << "Display name: " << alias->displayName() << Qt::endl;
+ stream << "Description: " << alias->description() << Qt::endl;
+ stream << "Version: " << alias->version() << Qt::endl;
+ if (verboseLevel() == VerbosityLevel::Detailed)
+ stream << "Virtual: " << alias->value(scVirtual) << Qt::endl;
+
+ stream << "Components: " << alias->value(scRequiredComponents) << Qt::endl;
+ stream << "Required aliases: " << alias->value(scRequiredAliases) << Qt::endl;
+
+ stream << "Optional components: " << alias->value(scOptionalComponents) << Qt::endl;
+ stream << "Optional aliases: " << alias->value(scOptionalAliases) << Qt::endl;
+
+ if (sortedAliases.indexOf(alias) != (sortedAliases.count() - 1))
+ stream << "========================================" << Qt::endl;
}
- std::cout << qPrintable(doc.toString(4));
+
+ std::cout << qPrintable(output);
}
/*!
@@ -418,7 +482,7 @@ VerboseWriter *VerboseWriter::instance()
*/
void VerboseWriter::appendLine(const QString &msg)
{
- m_stream << msg << endl;
+ m_stream << msg << Qt::endl;
}
/*!
diff --git a/src/libs/installer/loggingutils.h b/src/libs/installer/loggingutils.h
index 06f0400f8..18ff2d2c5 100644
--- a/src/libs/installer/loggingutils.h
+++ b/src/libs/installer/loggingutils.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,12 +29,20 @@
#ifndef LOGGINGUTILS_H
#define LOGGINGUTILS_H
-#include "component.h"
+#include "qinstallerglobal.h"
+#include "localpackagehub.h"
#include <QObject>
+#include <QIODevice>
+#include <QTextStream>
+#include <QBuffer>
+#include <QMutex>
namespace QInstaller {
+class Component;
+class ComponentAlias;
+
class INSTALLER_EXPORT LoggingHandler
{
Q_DISABLE_COPY(LoggingHandler)
@@ -57,9 +65,10 @@ public:
VerbosityLevel verboseLevel() const;
bool outputRedirected() const;
- void printUpdateInformation(const QList<Component *> components) const;
+ void printUpdateInformation(const QList<Component *> &components) const;
void printLocalPackageInformation(const QList<KDUpdater::LocalPackage> &packages) const;
- void printPackageInformation(const PackagesList &matchedPackages, const LocalPackagesHash &installedPackages) const;
+ void printPackageInformation(const PackagesList &matchedPackages, const LocalPackagesMap &installedPackages) const;
+ void printAliasInformation(const QList<ComponentAlias *> &aliases);
friend VerbosityLevel &operator++(VerbosityLevel &level, int);
friend VerbosityLevel &operator--(VerbosityLevel &level, int);
@@ -73,6 +82,8 @@ private:
private:
VerbosityLevel m_verbLevel;
bool m_outputRedirected;
+
+ QMutex m_mutex;
};
class INSTALLER_EXPORT VerboseWriterOutput
diff --git a/src/libs/installer/messageboxhandler.cpp b/src/libs/installer/messageboxhandler.cpp
index e2d461ba8..052709e51 100644
--- a/src/libs/installer/messageboxhandler.cpp
+++ b/src/libs/installer/messageboxhandler.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -368,6 +368,9 @@ static QMessageBox::StandardButton showNewMessageBox(QWidget *parent, QMessageBo
QMessageBox::StandardButton defaultButton)
{
QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent);
+ msgBox.setTextInteractionFlags(Qt::TextBrowserInteraction);
+ msgBox.setTextFormat(Qt::RichText);
+
QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox *>();
Q_ASSERT(buttonBox != nullptr);
diff --git a/src/libs/installer/metadata.cpp b/src/libs/installer/metadata.cpp
new file mode 100644
index 000000000..2eccb020e
--- /dev/null
+++ b/src/libs/installer/metadata.cpp
@@ -0,0 +1,410 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "metadata.h"
+
+#include "constants.h"
+#include "globals.h"
+#include "metadatajob.h"
+
+#include <QCryptographicHash>
+#include <QDir>
+#include <QDomDocument>
+#include <QFile>
+#include <QByteArrayMatcher>
+
+namespace QInstaller {
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::Metadata
+ \brief The Metadata class represents fetched metadata from a repository.
+*/
+
+
+/*!
+ \internal
+*/
+static bool verifyFileIntegrityFromElement(const QDomElement &element, const QString &childNodeName,
+ const QString &attribute, const QString &metaDirectory, bool testChecksum)
+{
+ const QDomNodeList nodes = element.childNodes();
+ for (int i = 0; i < nodes.count(); ++i) {
+ const QDomNode node = nodes.at(i);
+ if (node.nodeName() != childNodeName)
+ continue;
+
+ const QDir dir(metaDirectory);
+ const QString filename = attribute.isEmpty()
+ ? node.toElement().text()
+ : node.toElement().attribute(attribute);
+
+ if (filename.isEmpty())
+ continue;
+
+ QFile file(dir.absolutePath() + QDir::separator() + filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << file.fileName()
+ << "for reading:" << file.errorString();
+ return false;
+ }
+
+ if (!testChecksum)
+ continue;
+
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(&file);
+
+ const QByteArray checksum = hash.result().toHex();
+ if (!QFileInfo::exists(dir.absolutePath() + QDir::separator()
+ + QString::fromLatin1(checksum) + QLatin1String(".sha1"))) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Unexpected checksum for file" << file.fileName();
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ Constructs a new metadata object.
+*/
+Metadata::Metadata()
+ : CacheableItem()
+ , m_fromDefaultRepository(false)
+{
+}
+
+/*!
+ Constructs a new metadata object with a \a path.
+*/
+Metadata::Metadata(const QString &path)
+ : CacheableItem(path)
+ , m_fromDefaultRepository(false)
+{
+}
+
+/*!
+ Returns the checksum of this metadata which is the checksum of the Updates.xml file.
+ The checksum value is stored to memory after first read, so a single object should
+ not be reused for referring other metadata.
+*/
+QByteArray Metadata::checksum() const
+{
+ if (!m_checksum.isEmpty())
+ return m_checksum;
+
+ QFile updateFile(path() + QLatin1String("/Updates.xml"));
+ if (!updateFile.open(QIODevice::ReadOnly))
+ return QByteArray();
+
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(&updateFile);
+ m_checksum = hash.result().toHex();
+
+ return m_checksum;
+}
+
+/*!
+ Sets the checksum of this metadata to \a checksum. Calling this function
+ will omit calculating the checksum from the update file when retrieving
+ the checksum with \l{checksum()} for the first time.
+*/
+void Metadata::setChecksum(const QByteArray &checksum)
+{
+ m_checksum = checksum;
+}
+
+/*!
+ Returns the root of the document tree representing the \c Updates.xml
+ document of this metadata. Returns an empty \c QDomDocument in case
+ of failure to reading the file.
+*/
+QDomDocument Metadata::updatesDocument() const
+{
+ QFile updateFile(path() + QLatin1String("/Updates.xml"));
+ if (!updateFile.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << updateFile.fileName()
+ << "for reading:" << updateFile.errorString();
+ return QDomDocument();
+ }
+
+ QDomDocument doc;
+ QString errorString;
+ if (!doc.setContent(&updateFile, &errorString)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot set document content:" << errorString;
+ return QDomDocument();
+ }
+
+ return doc;
+}
+
+/*!
+ Returns \c true if the \c Updates.xml document of this metadata exists, and that all
+ meta files referenced in the document exist. If the \c Updates.xml contains a \c Checksum
+ element with a value of \c true, the integrity of the files is also verified.
+
+ Returns \c false otherwise.
+*/
+bool Metadata::isValid() const
+{
+ QFile updateFile(path() + QLatin1String("/Updates.xml"));
+ if (!updateFile.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << updateFile.fileName()
+ << "for reading:" << updateFile.errorString();
+ return false;
+ }
+
+ return verifyMetaFiles(&updateFile);
+}
+
+/*!
+ Returns \c true if this metadata is active, \c false otherwise. Metadata is
+ considered active if it is currently associated with a valid repository.
+*/
+bool Metadata::isActive() const
+{
+ return m_repository.isValid();
+}
+
+/*!
+ Checks whether this metadata object obsoletes the \a other metadata. The other metadata
+ is considered obsolete if it is not currently associated with any repository, and the
+ URL of the calling metadata matches the last known URL of the other metadata. Returns
+ \c true if the current metadata obsoletes the other, \c false otherwise.
+*/
+bool Metadata::obsoletes(CacheableItem *other)
+{
+ if (Metadata *meta = dynamic_cast<Metadata *>(other)) {
+ // If the current metadata is not in use it should not replace anything.
+ if (!isActive())
+ return false;
+
+ // If the other metadata is in use it is not obsolete.
+ if (meta->isActive())
+ return false;
+
+ // Current metadata has the same persistent url as other metadata, other is obsolete.
+ if (persistentRepositoryPath() == meta->persistentRepositoryPath())
+ return true;
+
+ // The refreshed url of the current metadata matches the persistent url of other
+ // metadata, other is obsolete.
+ if (m_repository.url().path(QUrl::FullyEncoded) == meta->persistentRepositoryPath())
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Returns the repository object set for this metadata. This is the repository
+ the metadata is currently associated with, which may be different from the
+ repository where it was originally fetched.
+*/
+Repository Metadata::repository() const
+{
+ return m_repository;
+}
+
+/*!
+ Sets the \a repository object of this metadata. If a repository
+ is already set, the new one will override the previous one. The metadata becomes
+ associated with the set repository even if it was fetched from another one.
+*/
+void Metadata::setRepository(const Repository &repository)
+{
+ m_repository = repository;
+}
+
+/*!
+ Returns \c true if this metadata is available from a default repository,
+ which means a repository without category, \c false otherwise.
+*/
+bool Metadata::isAvailableFromDefaultRepository() const
+{
+ return m_fromDefaultRepository;
+}
+
+/*!
+ Sets the metadata available from a default repository based on the value
+ of \a defaultRepository. This is not mutually exclusive from a metadata
+ that has repository categories set.
+*/
+void Metadata::setAvailableFromDefaultRepository(bool defaultRepository)
+{
+ m_fromDefaultRepository = defaultRepository;
+}
+
+/*!
+ Sets the repository path of this metadata from \a url, without the protocol or hostname.
+ Unlike \l{setRepository()} this value is saved to disk, which allows retrieving the
+ repository path of the metadata on later runs.
+*/
+void Metadata::setPersistentRepositoryPath(const QUrl &url)
+{
+ const QString newPath = url.path(QUrl::FullyEncoded).trimmed();
+ if (m_persistentRepositoryPath == newPath)
+ return;
+
+ QFile file(path() + QLatin1String("/repository.txt"));
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << file.fileName() << "for writing:" << file.errorString();
+ return;
+ }
+ QTextStream out(&file);
+ out << newPath;
+
+ m_persistentRepositoryPath = newPath;
+}
+
+/*!
+ Returns the persistent repository path of the metadata.
+*/
+QString Metadata::persistentRepositoryPath()
+{
+ if (!m_persistentRepositoryPath.isEmpty())
+ return m_persistentRepositoryPath;
+
+ QFile file(path() + QLatin1String("/repository.txt"));
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << file.fileName() << "for reading:" << file.errorString();
+ return QString();
+ }
+ m_persistentRepositoryPath = QString::fromLatin1(file.readAll()).trimmed();
+ return m_persistentRepositoryPath;
+}
+
+/*!
+ Returns true if the updates document of this metadata contains the repository
+ update element, which can include actions to \c add, \c remove, and \c replace
+ repositories.
+
+ \note This function does not check that the repository updates are actually
+ valid, only that the updates document contains the \c RepositoryUpdate element.
+*/
+bool Metadata::containsRepositoryUpdates() const
+{
+ QFile updateFile(path() + QLatin1String("/Updates.xml"));
+ if (!updateFile.open(QIODevice::ReadOnly)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot open" << updateFile.fileName()
+ << "for reading:" << updateFile.errorString();
+ return false;
+ }
+
+ static const auto matcher = qMakeStaticByteArrayMatcher("<RepositoryUpdate>");
+ while (!updateFile.atEnd()) {
+ const QByteArray line = updateFile.readLine().simplified();
+ if (matcher.indexIn(line) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+/*!
+ Verifies that the files referenced in \a updateFile document exist
+ on disk. If the document contains a \c Checksum element with a value
+ of \c true, the integrity of the files is also verified.
+
+ Returns \c true if the meta files are valid, \c false otherwise.
+*/
+bool Metadata::verifyMetaFiles(QFile *updateFile) const
+{
+ QDomDocument doc;
+ QString errorString;
+ if (!doc.setContent(updateFile, &errorString)) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "Cannot set document content:" << errorString;
+ return false;
+ }
+
+ const QDomElement rootElement = doc.documentElement();
+ const QDomNodeList childNodes = rootElement.childNodes();
+
+ bool testChecksum = true;
+ const QDomElement checksumElement = rootElement.firstChildElement(QLatin1String("Checksum"));
+ if (!checksumElement.isNull())
+ testChecksum = (checksumElement.text().toLower() == scTrue);
+
+ for (int i = 0; i < childNodes.count(); ++i) {
+ const QDomElement element = childNodes.at(i).toElement();
+ if (element.isNull() || element.tagName() != QLatin1String("PackageUpdate"))
+ continue;
+
+ const QDomNodeList c2 = element.childNodes();
+ QString packageName;
+ QString unused1;
+ QString unused2;
+
+ // Only need the package name, so values for "online" and "testCheckSum" do not matter
+ if (!MetadataJob::parsePackageUpdate(c2, packageName, unused1, unused2, true, true))
+ continue; // nothing to check for this package
+
+ const QString packagePath = QString::fromLatin1("%1/%2/").arg(path(), packageName);
+ for (auto &metaTagName : scMetaElements) {
+ const QDomElement metaElement = element.firstChildElement(metaTagName);
+ if (metaElement.isNull())
+ continue;
+
+ if (metaElement.tagName() == QLatin1String("Licenses")) {
+ if (!verifyFileIntegrityFromElement(metaElement, QLatin1String("License"),
+ QLatin1String("file"), packagePath, testChecksum)) {
+ return false;
+ }
+ } else if (metaElement.tagName() == QLatin1String("UserInterfaces")) {
+ if (!verifyFileIntegrityFromElement(metaElement, QLatin1String("UserInterface"),
+ QString(), packagePath, testChecksum)) {
+ return false;
+ }
+ } else if (metaElement.tagName() == QLatin1String("Translations")) {
+ if (!verifyFileIntegrityFromElement(metaElement, QLatin1String("Translation"),
+ QString(), packagePath, testChecksum)) {
+ return false;
+ }
+ } else if (metaElement.tagName() == QLatin1String("Script")) {
+ if (!verifyFileIntegrityFromElement(metaElement.parentNode().toElement(),
+ QLatin1String("Script"), QString(), packagePath, testChecksum)) {
+ return false;
+ }
+ } else {
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown meta element.");
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/metadata.h b/src/libs/installer/metadata.h
new file mode 100644
index 000000000..c7e4e857c
--- /dev/null
+++ b/src/libs/installer/metadata.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef METADATA_H
+#define METADATA_H
+
+#include "installer_global.h"
+#include "genericdatacache.h"
+#include "repository.h"
+
+#include <QDomDocument>
+
+class QFile;
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT Metadata : public CacheableItem
+{
+public:
+ Metadata();
+ explicit Metadata(const QString &path);
+ ~Metadata() {}
+
+ QByteArray checksum() const override;
+ void setChecksum(const QByteArray &checksum);
+ QDomDocument updatesDocument() const;
+
+ bool isValid() const override;
+ bool isActive() const override;
+ bool obsoletes(CacheableItem *other) override;
+
+ Repository repository() const;
+ void setRepository(const Repository &repository);
+
+ bool isAvailableFromDefaultRepository() const;
+ void setAvailableFromDefaultRepository(bool defaultRepository);
+
+ void setPersistentRepositoryPath(const QUrl &url);
+ QString persistentRepositoryPath();
+
+ bool containsRepositoryUpdates() const;
+
+private:
+ bool verifyMetaFiles(QFile *updateFile) const;
+
+private:
+ Repository m_repository;
+ QString m_persistentRepositoryPath;
+ mutable QByteArray m_checksum;
+
+ bool m_fromDefaultRepository;
+};
+
+} // namespace QInstaller
+
+#endif // METADATA_H
diff --git a/src/libs/installer/metadatacache.cpp b/src/libs/installer/metadatacache.cpp
new file mode 100644
index 000000000..744e455f4
--- /dev/null
+++ b/src/libs/installer/metadatacache.cpp
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "metadatacache.h"
+
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
+namespace QInstaller {
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::MetadataCache
+ \brief The MetadataCache is a class for a checksum based storage of \c Metadata objects on disk.
+
+ MetadataCache manages a cache storage for a set \l{path()}, which contains
+ a subdirectory for each registered \c Metadata item. The cache has a manifest file in
+ its root directory, which lists the version and type of the cache, and all its items.
+ The file is updated automatically when the metadata cache object is destructed, or
+ it can be updated periodically by calling \l{sync()}.
+*/
+
+/*!
+ Constructs a new empty cache. The cache is invalid until set with a
+ path and initialized.
+*/
+MetadataCache::MetadataCache()
+ : GenericDataCache<Metadata>()
+{
+ setType(QLatin1String("Metadata"));
+ setVersion(QLatin1String(QUOTE(IFW_CACHE_FORMAT_VERSION)));
+}
+
+/*!
+ Constructs a cache to \a path. The cache is initialized automatically.
+*/
+MetadataCache::MetadataCache(const QString &path)
+ : GenericDataCache(path, QLatin1String("Metadata"), QLatin1String(QUOTE(IFW_CACHE_FORMAT_VERSION)))
+{
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/metadatacache.h b/src/libs/installer/metadatacache.h
new file mode 100644
index 000000000..804d1b6db
--- /dev/null
+++ b/src/libs/installer/metadatacache.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef METADATACACHE_H
+#define METADATACACHE_H
+
+#include "genericdatacache.h"
+#include "metadata.h"
+
+namespace QInstaller {
+
+class MetadataCache : public GenericDataCache<Metadata>
+{
+public:
+ MetadataCache();
+ explicit MetadataCache(const QString &path);
+};
+
+} // namespace QInstaller
+
+#endif // METADATACACHE_H
diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp
index 68a242ebc..1bed304c6 100644
--- a/src/libs/installer/metadatajob.cpp
+++ b/src/libs/installer/metadatajob.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -38,31 +38,18 @@
#include "globals.h"
#include <QTemporaryDir>
+#include <QtConcurrent>
#include <QtMath>
#include <QRandomGenerator>
-
-const QStringList metaElements = {QLatin1String("Script"), QLatin1String("Licenses"), QLatin1String("UserInterfaces"), QLatin1String("Translations")};
+#include <QApplication>
namespace QInstaller {
/*!
- \inmodule QtInstallerFramework
- \class QInstaller::Metadata
- \internal
-*/
-
-/*!
- \inmodule QtInstallerFramework
- \class QInstaller::ArchiveMetadata
- \internal
-*/
-
-/*!
\enum QInstaller::DownloadType
\value All
\value CompressedPackage
- \value UpdatesXML
*/
/*!
@@ -97,6 +84,7 @@ MetadataJob::MetadataJob(QObject *parent)
, m_downloadType(DownloadType::All)
, m_downloadableChunkSize(1000)
, m_taskNumber(0)
+ , m_defaultRepositoriesFetched(false)
{
QByteArray downloadableChunkSize = qgetenv("IFW_METADATA_SIZE");
if (!downloadableChunkSize.isEmpty()) {
@@ -109,12 +97,19 @@ MetadataJob::MetadataJob(QObject *parent)
connect(&m_xmlTask, &QFutureWatcherBase::finished, this, &MetadataJob::xmlTaskFinished);
connect(&m_metadataTask, &QFutureWatcherBase::finished, this, &MetadataJob::metadataTaskFinished);
connect(&m_metadataTask, &QFutureWatcherBase::progressValueChanged, this, &MetadataJob::progressChanged);
+ connect(&m_updateCacheTask, &QFutureWatcherBase::finished, this, &MetadataJob::updateCacheTaskFinished);
}
MetadataJob::~MetadataJob()
{
resetCompressedFetch();
reset();
+
+ if (!m_core)
+ return;
+
+ if (m_metaFromCache.isValid() && !m_core->settings().persistentLocalCache())
+ m_metaFromCache.clear();
}
/*
@@ -123,26 +118,101 @@ MetadataJob::~MetadataJob()
* repositories which might not be currently selected.
*/
-QList<Metadata> MetadataJob::metadata() const
+QList<Metadata *> MetadataJob::metadata() const
{
- QList<Metadata> metadata = m_metaFromDefaultRepositories.values();
- foreach (RepositoryCategory repositoryCategory, m_core->settings().repositoryCategories()) {
- if (m_core->isUpdater() || (repositoryCategory.isEnabled() && m_fetchedArchive.contains(repositoryCategory.displayname()))) {
- QList<ArchiveMetadata> archiveMetaList = m_fetchedArchive.values(repositoryCategory.displayname());
- foreach (ArchiveMetadata archiveMeta, archiveMetaList) {
- metadata.append(archiveMeta.metaData);
- }
+ const QSet<RepositoryCategory> categories = m_core->settings().repositoryCategories();
+ QHash<RepositoryCategory, QSet<Repository>> repositoryHash;
+ // Create hash of categorized repositories to avoid constructing
+ // excess temp objects when filtering below.
+ for (const RepositoryCategory &category : categories)
+ repositoryHash.insert(category, category.repositories());
+
+ QList<Metadata *> metadata = m_metaFromCache.items();
+ // Filter cache items not associated with current repositories and categories
+ QtConcurrent::blockingFilter(metadata, [&](const Metadata *item) {
+ if (!item->isActive())
+ return false;
+
+ // No need to check if the repository is enabled here. Changing the network
+ // settings resets the cache and we don't fetch the disabled repositories,
+ // so the cached items stay inactive.
+
+ if (item->isAvailableFromDefaultRepository())
+ return true;
+
+ QHash<RepositoryCategory, QSet<Repository>>::const_iterator it;
+ for (it = repositoryHash.constBegin(); it != repositoryHash.constEnd(); ++it) {
+ if (!it.key().isEnabled())
+ continue; // Let's try the next one
+
+ if (it->contains(item->repository()))
+ return true;
}
- }
+ return false;
+ });
+
return metadata;
}
-Repository MetadataJob::repositoryForDirectory(const QString &directory) const
+/*
+ Returns a repository object from the cache item matching \a directory. If the
+ \a directory does not belong to the cache, an empty repository is returned.
+*/
+Repository MetadataJob::repositoryForCacheDirectory(const QString &directory) const
{
- if (m_metaFromDefaultRepositories.contains(directory))
- return m_metaFromDefaultRepositories.value(directory).repository;
- else
- return m_metaFromArchive.value(directory).repository;
+ QDir dir(directory);
+ if (!QDir::fromNativeSeparators(dir.path())
+ .startsWith(QDir::fromNativeSeparators(m_metaFromCache.path()))) {
+ return Repository();
+ }
+ const QString dirName = dir.dirName();
+ Metadata *cachedMeta = m_metaFromCache.itemByChecksum(dirName.toUtf8());
+ if (cachedMeta)
+ return cachedMeta->repository();
+
+ return Repository();
+}
+
+bool MetadataJob::resetCache(bool init)
+{
+ // Need the path from current settings
+ if (!m_core) {
+ qCWarning(lcInstallerInstallLog) << "Cannot reset metadata cache: "
+ "missing package manager core engine.";
+ return false;
+ }
+
+ if (m_metaFromCache.isValid() && !m_core->settings().persistentLocalCache())
+ m_metaFromCache.clear();
+
+ m_metaFromCache.setPath(m_core->settings().localCachePath());
+
+ if (!init)
+ return true;
+
+ const bool success = m_metaFromCache.initialize();
+ if (success) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Using metadata cache from"
+ << m_metaFromCache.path();
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Found"
+ << m_metaFromCache.items().count() << "cached items.";
+ }
+ return success;
+}
+
+bool MetadataJob::clearCache()
+{
+ if (m_metaFromCache.clear())
+ return true;
+
+ setError(JobError::CacheError);
+ setErrorString(m_metaFromCache.errorString());
+ return false;
+}
+
+bool MetadataJob::isValidCache() const
+{
+ return m_metaFromCache.isValid();
}
// -- private slots
@@ -151,39 +221,91 @@ void MetadataJob::doStart()
{
setError(Job::NoError);
setErrorString(QString());
+ m_metadataResult.clear();
+ setProgressTotalAmount(100);
+
if (!m_core) {
emitFinishedWithError(Job::Canceled, tr("Missing package manager core engine."));
return; // We can't do anything here without core, so avoid tons of !m_core checks.
}
+ if (!m_metaFromCache.isValid() && !resetCache(true)) {
+ emitFinishedWithError(JobError::CacheError, m_metaFromCache.errorString());
+ return;
+ }
+
const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance();
- if (m_downloadType == DownloadType::All || m_downloadType == DownloadType::UpdatesXML) {
- emit infoMessage(this, tr("Preparing meta information download..."));
+ if (m_downloadType != DownloadType::CompressedPackage) {
+ emit infoMessage(this, tr("Fetching latest update information..."));
const bool onlineInstaller = m_core->isInstaller() && !m_core->isOfflineOnly();
- if (onlineInstaller || m_core->isMaintainer()) {
- QList<FileTaskItem> items;
- QSet<Repository> repositories = getRepositories();
+ const QSet<Repository> repositories = getRepositories();
+
+ if (onlineInstaller || m_core->isMaintainer()
+ || (m_core->settings().allowRepositoriesForOfflineInstaller() && !repositories.isEmpty())) {
+ static const QString updateFilePath(QLatin1Char('/') + scUpdatesXML + QLatin1Char('?'));
+ static const QString randomQueryString = QString::number(QRandomGenerator::global()->generate());
+
+ quint64 cachedCount = 0;
+ setProgressTotalAmount(0); // Show only busy indicator during this loop as we have no progress to measure
foreach (const Repository &repo, repositories) {
+ // For not blocking the UI
+ qApp->processEvents();
+
if (repo.isEnabled() &&
productKeyCheck->isValidRepository(repo)) {
QAuthenticator authenticator;
authenticator.setUser(repo.username());
authenticator.setPassword(repo.password());
- if (!repo.isCompressed()) {
- QString url = repo.url().toString() + QLatin1String("/Updates.xml?");
- if (!m_core->value(scUrlQueryString).isEmpty())
- url += m_core->value(scUrlQueryString) + QLatin1Char('&');
+ if (repo.isCompressed())
+ continue;
+
+ QString url;
+ url = repo.url().toString() + updateFilePath;
+ if (!m_core->value(scUrlQueryString).isEmpty())
+ url += m_core->value(scUrlQueryString) + QLatin1Char('&');
+ // also append a random string to avoid proxy caches
+ url.append(randomQueryString);
+
+ // Check if we can skip downloading already cached repositories
+ const Status foundStatus = findCachedUpdatesFile(repo, url);
+ if (foundStatus == XmlDownloadSuccess) {
+ // Found existing Updates.xml
+ ++cachedCount;
+ continue;
+ } else if (foundStatus == XmlDownloadRetry) {
+ // Repositories changed, restart with the new repositories
+ QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
+ return;
+ }
- // also append a random string to avoid proxy caches
- FileTaskItem item(url.append(QString::number(QRandomGenerator::global()->generate())));
- item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
- item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
- items.append(item);
+ QTemporaryDir tmp(QDir::tempPath() + QLatin1String("/remoterepo-XXXXXX"));
+ if (!tmp.isValid()) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot create unique temporary directory.";
+ continue;
}
+ tmp.setAutoRemove(false);
+ m_tempDirDeleter.add(tmp.path());
+ FileTaskItem item(url, tmp.path() + QLatin1String("/Updates.xml"));
+ item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
+ item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
+ m_updatesXmlItems.append(item);
}
}
- if (items.count() > 0) {
- startXMLTask(items);
+ setProgressTotalAmount(100);
+ const quint64 totalCount = repositories.count();
+ if (cachedCount > 0) {
+ qCDebug(lcInstallerInstallLog).nospace() << "Loaded from cache "
+ << cachedCount << "/" << totalCount << ". Downloading remaining "
+ << m_updatesXmlItems.count() << "/" << totalCount <<".";
+ } else {
+ qCDebug(lcInstallerInstallLog).nospace() <<"Downloading " << m_updatesXmlItems.count()
+ << " items to cache.";
+ }
+ if (m_updatesXmlItems.count() > 0) {
+ double taskCount = m_updatesXmlItems.length()/static_cast<double>(m_downloadableChunkSize);
+ m_totalTaskCount = qCeil(taskCount);
+ m_taskNumber = 0;
+ startXMLTask();
} else {
emitFinished();
}
@@ -222,18 +344,28 @@ void MetadataJob::doStart()
}
}
-void MetadataJob::startXMLTask(const QList<FileTaskItem> &items)
+bool MetadataJob::startXMLTask()
{
- DownloadFileTask *const xmlTask = new DownloadFileTask(items);
- xmlTask->setProxyFactory(m_core->proxyFactory());
- connect(&m_xmlTask, &QFutureWatcher<FileTaskResult>::progressValueChanged, this,
- &MetadataJob::progressChanged);
- m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
+ int chunkSize = qMin(m_updatesXmlItems.length(), m_downloadableChunkSize);
+ QList<FileTaskItem> tempPackages = m_updatesXmlItems.mid(0, chunkSize);
+ m_updatesXmlItems = m_updatesXmlItems.mid(chunkSize, m_updatesXmlItems.length());
+ if (tempPackages.length() > 0) {
+ DownloadFileTask *const xmlTask = new DownloadFileTask(tempPackages);
+ xmlTask->setProxyFactory(m_core->proxyFactory());
+ connect(&m_xmlTask, &QFutureWatcher<FileTaskResult>::progressValueChanged, this,
+ &MetadataJob::progressChanged);
+ m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
+
+ setInfoMessage(tr("Retrieving information from remote repositories..."));
+ return true;
+ }
+ return false;
}
void MetadataJob::doCancel()
{
reset();
+ resetCache();
emitFinishedWithError(Job::Canceled, tr("Metadata download canceled."));
}
@@ -257,6 +389,27 @@ void MetadataJob::startUnzipRepositoryTask(const Repository &repo)
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
+void MetadataJob::startUpdateCacheTask()
+{
+ const int toRegisterCount = m_fetchedMetadata.count();
+ if (toRegisterCount > 0)
+ emit infoMessage(this, tr("Updating local cache with %n new items...",
+ nullptr, toRegisterCount));
+
+ UpdateCacheTask *task = new UpdateCacheTask(m_metaFromCache, m_fetchedMetadata);
+ m_updateCacheTask.setFuture(QtConcurrent::run(&UpdateCacheTask::doTask, task));
+}
+
+/*
+ Resets the repository information from all cache items, which
+ makes them inactive until associated with new repositories.
+*/
+void MetadataJob::resetCacheRepositories()
+{
+ for (auto *metaToReset : m_metaFromCache.items())
+ metaToReset->setRepository(Repository());
+}
+
void MetadataJob::unzipRepositoryTaskFinished()
{
QFutureWatcher<void> *watcher = static_cast<QFutureWatcher<void> *>(sender());
@@ -283,9 +436,17 @@ void MetadataJob::unzipRepositoryTaskFinished()
error = testJob.error();
errorString = testJob.errorString();
if (error == Job::NoError) {
- FileTaskItem item(url);
+ QTemporaryDir tmp(QDir::tempPath() + QLatin1String("/remoterepo-XXXXXX"));
+ if (!tmp.isValid()) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot create unique temporary directory.";
+ continue;
+ }
+ tmp.setAutoRemove(false);
+ m_tempDirDeleter.add(tmp.path());
+ FileTaskItem item(url, tmp.path() + QLatin1String("/Updates.xml"));
+
item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
- m_unzipRepositoryitems.append(item);
+ m_updatesXmlItems.append(item);
} else {
//Repository is not valid, remove it
Settings &s = m_core->settings();
@@ -305,8 +466,8 @@ void MetadataJob::unzipRepositoryTaskFinished()
//One can specify many zipped repository items at once. As the repositories are
//unzipped one by one, we collect here all items before parsing xml files from those.
- if (m_unzipRepositoryitems.count() > 0 && m_unzipRepositoryTasks.isEmpty()) {
- startXMLTask(m_unzipRepositoryitems);
+ if (m_updatesXmlItems.count() > 0 && m_unzipRepositoryTasks.isEmpty()) {
+ startXMLTask();
} else {
if (error != Job::NoError) {
emitFinishedWithError(QInstaller::DownloadError, errorString);
@@ -330,19 +491,34 @@ void MetadataJob::xmlTaskFinished()
Status status = XmlDownloadFailure;
try {
m_xmlTask.waitForFinished();
- status = parseUpdatesXml(m_xmlTask.future().results());
+ m_updatesXmlResult.append(m_xmlTask.future().results());
+ if (!startXMLTask()) {
+ status = parseUpdatesXml(m_updatesXmlResult);
+ m_updatesXmlResult.clear();
+ } else {
+ return;
+ }
} catch (const AuthenticationRequiredException &e) {
if (e.type() == AuthenticationRequiredException::Type::Proxy) {
- const QNetworkProxy proxy = e.proxy();
- ProxyCredentialsDialog proxyCredentials(proxy);
qCWarning(QInstaller::lcInstallerInstallLog) << e.message();
-
- if (proxyCredentials.exec() == QDialog::Accepted) {
+ QString username;
+ QString password;
+ const QNetworkProxy proxy = e.proxy();
+ if (m_core->isCommandLineInstance()) {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote() << QString::fromLatin1("The proxy %1:%2 requires a username and password").arg(proxy.hostName(), proxy.port());
+ askForCredentials(&username, &password, QLatin1String("Username: "), QLatin1String("Password: "));
+ } else {
+ ProxyCredentialsDialog proxyCredentials(proxy);
+ if (proxyCredentials.exec() == QDialog::Accepted) {
+ username = proxyCredentials.userName();
+ password = proxyCredentials.password();
+ }
+ }
+ if (!username.isEmpty()) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Retrying with new credentials ...";
PackageManagerProxyFactory *factory = m_core->proxyFactory();
- factory->setProxyCredentials(proxy, proxyCredentials.userName(),
- proxyCredentials.password());
+ factory->setProxyCredentials(proxy, username, password);
m_core->setProxyFactory(factory);
status = XmlDownloadRetry;
} else {
@@ -351,13 +527,25 @@ void MetadataJob::xmlTaskFinished()
}
} else if (e.type() == AuthenticationRequiredException::Type::Server) {
qCWarning(QInstaller::lcInstallerInstallLog) << e.message();
- ServerAuthenticationDialog dlg(e.message(), e.taskItem());
- if (dlg.exec() == QDialog::Accepted) {
+ QString username;
+ QString password;
+ if (m_core->isCommandLineInstance()) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Server Requires Authentication";
+ qCDebug(QInstaller::lcInstallerInstallLog) << "You need to supply a username and password to access this site.";
+ askForCredentials(&username, &password, QLatin1String("Username: "), QLatin1String("Password: "));
+ } else {
+ ServerAuthenticationDialog dlg(e.message(), e.taskItem());
+ if (dlg.exec() == QDialog::Accepted) {
+ username = dlg.user();
+ password = dlg.password();
+ }
+ }
+ if (!username.isEmpty()) {
Repository original = e.taskItem().value(TaskRole::UserRole)
.value<Repository>();
Repository replacement = original;
- replacement.setUsername(dlg.user());
- replacement.setPassword(dlg.password());
+ replacement.setUsername(username);
+ replacement.setPassword(password);
Settings &s = m_core->settings();
QSet<Repository> temporaries = s.temporaryRepositories();
@@ -366,7 +554,7 @@ void MetadataJob::xmlTaskFinished()
temporaries.insert(replacement);
s.addTemporaryRepositories(temporaries, true);
} else {
- QHash<QString, QPair<Repository, Repository> > update;
+ QMultiHash<QString, QPair<Repository, Repository> > update;
update.insert(QLatin1String("replace"), qMakePair(original, replacement));
if (s.updateRepositoryCategories(update) == Settings::UpdatesApplied)
@@ -407,13 +595,13 @@ void MetadataJob::xmlTaskFinished()
return;
if (status == XmlDownloadSuccess) {
- if (m_downloadType != DownloadType::UpdatesXML) {
- if (!fetchMetaDataPackages())
- emitFinished();
- } else {
- emitFinished();
+ if (!fetchMetaDataPackages()) {
+ // No new metadata packages to fetch, still need to update the cache
+ // for refreshed repositories.
+ startUpdateCacheTask();
}
} else if (status == XmlDownloadRetry) {
+ reset();
QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
} else {
reset();
@@ -441,10 +629,8 @@ void MetadataJob::unzipTaskFinished()
m_unzipTasks.remove(watcher);
delete watcher;
- if (m_unzipTasks.isEmpty()) {
- setProcessedAmount(100);
- emitFinished();
- }
+ if (m_unzipTasks.isEmpty())
+ startUpdateCacheTask();
}
void MetadataJob::progressChanged(int progress)
@@ -476,17 +662,29 @@ void MetadataJob::metadataTaskFinished()
} else {
throw QInstaller::TaskException(mismatchMessage);
}
+ QFileInfo fi(result.target());
+ QString targetPath = fi.absolutePath();
+ if (m_fetchedMetadata.contains(targetPath)) {
+ delete m_fetchedMetadata.value(targetPath);
+ m_fetchedMetadata.remove(targetPath);
+ }
+ continue;
}
UnzipArchiveTask *task = new UnzipArchiveTask(result.target(),
item.value(TaskRole::UserRole).toString());
+ task->setRemoveArchive(true);
+ task->setStoreChecksums(true);
QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
m_unzipTasks.insert(watcher, qobject_cast<QObject*> (task));
connect(watcher, &QFutureWatcherBase::finished, this, &MetadataJob::unzipTaskFinished);
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
+ if (m_unzipTasks.isEmpty())
+ startUpdateCacheTask();
+
} else {
- emitFinished();
+ startUpdateCacheTask();
}
}
} catch (const TaskException &e) {
@@ -501,6 +699,25 @@ void MetadataJob::metadataTaskFinished()
}
}
+void MetadataJob::updateCacheTaskFinished()
+{
+ try {
+ m_updateCacheTask.waitForFinished();
+ } catch (const CacheTaskException &e) {
+ emitFinishedWithError(QInstaller::CacheError, e.message());
+ } catch (const QUnhandledException &e) {
+ emitFinishedWithError(QInstaller::CacheError, QLatin1String(e.what()));
+ } catch (...) {
+ emitFinishedWithError(QInstaller::CacheError, tr("Unknown exception during updating cache."));
+ }
+
+ if (error() != Job::NoError)
+ return;
+
+ setProcessedAmount(100);
+ emitFinished();
+}
+
// -- private
@@ -511,18 +728,11 @@ bool MetadataJob::fetchMetaDataPackages()
QList<FileTaskItem> tempPackages = m_packages.mid(0, chunkSize);
m_packages = m_packages.mid(chunkSize, m_packages.length());
if (tempPackages.length() > 0) {
- m_taskNumber++;
setProcessedAmount(0);
DownloadFileTask *const metadataTask = new DownloadFileTask(tempPackages);
metadataTask->setProxyFactory(m_core->proxyFactory());
m_metadataTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, metadataTask));
- setProgressTotalAmount(100);
- QString metaInformation;
- if (m_totalTaskCount > 1)
- metaInformation = tr("Retrieving meta information from remote repository... %1/%2 ").arg(m_taskNumber).arg(m_totalTaskCount);
- else
- metaInformation = tr("Retrieving meta information from remote repository... ");
- emit infoMessage(this, metaInformation);
+ setInfoMessage(tr("Retrieving meta information from remote repository..."));
return true;
}
return false;
@@ -531,9 +741,12 @@ bool MetadataJob::fetchMetaDataPackages()
void MetadataJob::reset()
{
m_packages.clear();
- m_metaFromDefaultRepositories.clear();
- m_metaFromArchive.clear();
- m_fetchedArchive.clear();
+ m_updatesXmlItems.clear();
+ m_defaultRepositoriesFetched = false;
+ m_fetchedCategorizedRepositories.clear();
+
+ qDeleteAll(m_fetchedMetadata);
+ m_fetchedMetadata.clear();
setError(Job::NoError);
setErrorString(QString());
@@ -547,6 +760,7 @@ void MetadataJob::reset()
} catch (...) {}
m_tempDirDeleter.releaseAndDeleteAll();
m_metadataResult.clear();
+ m_updatesXmlResult.clear();
m_taskNumber = 0;
}
@@ -554,7 +768,6 @@ void MetadataJob::resetCompressedFetch()
{
setError(Job::NoError);
setErrorString(QString());
- m_unzipRepositoryitems.clear();
try {
foreach (QFutureWatcher<void> *const watcher, m_unzipTasks.keys()) {
@@ -586,43 +799,54 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
if (result.target().isEmpty()) {
continue;
}
- Metadata metadata;
- QTemporaryDir tmp(QDir::tempPath() + QLatin1String("/remoterepo-XXXXXX"));
- if (!tmp.isValid()) {
- qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot create unique temporary directory.";
- return XmlDownloadFailure;
- }
-
- tmp.setAutoRemove(false);
- metadata.directory = tmp.path();
- m_tempDirDeleter.add(metadata.directory);
+ QFileInfo fileInfo(result.target());
+ std::unique_ptr<Metadata> metadata(new Metadata(fileInfo.absolutePath()));
QFile file(result.target());
- if (!file.rename(metadata.directory + QLatin1String("/Updates.xml"))) {
- qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot rename target to Updates.xml:"
- << file.errorString();
- return XmlDownloadFailure;
- }
-
if (!file.open(QIODevice::ReadOnly)) {
qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot open Updates.xml for reading:"
<< file.errorString();
return XmlDownloadFailure;
}
+ const FileTaskItem item = result.value(TaskRole::TaskItem).value<FileTaskItem>();
+ const Repository repository = item.value(TaskRole::UserRole).value<Repository>();
+
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(&file);
+ const QByteArray updatesChecksum = hash.result().toHex();
+
+ if (!repository.xmlChecksum().isEmpty() && updatesChecksum != repository.xmlChecksum()) {
+ qCWarning(lcDeveloperBuild).noquote().nospace() << "The checksum for Updates.xml "
+ "file downloaded from repository:\n" << repository.url().toString() << "\ndoes not "
+ "match the expected value:\n\tActual SHA1: " << updatesChecksum << "\n\tExpected SHA1: "
+ << repository.xmlChecksum() << Qt::endl;
+ }
+
+ bool refreshed;
+ // Check if we have cached the metadata for this repository already
+ Status status = refreshCacheItem(result, updatesChecksum, &refreshed);
+ if (status != XmlDownloadSuccess)
+ return status;
+
+ if (refreshed) // Found existing metadata
+ continue;
+
+ metadata->setChecksum(updatesChecksum);
+
+ file.seek(0);
QString error;
QDomDocument doc;
if (!doc.setContent(&file, &error)) {
qCWarning(QInstaller::lcInstallerInstallLog).nospace() << "Cannot fetch a valid version of Updates.xml from repository "
- << metadata.repository.displayname() << ": " << error;
+ << metadata->repository().displayname() << ": " << error;
//If there are other repositories, try to use those
continue;
}
file.close();
- const FileTaskItem item = result.value(TaskRole::TaskItem).value<FileTaskItem>();
- metadata.repository = item.value(TaskRole::UserRole).value<Repository>();
- const bool online = !(metadata.repository.url().scheme()).isEmpty();
+ metadata->setRepository(repository);
+ const bool online = !(metadata->repository().url().scheme()).isEmpty();
bool testCheckSum = true;
const QDomElement root = doc.documentElement();
@@ -634,14 +858,14 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
// all metadata inside one repository to a single 7z file. Fetch that
// instead of component specific meta 7z files.
const QDomNode sha1 = root.firstChildElement(scSHA1);
- QDomElement metadataNameElement = root.firstChildElement(QLatin1String("MetadataName"));
+ QDomElement metadataNameElement = root.firstChildElement(scMetadataName);
QDomNodeList children = root.childNodes();
if (!sha1.isNull() && !metadataNameElement.isNull()) {
- const QString repoUrl = metadata.repository.url().toString();
- const QString metadataName = metadataNameElement.toElement().text();
- addFileTaskItem(QString::fromLatin1("%1/%2").arg(repoUrl, metadataName),
- metadata.directory + QString::fromLatin1("/%1").arg(metadataName),
- metadata, sha1.toElement().text(), QString());
+ const QString repoUrl = metadata->repository().url().toString();
+ const QString metadataName = metadataNameElement.toElement().text();
+ addFileTaskItem(QString::fromLatin1("%1/%2").arg(repoUrl, metadataName),
+ metadata->path() + QString::fromLatin1("/%1").arg(metadataName),
+ metadata.get(), sha1.toElement().text(), QString());
} else {
bool metaFound = false;
for (int i = 0; i < children.count(); ++i) {
@@ -653,16 +877,13 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
online, testCheckSum);
// If meta element (script, licenses, etc.) is not found, no need to fetch metadata.
- // The offline-generator instance is an exception to this - if the Updates.xml contains
- // checksum element for the meta-archive, we will fetch it, so that the temporary
- // location contents match the remote repository.
- if (metaFound || (m_core->isOfflineGenerator() && !packageHash.isEmpty())) {
- const QString repoUrl = metadata.repository.url().toString();
+ if (metaFound) {
+ const QString repoUrl = metadata->repository().url().toString();
addFileTaskItem(QString::fromLatin1("%1/%2/%3meta.7z").arg(repoUrl, packageName, packageVersion),
- metadata.directory + QString::fromLatin1("/%1-%2-meta.7z").arg(packageName, packageVersion),
- metadata, packageHash, packageName);
+ metadata->path() + QString::fromLatin1("/%1-%2-meta.7z").arg(packageName, packageVersion),
+ metadata.get(), packageHash, packageName);
} else {
- QString fileName = metadata.directory + QLatin1Char('/') + packageName;
+ QString fileName = metadata->path() + QLatin1Char('/') + packageName;
QDir directory(fileName);
if (!directory.exists()) {
directory.mkdir(fileName);
@@ -672,40 +893,24 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
}
}
- if (metadata.repository.categoryname().isEmpty()) {
- m_metaFromDefaultRepositories.insert(metadata.directory, metadata);
- } else {
- //Hash metadata to help checking if meta for repository is already fetched
- ArchiveMetadata archiveMetadata;
- archiveMetadata.metaData = metadata;
- m_fetchedArchive.insertMulti(metadata.repository.categoryname(), archiveMetadata);
-
- //Check if other categories have the same url (contains same metadata)
- //so we can speed up other category fetches
- foreach (RepositoryCategory category, m_core->settings().repositoryCategories()) {
- if (category.displayname() != metadata.repository.categoryname()) {
- foreach (Repository repository, category.repositories()) {
- if (repository.url() == metadata.repository.url()) {
- m_fetchedArchive.insertMulti(category.displayname(), archiveMetadata);
- }
- }
- }
- }
- // Hash for faster lookups
- m_metaFromArchive.insert(metadata.directory, metadata);
- }
+ // Remember the fetched metadata
+ Metadata *const metadataPtr = metadata.get();
+ const QString categoryName = metadata->repository().categoryname();
+ if (categoryName.isEmpty())
+ metadata->setAvailableFromDefaultRepository(true);
+ else
+ m_fetchedCategorizedRepositories.insert(metadataPtr->repository()); // For faster lookups
+ const QString metadataPath = metadata->path();
+ m_fetchedMetadata.insert(metadataPath, metadata.release());
// search for additional repositories that we might need to check
- const QDomNode repositoryUpdate = root.firstChildElement(QLatin1String("RepositoryUpdate"));
- if (!repositoryUpdate.isNull()) {
- QHash<QString, QPair<Repository, Repository> > repositoryUpdates =
- searchAdditionalRepositories(repositoryUpdate, result, metadata);
- if (!repositoryUpdates.isEmpty()) {
- MetadataJob::Status status = setAdditionalRepositories(repositoryUpdates, result, metadata);
- if (status == XmlDownloadRetry)
- return status;
- }
+ status = parseRepositoryUpdates(root, result, metadataPtr);
+ if (status == XmlDownloadRetry) {
+ // The repository update may have removed or replaced current repositories,
+ // clear repository information from cached items and refresh on next fetch run.
+ resetCacheRepositories();
+ return status;
}
}
double taskCount = m_packages.length()/static_cast<double>(m_downloadableChunkSize);
@@ -715,46 +920,128 @@ MetadataJob::Status MetadataJob::parseUpdatesXml(const QList<FileTaskResult> &re
return XmlDownloadSuccess;
}
+MetadataJob::Status MetadataJob::refreshCacheItem(const FileTaskResult &result,
+ const QByteArray &checksum, bool *refreshed)
+{
+ Q_ASSERT(refreshed);
+ *refreshed = false;
+
+ Metadata *cachedMetadata = m_metaFromCache.itemByChecksum(checksum);
+ if (!cachedMetadata)
+ return XmlDownloadSuccess;
+
+ const FileTaskItem item = result.value(TaskRole::TaskItem).value<FileTaskItem>();
+ const Repository repository = item.value(TaskRole::UserRole).value<Repository>();
+
+ if (cachedMetadata->isValid() && !repository.isCompressed()) {
+ // Refresh repository information to cache. Same repository may appear in multiple
+ // categories and the metadata may be available from default repositories simultaneously.
+ cachedMetadata->setRepository(repository);
+ if (!repository.categoryname().isEmpty())
+ m_fetchedCategorizedRepositories.insert(repository); // For faster lookups
+ else
+ cachedMetadata->setAvailableFromDefaultRepository(true);
+
+ // Refresh also persistent information, the url of the repository may have changed
+ // from the last fetch.
+ cachedMetadata->setPersistentRepositoryPath(repository.url());
+
+ // search for additional repositories that we might need to check
+ if (cachedMetadata->containsRepositoryUpdates()) {
+ QDomDocument doc = cachedMetadata->updatesDocument();
+ const Status status = parseRepositoryUpdates(doc.documentElement(), result, cachedMetadata);
+ if (status == XmlDownloadRetry) {
+ // The repository update may have removed or replaced current repositories,
+ // clear repository information from cached items and refresh on next fetch run.
+ resetCacheRepositories();
+ return status;
+ }
+ }
+ *refreshed = true;
+ return XmlDownloadSuccess;
+ }
+ // Missing or corrupted files, or compressed repository which takes priority
+ // over remote repository. We will re-download and uncompress
+ // the metadata. Remove broken item from the cache.
+ if (!m_metaFromCache.removeItem(checksum)) {
+ qCWarning(lcInstallerInstallLog) << m_metaFromCache.errorString();
+ return XmlDownloadFailure;
+ }
+ return XmlDownloadSuccess;
+}
+
+MetadataJob::Status MetadataJob::findCachedUpdatesFile(const Repository &repository, const QString &fileUrl)
+{
+ if (repository.xmlChecksum().isEmpty())
+ return XmlDownloadFailure;
+
+ Metadata *metadata = m_metaFromCache.itemByChecksum(repository.xmlChecksum());
+ if (!metadata)
+ return XmlDownloadFailure;
+
+ const QString targetPath = metadata->path() + QLatin1Char('/') + scUpdatesXML;
+
+ FileTaskItem cachedMetaTaskItem(fileUrl, targetPath);
+ cachedMetaTaskItem.insert(TaskRole::UserRole, QVariant::fromValue(repository));
+ const FileTaskResult cachedMetaTaskResult(targetPath, repository.xmlChecksum(), cachedMetaTaskItem, false);
+
+ bool isCached = false;
+ const Status status = refreshCacheItem(cachedMetaTaskResult, repository.xmlChecksum(), &isCached);
+ if (isCached)
+ return XmlDownloadSuccess;
+ else if (status == XmlDownloadRetry)
+ return XmlDownloadRetry;
+ else
+ return XmlDownloadFailure;
+}
+
+MetadataJob::Status MetadataJob::parseRepositoryUpdates(const QDomElement &root,
+ const FileTaskResult &result, Metadata *metadata)
+{
+ MetadataJob::Status status = XmlDownloadSuccess;
+ const QDomNode repositoryUpdate = root.firstChildElement(QLatin1String("RepositoryUpdate"));
+ if (!repositoryUpdate.isNull()) {
+ const QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates
+ = searchAdditionalRepositories(repositoryUpdate, result, *metadata);
+ if (!repositoryUpdates.isEmpty())
+ status = setAdditionalRepositories(repositoryUpdates, result, *metadata);
+ }
+ return status;
+}
+
QSet<Repository> MetadataJob::getRepositories()
{
QSet<Repository> repositories;
- //In the first run, m_metadata is empty. Get always the default repositories
- if (m_metaFromDefaultRepositories.isEmpty()) {
+ //In the first run, get always the default repositories
+ if (!m_defaultRepositoriesFetched) {
repositories = m_core->settings().repositories();
+ m_defaultRepositoriesFetched = true;
}
// Fetch repositories under archive which are selected in UI.
// If repository is already fetched, do not fetch it again.
- // In updater mode, fetch always all archive repositories to get updates
- foreach (RepositoryCategory repositoryCategory, m_core->settings().repositoryCategories()) {
- if (m_core->isUpdater() || (repositoryCategory.isEnabled())) {
- foreach (Repository repository, repositoryCategory.repositories()) {
- QHashIterator<QString, ArchiveMetadata> i(m_fetchedArchive);
- bool fetch = true;
- while (i.hasNext()) {
- i.next();
- ArchiveMetadata metaData = i.value();
- if (repository.url() == metaData.metaData.repository.url())
- fetch = false;
- }
- if (fetch)
- repositories.insert(repository);
- }
- }
+ for (const RepositoryCategory &repositoryCategory : m_core->settings().repositoryCategories()) {
+ if (!repositoryCategory.isEnabled())
+ continue;
+
+ for (const Repository &repository : repositoryCategory.repositories()) {
+ if (!m_fetchedCategorizedRepositories.contains(repository))
+ repositories.insert(repository);
+ }
}
return repositories;
}
-void MetadataJob::addFileTaskItem(const QString &source, const QString &target, const Metadata &metadata,
+void MetadataJob::addFileTaskItem(const QString &source, const QString &target, Metadata *metadata,
const QString &sha1, const QString &packageName)
{
FileTaskItem item(source, target);
QAuthenticator authenticator;
- authenticator.setUser(metadata.repository.username());
- authenticator.setPassword(metadata.repository.password());
+ authenticator.setUser(metadata->repository().username());
+ authenticator.setPassword(metadata->repository().password());
- item.insert(TaskRole::UserRole, metadata.directory);
+ item.insert(TaskRole::UserRole, metadata->path());
item.insert(TaskRole::Checksum, sha1.toLatin1());
item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
item.insert(TaskRole::Name, packageName);
@@ -775,7 +1062,7 @@ bool MetadataJob::parsePackageUpdate(const QDomNodeList &c2, QString &packageNam
else if ((element.tagName() == QLatin1String("SHA1")) && testCheckSum)
packageHash = element.text();
else {
- foreach (QString meta, metaElements) {
+ foreach (QString meta, scMetaElements) {
if (element.tagName() == meta) {
metaFound = true;
break;
@@ -786,10 +1073,10 @@ bool MetadataJob::parsePackageUpdate(const QDomNodeList &c2, QString &packageNam
return metaFound;
}
-QHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepositories
+QMultiHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepositories
(const QDomNode &repositoryUpdate, const FileTaskResult &result, const Metadata &metadata)
{
- QHash<QString, QPair<Repository, Repository> > repositoryUpdates;
+ QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates;
const QDomNodeList children = repositoryUpdate.toElement().childNodes();
for (int i = 0; i < children.count(); ++i) {
const QDomElement el = children.at(i).toElement();
@@ -802,14 +1089,14 @@ QHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepo
repository.setPassword(el.attribute(QLatin1String("password")));
repository.setDisplayName(el.attribute(QLatin1String("displayname")));
if (ProductKeyCheck::instance()->isValidRepository(repository)) {
- repositoryUpdates.insertMulti(action, qMakePair(repository, Repository()));
+ repositoryUpdates.insert(action, qMakePair(repository, Repository()));
qDebug() << "Repository to add:" << repository.displayname();
}
} else if (action == QLatin1String("remove")) {
// remove possible default repositories using the given server url
Repository repository(resolveUrl(result, el.attribute(QLatin1String("url"))), true);
repository.setDisplayName(el.attribute(QLatin1String("displayname")));
- repositoryUpdates.insertMulti(action, qMakePair(repository, Repository()));
+ repositoryUpdates.insert(action, qMakePair(repository, Repository()));
qDebug() << "Repository to remove:" << repository.displayname();
} else if (action == QLatin1String("replace")) {
@@ -822,27 +1109,27 @@ QHash<QString, QPair<Repository, Repository> > MetadataJob::searchAdditionalRepo
if (ProductKeyCheck::instance()->isValidRepository(newRepository)) {
// store the new repository and the one old it replaces
- repositoryUpdates.insertMulti(action, qMakePair(newRepository, oldRepository));
+ repositoryUpdates.insert(action, qMakePair(newRepository, oldRepository));
qDebug() << "Replace repository" << oldRepository.displayname() << "with"
<< newRepository.displayname();
}
} else {
qDebug() << "Invalid additional repositories action set in Updates.xml fetched "
- "from" << metadata.repository.displayname() << "line:" << el.lineNumber();
+ "from" << metadata.repository().displayname() << "line:" << el.lineNumber();
}
}
}
return repositoryUpdates;
}
-MetadataJob::Status MetadataJob::setAdditionalRepositories(QHash<QString, QPair<Repository, Repository> > repositoryUpdates,
+MetadataJob::Status MetadataJob::setAdditionalRepositories(QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates,
const FileTaskResult &result, const Metadata& metadata)
{
MetadataJob::Status status = XmlDownloadSuccess;
Settings &s = m_core->settings();
const QSet<Repository> temporaries = s.temporaryRepositories();
// in case the temp repository introduced something new, we only want that temporary
- if (temporaries.contains(metadata.repository)) {
+ if (temporaries.contains(metadata.repository())) {
QSet<Repository> tmpRepositories;
typedef QPair<Repository, Repository> RepositoryPair;
@@ -858,7 +1145,9 @@ MetadataJob::Status MetadataJob::setAdditionalRepositories(QHash<QString, QPair<
if (tmpRepositories.count() > 0) {
s.addTemporaryRepositories(tmpRepositories, true);
QFile::remove(result.target());
- m_metaFromDefaultRepositories.clear();
+ m_defaultRepositoriesFetched = false;
+ qDeleteAll(m_fetchedMetadata);
+ m_fetchedMetadata.clear();
status = XmlDownloadRetry;
}
} else if (s.updateDefaultRepositories(repositoryUpdates) == Settings::UpdatesApplied) {
@@ -872,10 +1161,22 @@ MetadataJob::Status MetadataJob::setAdditionalRepositories(QHash<QString, QPair<
if (gainedAdminRights)
m_core->dropAdminRights();
}
- m_metaFromDefaultRepositories.clear();
+ m_defaultRepositoriesFetched = false;
+ qDeleteAll(m_fetchedMetadata);
+ m_fetchedMetadata.clear();
QFile::remove(result.target());
status = XmlDownloadRetry;
}
return status;
}
+
+void MetadataJob::setInfoMessage(const QString &message)
+{
+ m_taskNumber++;
+ QString metaInformation = message;
+ if (m_totalTaskCount > 1)
+ metaInformation = QLatin1String(" %1 %2/%3 ").arg(message).arg(m_taskNumber).arg(m_totalTaskCount);
+ emit infoMessage(this, metaInformation);
+
+}
} // namespace QInstaller
diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h
index eb0e91a4f..13ad3ea8c 100644
--- a/src/libs/installer/metadatajob.h
+++ b/src/libs/installer/metadatajob.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,8 @@
#include "downloadfiletask.h"
#include "fileutils.h"
#include "job.h"
+#include "metadata.h"
+#include "metadatacache.h"
#include "repository.h"
#include <QFutureWatcher>
@@ -43,23 +45,10 @@ namespace QInstaller {
class PackageManagerCore;
-struct Metadata
-{
- QString directory;
- Repository repository;
-};
-
-struct ArchiveMetadata
-{
- QString archive;
- Metadata metaData;
-};
-
enum DownloadType
{
All,
- CompressedPackage,
- UpdatesXML
+ CompressedPackage
};
class INSTALLER_EXPORT MetadataJob : public Job
@@ -77,59 +66,77 @@ public:
explicit MetadataJob(QObject *parent = 0);
~MetadataJob();
- QList<Metadata> metadata() const;
- Repository repositoryForDirectory(const QString &directory) const;
+ QList<Metadata *> metadata() const;
+ Repository repositoryForCacheDirectory(const QString &directory) const;
void setPackageManagerCore(PackageManagerCore *core) { m_core = core; }
void addDownloadType(DownloadType downloadType) { m_downloadType = downloadType;}
QStringList shaMismatchPackages() const { return m_shaMissmatchPackages; }
+ bool resetCache(bool init = false);
+ bool clearCache();
+ bool isValidCache() const;
+
private slots:
- void doStart();
- void doCancel();
+ void doStart() override;
+ void doCancel() override;
void xmlTaskFinished();
void unzipTaskFinished();
void metadataTaskFinished();
+ void updateCacheTaskFinished();
void progressChanged(int progress);
void setProgressTotalAmount(int maximum);
void unzipRepositoryTaskFinished();
- void startXMLTask(const QList<FileTaskItem> &items);
+ bool startXMLTask();
private:
bool fetchMetaDataPackages();
void startUnzipRepositoryTask(const Repository &repo);
+ void startUpdateCacheTask();
+ void resetCacheRepositories();
void reset();
void resetCompressedFetch();
Status parseUpdatesXml(const QList<FileTaskResult> &results);
+ Status refreshCacheItem(const FileTaskResult &result, const QByteArray &checksum, bool *refreshed);
+ Status findCachedUpdatesFile(const Repository &repository, const QString &fileUrl);
+ Status parseRepositoryUpdates(const QDomElement &root, const FileTaskResult &result, Metadata *metadata);
QSet<Repository> getRepositories();
- void addFileTaskItem(const QString &source, const QString &target, const Metadata &metadata,
+ void addFileTaskItem(const QString &source, const QString &target, Metadata *metadata,
const QString &sha1, const QString &packageName);
- bool parsePackageUpdate(const QDomNodeList &c2, QString &packageName, QString &packageVersion,
+ static bool parsePackageUpdate(const QDomNodeList &c2, QString &packageName, QString &packageVersion,
QString &packageHash, bool online, bool testCheckSum);
- QHash<QString, QPair<Repository, Repository> > searchAdditionalRepositories(const QDomNode &repositoryUpdate,
+ QMultiHash<QString, QPair<Repository, Repository> > searchAdditionalRepositories(const QDomNode &repositoryUpdate,
const FileTaskResult &result, const Metadata &metadata);
- MetadataJob::Status setAdditionalRepositories(QHash<QString, QPair<Repository, Repository> > repositoryUpdates,
+ MetadataJob::Status setAdditionalRepositories(QMultiHash<QString, QPair<Repository, Repository> > repositoryUpdates,
const FileTaskResult &result, const Metadata& metadata);
+ void setInfoMessage(const QString &message);
+
+private:
+ friend class Metadata;
private:
PackageManagerCore *m_core;
QList<FileTaskItem> m_packages;
- TempDirDeleter m_tempDirDeleter;
+ QList<FileTaskItem> m_updatesXmlItems;
+ TempPathDeleter m_tempDirDeleter;
QFutureWatcher<FileTaskResult> m_xmlTask;
QFutureWatcher<FileTaskResult> m_metadataTask;
+ QFutureWatcher<void> m_updateCacheTask;
QHash<QFutureWatcher<void> *, QObject*> m_unzipTasks;
QHash<QFutureWatcher<void> *, QObject*> m_unzipRepositoryTasks;
DownloadType m_downloadType;
- QList<FileTaskItem> m_unzipRepositoryitems;
QList<FileTaskResult> m_metadataResult;
+ QList<FileTaskResult> m_updatesXmlResult;
int m_downloadableChunkSize;
int m_taskNumber;
int m_totalTaskCount;
QStringList m_shaMissmatchPackages;
- QHash<QString, ArchiveMetadata> m_fetchedArchive;
- QHash<QString, Metadata> m_metaFromDefaultRepositories;
- QHash<QString, Metadata> m_metaFromArchive; //for faster lookups.
+ bool m_defaultRepositoriesFetched;
+
+ QSet<Repository> m_fetchedCategorizedRepositories;
+ QHash<QString, Metadata *> m_fetchedMetadata;
+ MetadataCache m_metaFromCache;
};
} // namespace QInstaller
diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h
index 99b48e626..837a7e9ae 100644
--- a/src/libs/installer/metadatajob_p.h
+++ b/src/libs/installer/metadatajob_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,9 +29,10 @@
#ifndef METADATAJOB_P_H
#define METADATAJOB_P_H
-#include "lib7zarchive.h"
+#include "archivefactory.h"
#include "metadatajob.h"
+#include <QCryptographicHash>
#include <QDir>
#include <QFile>
@@ -46,9 +47,9 @@ public:
: m_message(message)
{}
- void raise() const { throw *this; }
+ void raise() const override { throw *this; }
QString message() const { return m_message; }
- UnzipArchiveException *clone() const { return new UnzipArchiveException(*this); }
+ UnzipArchiveException *clone() const override{ return new UnzipArchiveException(*this); }
private:
QString m_message;
@@ -61,11 +62,18 @@ class UnzipArchiveTask : public AbstractTask<void>
public:
UnzipArchiveTask(const QString &arcive, const QString &target)
- : m_archive(arcive), m_targetDir(target)
+ : m_archive(arcive)
+ , m_targetDir(target)
+ , m_removeArchive(false)
+ , m_storeChecksums(false)
{}
+
QString target() { return m_targetDir; }
QString archive() { return m_archive; }
- void doTask(QFutureInterface<void> &fi)
+ void setRemoveArchive(bool remove) { m_removeArchive = remove; }
+ void setStoreChecksums(bool store) { m_storeChecksums = store; }
+
+ void doTask(QFutureInterface<void> &fi) override
{
fi.reportStarted();
fi.setExpectedResultCount(1);
@@ -75,22 +83,136 @@ public:
return; // ignore already canceled
}
- Lib7zArchive archive(m_archive);
- if (!archive.open(QIODevice::ReadOnly)) {
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create(m_archive));
+ if (!archive) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Unsupported archive \"%1\": no handler "
+ "registered for file suffix \"%2\".").arg(m_archive, QFileInfo(m_archive).suffix())));
+ return;
+ } else if (!archive->open(QIODevice::ReadOnly)) {
fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open file \"%1\" for "
- "reading: %2").arg(QDir::toNativeSeparators(m_archive), archive.errorString())));
- }
- if (!archive.extract(m_targetDir)) {
+ "reading: %2").arg(QDir::toNativeSeparators(m_archive), archive->errorString())));
+ return;
+ } else if (!archive->extract(m_targetDir)) {
fi.reportException(UnzipArchiveException(MetadataJob::tr("Error while extracting "
- "archive \"%1\": %2").arg(QDir::toNativeSeparators(m_archive), archive.errorString())));
+ "archive \"%1\": %2").arg(QDir::toNativeSeparators(m_archive), archive->errorString())));
+ return;
}
+ if (m_storeChecksums) {
+ // Calculate and store checksums of extracted files for later use
+ const QVector<ArchiveEntry> entries = archive->list();
+ for (auto &entry : entries) {
+ if (entry.isDirectory)
+ continue;
+
+ QFile file(m_targetDir + QDir::separator() + entry.path);
+ if (!file.open(QIODevice::ReadOnly)) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open extracted file \"%1\" for "
+ "reading: %2").arg(QDir::toNativeSeparators(file.fileName()), file.errorString())));
+ break;
+ }
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(&file);
+
+ const QByteArray hexChecksum = hash.result().toHex();
+ QFileInfo fileInfo(file.fileName());
+ QFile hashFile(fileInfo.absolutePath() + QDir::separator()
+ + QString::fromLatin1(hexChecksum) + QLatin1String(".sha1"));
+ if (!hashFile.open(QIODevice::WriteOnly)) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open file \"%1\" for "
+ "writing: %2").arg(QDir::toNativeSeparators(hashFile.fileName()), hashFile.errorString())));
+ break;
+ }
+ }
+ }
+
+ archive->close();
+ if (m_removeArchive)
+ QFile::remove(m_archive);
+
fi.reportFinished();
}
private:
QString m_archive;
QString m_targetDir;
+ bool m_removeArchive;
+ bool m_storeChecksums;
+};
+
+class CacheTaskException : public QException
+{
+public:
+ CacheTaskException() {}
+ explicit CacheTaskException(const QString &message)
+ : m_message(message)
+ {}
+ ~CacheTaskException() {}
+
+ void raise() const override { throw *this; }
+ QString message() const { return m_message; }
+ CacheTaskException *clone() const override { return new CacheTaskException(*this); }
+
+private:
+ QString m_message;
+};
+
+class UpdateCacheTask : public AbstractTask<void>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(UpdateCacheTask)
+
+public:
+ UpdateCacheTask(MetadataCache &cache, QHash<QString, Metadata *> &updates)
+ : m_cache(&cache)
+ , m_updates(&updates)
+ {}
+
+ void doTask(QFutureInterface<void> &fi) override
+ {
+ fi.reportStarted();
+ fi.setExpectedResultCount(1);
+
+ // Register items from current run to cache
+ QStringList registeredKeys;
+ bool success = true;
+ for (auto *meta : qAsConst(*m_updates)) {
+ if (!m_cache->registerItem(meta, true, MetadataCache::Move)) {
+ success = false;
+ break;
+ }
+ meta->setPersistentRepositoryPath(meta->repository().url());
+ registeredKeys.append(m_updates->key(meta));
+ }
+ // Remove items whose ownership was transferred to cache
+ for (auto &key : qAsConst(registeredKeys))
+ m_updates->remove(key);
+
+ // Bail out if there was error while registering items
+ if (!success) {
+ fi.reportException(CacheTaskException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ m_cache->sync();
+ fi.reportFinished();
+ return;
+ }
+
+ // ...and clean up obsolete cached items
+ const QList<Metadata *> obsolete = m_cache->obsoleteItems();
+ for (auto *meta : obsolete)
+ m_cache->removeItem(meta->checksum());
+
+ if (!m_cache->sync()) {
+ fi.reportException(CacheTaskException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ }
+
+ fi.reportFinished();
+ }
+
+private:
+ MetadataCache *const m_cache;
+ QHash<QString, Metadata *> *const m_updates;
};
} // namespace QInstaller
diff --git a/src/libs/installer/minimumprogressoperation.h b/src/libs/installer/minimumprogressoperation.h
index 4cdafca70..a16345730 100644
--- a/src/libs/installer/minimumprogressoperation.h
+++ b/src/libs/installer/minimumprogressoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -42,10 +42,10 @@ class MinimumProgressOperation : public QObject, public Operation
public:
explicit MinimumProgressOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
signals:
void progressChanged(double progress);
diff --git a/src/libs/installer/observer.cpp b/src/libs/installer/observer.cpp
index 30afce719..57b67d8e1 100644
--- a/src/libs/installer/observer.cpp
+++ b/src/libs/installer/observer.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -121,9 +121,9 @@ QByteArray FileTaskObserver::checkSum() const
return m_hash.result();
}
-void FileTaskObserver::addCheckSumData(const char *data, int length)
+void FileTaskObserver::addCheckSumData(const QByteArray &data)
{
- m_hash.addData(data, length);
+ m_hash.addData(data);
}
void FileTaskObserver::addSample(qint64 sample)
diff --git a/src/libs/installer/observer.h b/src/libs/installer/observer.h
index 166ede6ac..d638d8ee4 100644
--- a/src/libs/installer/observer.h
+++ b/src/libs/installer/observer.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -56,14 +56,14 @@ public:
FileTaskObserver(QCryptographicHash::Algorithm algorithm);
~FileTaskObserver();
- int progressValue() const;
- QString progressText() const;
+ int progressValue() const override;
+ QString progressText() const override;
QByteArray checkSum() const;
- void addCheckSumData(const char *data, int length);
+ void addCheckSumData(const QByteArray &data);
void addSample(qint64 sample);
- void timerEvent(QTimerEvent *event);
+ void timerEvent(QTimerEvent *event) override;
void setBytesTransfered(qint64 bytesTransfered);
void addBytesTransfered(qint64 bytesTransfered);
diff --git a/src/libs/installer/operationtracer.cpp b/src/libs/installer/operationtracer.cpp
new file mode 100644
index 000000000..b09c08d2e
--- /dev/null
+++ b/src/libs/installer/operationtracer.cpp
@@ -0,0 +1,151 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "operationtracer.h"
+
+#include "packagemanagercore.h"
+
+namespace QInstaller {
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::AbstractOperationTracer
+ \brief The AbstractOperationTracer is a pure virtual base class for classes
+ tracing starting and finishing of installer operations.
+*/
+
+/*!
+ \fn QInstaller::AbstractOperationTracer::~AbstractOperationTracer()
+
+ Destructs object. A subclass may override this method.
+*/
+
+/*!
+ \fn QInstaller::AbstractOperationTracer::trace(const QString &state)
+
+ Prints trace output for starting operation in \a state.
+ A subclass should implement this method.
+*/
+
+/*!
+ Constructs tracer for \a operation. Objects of this class cannot
+ be constructed directly, but the derived classes should explicitly call
+ the base class constructor in their constructors.
+*/
+AbstractOperationTracer::AbstractOperationTracer(Operation *operation)
+ : m_operation(nullptr)
+{
+ // don't create output for that hacky pseudo operation
+ if (operation->name() != QLatin1String("MinimumProgress"))
+ m_operation = operation;
+}
+
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::OperationTracer
+ \brief The OperationTracer prints trace output for starting of operations
+ and automatically indicates finish on destruction.
+*/
+
+/*!
+ Constructs tracer for \a operation.
+*/
+OperationTracer::OperationTracer(Operation *operation)
+ : AbstractOperationTracer(operation)
+{
+}
+
+/*!
+ Destructs object and prints message indicating finished operation.
+*/
+OperationTracer::~OperationTracer()
+{
+ if (!m_operation)
+ return;
+
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Done";
+}
+
+/*!
+ Prints trace output for starting operation in \a state.
+*/
+void OperationTracer::trace(const QString &state)
+{
+ if (!m_operation)
+ return;
+
+ qCDebug(lcInstallerInstallLog).noquote() << QString::fromLatin1("%1 %2 operation: %3")
+ .arg(state, m_operation->value(QLatin1String("component")).toString(), m_operation->name());
+
+ QStringList args = m_operation->arguments();
+ if (m_operation->requiresUnreplacedVariables())
+ args = m_operation->packageManager()->replaceVariables(m_operation->arguments());
+
+ qCDebug(lcInstallerInstallLog).noquote() << QString::fromLatin1("\t- arguments: %1")
+ .arg(args.join(QLatin1String(", ")));
+}
+
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::ConcurrentOperationTracer
+ \brief The ConcurrentOperationTracer prints trace output for starting of
+ asynchronous operations.
+*/
+
+/*!
+ Constructs tracer for \a operation.
+*/
+ConcurrentOperationTracer::ConcurrentOperationTracer(Operation *operation)
+ : AbstractOperationTracer(operation)
+{
+}
+
+/*!
+ Prints trace output for starting operation in \a state.
+*/
+void ConcurrentOperationTracer::trace(const QString &state)
+{
+ if (!m_operation)
+ return;
+
+ qCDebug(lcInstallerInstallLog).noquote() << QString::fromLatin1("%1 %2 concurrent operation: %3")
+ .arg(state, m_operation->value(QLatin1String("component")).toString(), m_operation->name());
+
+ QStringList args = m_operation->arguments();
+ if (m_operation->requiresUnreplacedVariables())
+ args = m_operation->packageManager()->replaceVariables(m_operation->arguments());
+
+ qCDebug(lcInstallerInstallLog).noquote() << QString::fromLatin1("\t- arguments: %1")
+ .arg(args.join(QLatin1String(", ")));
+
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Started";
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/operationtracer.h b/src/libs/installer/operationtracer.h
new file mode 100644
index 000000000..ce479662c
--- /dev/null
+++ b/src/libs/installer/operationtracer.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef OPERATIONTRACER_H
+#define OPERATIONTRACER_H
+
+#include "qinstallerglobal.h"
+#include "globals.h"
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT AbstractOperationTracer
+{
+public:
+ explicit AbstractOperationTracer(Operation *operation);
+ virtual ~AbstractOperationTracer() = default;
+
+ virtual void trace(const QString &state) = 0;
+
+protected:
+ Operation *m_operation;
+};
+
+class INSTALLER_EXPORT OperationTracer : public AbstractOperationTracer
+{
+public:
+ explicit OperationTracer(Operation *operation);
+ ~OperationTracer() override;
+
+ void trace(const QString &state) override;
+};
+
+class INSTALLER_EXPORT ConcurrentOperationTracer : public AbstractOperationTracer
+{
+public:
+ explicit ConcurrentOperationTracer(Operation *operation);
+
+ void trace(const QString &state) override;
+};
+
+} // namespace QInstaller
+
+#endif // OPERATIONTRACER_H
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 9d594b2eb..5c6f481f9 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,6 +31,7 @@
#include "adminauthorization.h"
#include "binarycontent.h"
#include "component.h"
+#include "componentalias.h"
#include "componentmodel.h"
#include "downloadarchivesjob.h"
#include "errors.h"
@@ -46,6 +47,7 @@
#include "installercalculator.h"
#include "uninstallercalculator.h"
#include "loggingutils.h"
+#include "componentsortfilterproxymodel.h"
#include <productkeycheck.h>
@@ -54,12 +56,17 @@
#include <QtConcurrentRun>
#include <QtCore/QMutex>
-#include <QtCore/QRegExp>
#include <QtCore/QSettings>
#include <QtCore/QTemporaryFile>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtCore5Compat/QTextCodec>
+#include <QtCore5Compat/QTextDecoder>
+#include <QtCore5Compat/QTextEncoder>
+#else
#include <QtCore/QTextCodec>
#include <QtCore/QTextDecoder>
#include <QtCore/QTextEncoder>
+#endif
#include <QtCore/QTextStream>
#include <QDesktopServices>
@@ -176,25 +183,6 @@ using namespace QInstaller;
Emitted when the new root component \a comp is added.
\sa {installer::componentAdded}{installer.componentAdded}
- \sa rootComponentsAdded(), updaterComponentsAdded()
-*/
-
-/*!
- \fn QInstaller::PackageManagerCore::rootComponentsAdded(QList<QInstaller::Component*> components)
-
- Emitted when the list of root components specified by \a components is added.
-
- \sa {installer::rootComponentsAdded}{installer.rootComponentsAdded}
- \sa componentAdded(), updaterComponentsAdded()
-*/
-
-/*!
- \fn QInstaller::PackageManagerCore::updaterComponentsAdded(QList<QInstaller::Component*> components)
-
- Emitted when a new list of updater components specified by \a components is added.
-
- \sa {installer::updaterComponentsAdded}{installer.updaterComponentsAdded}
- \sa componentAdded(), rootComponentsAdded()
*/
/*!
@@ -214,6 +202,13 @@ using namespace QInstaller;
*/
/*!
+ \fn QInstaller::PackageManagerCore::defaultTranslationsLoadedForLanguage(QLocale lang)
+
+ Emitted when the language \a lang has changed.
+
+*/
+
+/*!
\fn QInstaller::PackageManagerCore::finishButtonClicked()
\sa {installer::finishButtonClicked}{installer.finishButtonClicked}
@@ -339,6 +334,14 @@ using namespace QInstaller;
*/
/*!
+ \fn QInstaller::PackageManagerCore::downloadArchivesFinished()
+
+ Emitted when all data archives for components have been downloaded successfully.
+
+ \sa {installer::downloadArchivesFinished}{installer.downloadArchivesFinished}
+*/
+
+/*!
\fn QInstaller::PackageManagerCore::wizardPageInsertionRequested(QWidget *widget, QInstaller::PackageManagerCore::WizardPage page)
Emitted when a custom \a widget is about to be inserted into \a page by
@@ -444,6 +447,7 @@ static bool sNoForceInstallation = false;
static bool sNoDefaultInstallation = false;
static bool sVirtualComponentsVisible = false;
static bool sCreateLocalRepositoryFromBinary = false;
+static int sMaxConcurrentOperations = 0;
static bool componentMatches(const Component *component, const QString &name,
const QString &version = QString())
@@ -516,7 +520,6 @@ void PackageManagerCore::reset()
d->m_status = PackageManagerCore::Unfinished;
d->m_installerBaseBinaryUnreplaced.clear();
d->m_coreCheckedHash.clear();
- d->m_componentsToInstallCalculated = false;
}
/*!
@@ -558,50 +561,113 @@ void PackageManagerCore::cancelMetaInfoJob()
}
/*!
- \sa {installer::componentsToInstallNeedsRecalculation}{installer.componentsToInstallNeedsRecalculation}
- */
-void PackageManagerCore::componentsToInstallNeedsRecalculation()
+ Resets the cache used to store downloaded metadata, if one was previously
+ initialized. If \a init is set to \c true, the cache is reinitialized for
+ the path configured in installer's settings.
+
+ Returns \c true on success, \c false otherwise.
+*/
+bool PackageManagerCore::resetLocalCache(bool init)
{
- d->clearInstallerCalculator();
- d->clearUninstallerCalculator();
- QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation();
+ return d->m_metadataJob.resetCache(init);
+}
- d->m_componentsToInstallCalculated =
- d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall);
+/*!
+ Clears the contents of the cache used to store downloaded metadata.
+ Returns \c true on success, \c false otherwise. An error string can
+ be retrieved with \a error.
+*/
+bool PackageManagerCore::clearLocalCache(QString *error)
+{
+ if (d->m_metadataJob.clearCache())
+ return true;
- QList<Component *> componentsToInstall = d->installerCalculator()->orderedComponentsToInstall();
+ if (error)
+ *error = d->m_metadataJob.errorString();
- QList<Component *> selectedComponentsToUninstall;
- foreach (Component *component, components(ComponentType::All)) {
- if (component->uninstallationRequested() && !selectedComponentsToInstall.contains(component))
- selectedComponentsToUninstall.append(component);
- }
+ return false;
+}
- d->uninstallerCalculator()->appendComponentsToUninstall(selectedComponentsToUninstall);
+/*!
+ Returns \c true if the metadata cache is initialized and valid, \c false otherwise.
+*/
+bool PackageManagerCore::isValidCache() const
+{
+ return d->m_metadataJob.isValidCache();
+}
- QSet<Component *> componentsToUninstall = d->uninstallerCalculator()->componentsToUninstall();
+/*!
+ \internal
+ */
+template <typename T>
+bool PackageManagerCore::loadComponentScripts(const T &components, const bool postScript)
+{
+ return d->loadComponentScripts(components, postScript);
+}
- foreach (Component *component, components(ComponentType::All))
- component->setInstallAction(component->isInstalled()
- ? ComponentModelHelper::KeepInstalled
- : ComponentModelHelper::KeepUninstalled);
- foreach (Component *component, componentsToUninstall)
- component->setInstallAction(ComponentModelHelper::Uninstall);
- foreach (Component *component, componentsToInstall)
- component->setInstallAction(ComponentModelHelper::Install);
+template bool PackageManagerCore::loadComponentScripts<QList<Component *>>(const QList<Component *> &, const bool);
+template bool PackageManagerCore::loadComponentScripts<QHash<QString, Component *>>(const QHash<QString, Component *> &, const bool);
- // update all nodes uncompressed size
- foreach (Component *const component, components(ComponentType::Root))
- component->updateUncompressedSize(); // this is a recursive call
+/*!
+ Saves the installer \a args user has given when running installer. Command and option arguments
+ are not saved.
+*/
+void PackageManagerCore::saveGivenArguments(const QStringList &args)
+{
+ m_arguments = args;
}
/*!
- Forces a recalculation of components to install.
+ Returns the commands and options user has given when running installer.
+*/
+QStringList PackageManagerCore::givenArguments() const
+{
+ return m_arguments;
+}
+/*!
+ \deprecated [4.5] Use recalculateAllComponents() instead.
+
+ \sa {installer::componentsToInstallNeedsRecalculation}{installer.componentsToInstallNeedsRecalculation}
+ */
+void PackageManagerCore::componentsToInstallNeedsRecalculation()
+{
+ recalculateAllComponents();
+}
+
+/*!
+ \fn QInstaller::PackageManagerCore::clearComponentsToInstallCalculated()
+
+ \deprecated [4.5] Installer framework recalculates components each time the calculation
+ of components to install is requested, so there is no need to call this anymore, and the
+ method does nothing. On previous versions calling this forced a recalculation of
+ components to install.
+
\sa {installer::clearComponentsToInstallCalculated}{installer.clearComponentsToInstallCalculated}
*/
-void PackageManagerCore::clearComponentsToInstallCalculated()
+
+/*!
+ Recalculates all components to install and uninstall. Returns \c true
+ on success, \c false otherwise. Detailed error messages can be retrieved
+ with {installer::componentsToInstallError} and {installer::componentsToUninstallError}.
+ */
+bool PackageManagerCore::recalculateAllComponents()
{
- d->m_componentsToInstallCalculated = false;
+ // Clear previous results first, as the check states are updated
+ // at the end of both calculate methods, which refer to the results
+ // from both calculators. Needed to keep the state correct.
+ d->clearInstallerCalculator();
+ d->clearUninstallerCalculator();
+
+ if (!calculateComponentsToInstall())
+ return false;
+ if (!isInstaller() && !calculateComponentsToUninstall())
+ return false;
+
+ // update all nodes uncompressed size
+ foreach (Component *const component, components(ComponentType::Root))
+ component->updateUncompressedSize(); // this is a recursive call
+
+ return true;
}
/*!
@@ -745,12 +811,13 @@ quint64 PackageManagerCore::requiredDiskSpace() const
*/
quint64 PackageManagerCore::requiredTemporaryDiskSpace() const
{
- if (isOfflineOnly())
- return 0;
-
quint64 result = 0;
- foreach (QInstaller::Component *component, orderedComponentsToInstall())
+ foreach (QInstaller::Component *component, orderedComponentsToInstall()) {
+ if (!component->isFromOnlineRepository())
+ continue;
+
result += size(component, scCompressedSize);
+ }
return result;
}
@@ -763,16 +830,19 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
{
Q_ASSERT(partProgressSize >= 0 && partProgressSize <= 1);
- QList<QPair<QString, QString> > archivesToDownload;
+ QList<DownloadItem> archivesToDownload;
quint64 archivesToDownloadTotalSize = 0;
QList<Component*> neededComponents = orderedComponentsToInstall();
foreach (Component *component, neededComponents) {
// collect all archives to be downloaded
const QStringList toDownload = component->downloadableArchives();
+ bool checkSha1CheckSum = (component->value(scCheckSha1CheckSum).toLower() == scTrue);
foreach (const QString &versionFreeString, toDownload) {
- archivesToDownload.push_back(qMakePair(QString::fromLatin1("installer://%1/%2")
- .arg(component->name(), versionFreeString), QString::fromLatin1("%1/%2/%3")
- .arg(component->repositoryUrl().toString(), component->name(), versionFreeString)));
+ DownloadItem item;
+ item.checkSha1CheckSum = checkSha1CheckSum;
+ item.fileName = scInstallerPrefixWithTwoArgs.arg(component->name(), versionFreeString);
+ item.sourceUrl = scThreeArgs.arg(component->repositoryUrl().toString(), component->name(), versionFreeString);
+ archivesToDownload.push_back(item);
}
archivesToDownloadTotalSize += component->value(scCompressedSize).toULongLong();
}
@@ -780,9 +850,10 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
if (archivesToDownload.isEmpty())
return 0;
- ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("\nDownloading packages..."));
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Downloading packages..."));
- DownloadArchivesJob archivesJob(this);
+ DownloadArchivesJob archivesJob(this, QLatin1String("downloadArchiveJob"));
archivesJob.setAutoDelete(false);
archivesJob.setArchivesToDownload(archivesToDownload);
archivesJob.setExpectedTotalSize(archivesToDownloadTotalSize);
@@ -790,7 +861,12 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
connect(&archivesJob, &DownloadArchivesJob::outputTextChanged,
ProgressCoordinator::instance(), &ProgressCoordinator::emitLabelAndDetailTextChanged);
connect(&archivesJob, &DownloadArchivesJob::downloadStatusChanged,
- ProgressCoordinator::instance(), &ProgressCoordinator::downloadStatusChanged);
+ ProgressCoordinator::instance(), &ProgressCoordinator::additionalProgressStatusChanged);
+
+ connect(&archivesJob, &DownloadArchivesJob::fileDownloadReady,
+ d, &PackageManagerCorePrivate::addPathForDeletion);
+ connect(&archivesJob, &DownloadArchivesJob::hashDownloadReady,
+ d, &PackageManagerCorePrivate::addPathForDeletion);
ProgressCoordinator::instance()->registerPartProgress(&archivesJob,
SIGNAL(progressChanged(double)), partProgressSize);
@@ -806,7 +882,8 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
if (d->statusCanceledOrFailed())
throw Error(tr("Installation canceled by user."));
- ProgressCoordinator::instance()->emitDownloadStatus(tr("All downloads finished."));
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(tr("All downloads finished."));
+ emit downloadArchivesFinished();
return archivesJob.numberOfDownloads();
}
@@ -929,7 +1006,7 @@ void PackageManagerCore::rollBackInstallation()
*/
bool PackageManagerCore::isFileExtensionRegistered(const QString &extension) const
{
- QSettingsWrapper settings(QLatin1String("HKEY_CLASSES_ROOT"), QSettingsWrapper::NativeFormat);
+ QSettingsWrapper settings(QLatin1String("HKEY_CLASSES_ROOT"), QSettings::NativeFormat);
return settings.value(QString::fromLatin1(".%1/Default").arg(extension)).isValid();
}
@@ -944,7 +1021,7 @@ bool PackageManagerCore::isFileExtensionRegistered(const QString &extension) con
*/
bool PackageManagerCore::fileExists(const QString &filePath) const
{
- return QFileInfo(filePath).exists();
+ return QFileInfo::exists(filePath);
}
/*!
@@ -969,8 +1046,7 @@ QString PackageManagerCore::readFile(const QString &filePath, const QString &cod
return QString();
QTextStream stream(&f);
- stream.setCodec(codec);
- return stream.readAll();
+ return QString::fromUtf8(codec->fromUnicode(stream.readAll()));
}
/*!
@@ -1008,8 +1084,13 @@ QString PackageManagerCore::readConsoleLine(const QString &title, qint64 maxlen)
On Unix platforms the returned string is the same as the argument.
+ \note Predefined variables, such as @TargetDir@, are not resolved by
+ this function. To convert the separators to predefined variables, use
+ \c installer.value() to resolve the variables first.
+
\sa {installer::toNativeSeparators}{installer.toNativeSeparators}
\sa fromNativeSeparators()
+ \sa {installer::value}{installer.value}
*/
QString PackageManagerCore::toNativeSeparators(const QString &path)
{
@@ -1021,8 +1102,13 @@ QString PackageManagerCore::toNativeSeparators(const QString &path)
On Unix platforms the returned string is the same as the argument.
+ \note Predefined variables, such as @TargetDir@, are not resolved by
+ this function. To convert the separators to predefined variables, use
+ \c installer.value() to resolve the variables first.
+
\sa {installer::fromNativeSeparators}{installer.fromNativeSeparators}
\sa toNativeSeparators()
+ \sa {installer::value}{installer.value}
*/
QString PackageManagerCore::fromNativeSeparators(const QString &path)
{
@@ -1030,8 +1116,9 @@ QString PackageManagerCore::fromNativeSeparators(const QString &path)
}
/*!
- Checks whether the target directory \a targetDirectory exists and has contents:
+ Checks whether installation is allowed to \a targetDirectory:
\list
+ \li Returns \c true if the directory does not exist.
\li Returns \c true if the directory exists and is empty.
\li Returns \c false if the directory already exists and contains an installation.
\li Returns \c false if the target is a file or a symbolic link.
@@ -1039,14 +1126,17 @@ QString PackageManagerCore::fromNativeSeparators(const QString &path)
choice that the end users make in the displayed message box.
\endlist
*/
-bool PackageManagerCore::checkTargetDir(const QString &targetDirectory)
+bool PackageManagerCore::installationAllowedToDirectory(const QString &targetDirectory)
{
+ const QFileInfo fi(targetDirectory);
+ if (!fi.exists())
+ return true;
+
const QDir dir(targetDirectory);
// the directory exists and is empty...
if (dir.exists() && dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty())
return true;
- const QFileInfo fi(targetDirectory);
if (fi.isDir()) {
QString fileName = settings().maintenanceToolName();
#if defined(Q_OS_MACOS)
@@ -1197,11 +1287,16 @@ PackageManagerCore::PackageManagerCore()
Creates and initializes a remote client. Requests administrator's rights for
QFile, QSettings, and QProcess operations. Calls \c init() with \a socketName, \a key,
and \a mode to set the server side authorization key.
+
+ The \a datFileName contains the corresponding .dat file name for the running
+ \c maintenance tool binary. \a datFileName can be empty if \c maintenance tool
+ fails to find it or if \c installer is run instead of \c maintenance tool.
*/
PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationBlob> &operations,
+ const QString &datFileName,
const QString &socketName, const QString &key, Protocol::Mode mode,
const QHash<QString, QString> &params, const bool commandLineInstance)
- : d(new PackageManagerCorePrivate(this, magicmaker, operations))
+ : d(new PackageManagerCorePrivate(this, magicmaker, operations, datFileName))
{
setCommandLineInstance(commandLineInstance);
Repository::registerMetaType(); // register, cause we stream the type as QVariant
@@ -1221,7 +1316,8 @@ PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationB
// Sanity check to detect a broken installations with missing operations.
// Every installed package should have at least one MinimalProgress operation.
//
- QSet<QString> installedPackages = d->m_core->localInstalledPackages().keys().toSet();
+ const QStringList localPackageList = d->m_core->localInstalledPackages().keys();
+ QSet<QString> installedPackages(localPackageList.begin(), localPackageList.end());
QSet<QString> operationPackages;
foreach (QInstaller::Operation *operation, d->m_performedOperationsOld) {
if (operation->hasValue(QLatin1String("component")))
@@ -1231,8 +1327,8 @@ PackageManagerCore::PackageManagerCore(qint64 magicmaker, const QList<OperationB
QSet<QString> packagesWithoutOperation = installedPackages - operationPackages;
QSet<QString> orphanedOperations = operationPackages - installedPackages;
if (!packagesWithoutOperation.isEmpty() || !orphanedOperations.isEmpty()) {
- qCritical() << "Operations missing for installed packages" << packagesWithoutOperation.toList();
- qCritical() << "Orphaned operations" << orphanedOperations.toList();
+ qCritical() << "Operations missing for installed packages" << packagesWithoutOperation.values();
+ qCritical() << "Orphaned operations" << orphanedOperations.values();
qCritical() << "Your installation seems to be corrupted. Please consider re-installing from scratch, "
"remove the packages from components.xml which operations are missing, "
"or reinstall the packages.";
@@ -1380,6 +1476,30 @@ void PackageManagerCore::setCreateLocalRepositoryFromBinary(bool create)
sCreateLocalRepositoryFromBinary = create;
}
+/* static */
+/*!
+ Returns the maximum count of operations that should be run concurrently
+ at the given time.
+
+ Currently this affects only operations in the unpacking phase.
+*/
+int PackageManagerCore::maxConcurrentOperations()
+{
+ return sMaxConcurrentOperations;
+}
+
+/* static */
+/*!
+ Sets the maximum \a count of operations that should be run concurrently
+ at the given time. A value of \c 0 is synonym for automatic count.
+
+ Currently this affects only operations in the unpacking phase.
+*/
+void PackageManagerCore::setMaxConcurrentOperations(int count)
+{
+ sMaxConcurrentOperations = count;
+}
+
/*!
Returns \c true if the package manager is running and installed packages are
found. Otherwise, returns \c false.
@@ -1393,7 +1513,7 @@ bool PackageManagerCore::fetchLocalPackagesTree()
return false;
}
- LocalPackagesHash installedPackages = d->localInstalledPackages();
+ LocalPackagesMap installedPackages = d->localInstalledPackages();
if (installedPackages.isEmpty()) {
if (status() != Failure)
d->setStatus(Failure, tr("No installed packages found."));
@@ -1404,23 +1524,64 @@ bool PackageManagerCore::fetchLocalPackagesTree()
d->clearAllComponentLists();
QHash<QString, QInstaller::Component*> components;
+ QMap<QString, QString> treeNameComponents;
- const QStringList &keys = installedPackages.keys();
- foreach (const QString &key, keys) {
- QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
- component->loadDataFromPackage(installedPackages.value(key));
- const QString &name = component->treeName();
- if (components.contains(name)) {
- d->setStatus(Failure, tr("Cannot register component! Component with identifier %1 "
- "already exists.").arg(name));
- return false;
+ std::function<void(QList<LocalPackage> *, bool)> loadLocalPackages;
+ loadLocalPackages = [&](QList<LocalPackage> *treeNamePackages, bool firstRun) {
+ foreach (auto &package, (firstRun ? installedPackages.values() : *treeNamePackages)) {
+ if (firstRun && !package.treeName.first.isEmpty()) {
+ // Package has a tree name, leave for later
+ treeNamePackages->append(package);
+ continue;
+ }
+
+ std::unique_ptr<QInstaller::Component> component(new QInstaller::Component(this));
+ component->loadDataFromPackage(package);
+ QString name = component->treeName();
+ if (components.contains(name)) {
+ qCritical() << "Cannot register component" << component->name() << "with name" << name
+ << "! Component with identifier" << name << "already exists.";
+ // Conflicting original name, skip.
+ if (component->value(scTreeName).isEmpty())
+ continue;
+
+ // Conflicting tree name, check if we can add with original name.
+ name = component->name();
+ if (!settings().allowUnstableComponents() || components.contains(name))
+ continue;
+
+ qCDebug(lcInstallerInstallLog)
+ << "Registering component with the original indetifier:" << name;
+ component->removeValue(scTreeName);
+ const QString errorString = QLatin1String("Tree name conflicts with an existing indentifier");
+ d->m_pendingUnstableComponents.insert(component->name(),
+ QPair<Component::UnstableError, QString>(Component::InvalidTreeName, errorString));
+ }
+ const QString treeName = component->value(scTreeName);
+ if (!treeName.isEmpty())
+ treeNameComponents.insert(component->name(), treeName);
+
+ components.insert(name, component.release());
}
- components.insert(name, component.take());
+ // Second pass with leftover packages
+ if (firstRun)
+ loadLocalPackages(treeNamePackages, false);
+ };
+
+ {
+ // Loading package data is performed in two steps: first, components without
+ // - and then components with tree names. This is to ensure components with tree
+ // names do not replace other components when registering fails to a name conflict.
+ QList<LocalPackage> treeNamePackagesTmp;
+ loadLocalPackages(&treeNamePackagesTmp, true);
}
+ createAutoTreeNames(components, treeNameComponents);
+
if (!d->buildComponentTree(components, false))
return false;
+ d->commitPendingUnstableComponents();
updateDisplayVersions(scDisplayVersion);
emit finishAllComponentsReset(d->m_rootComponents);
@@ -1432,7 +1593,7 @@ bool PackageManagerCore::fetchLocalPackagesTree()
/*!
Returns a list of local installed packages. The list can be empty.
*/
-LocalPackagesHash PackageManagerCore::localInstalledPackages()
+LocalPackagesMap PackageManagerCore::localInstalledPackages()
{
return d->localInstalledPackages();
}
@@ -1445,10 +1606,11 @@ void PackageManagerCore::networkSettingsChanged()
cancelMetaInfoJob();
d->m_updates = false;
+ d->m_aliases = false;
d->m_repoFetched = false;
d->m_updateSourcesAdded = false;
- if (isMaintainer() ) {
+ if (!isInstaller()) {
bool gainedAdminRights = false;
if (!directoryWritable(d->targetDir())) {
gainAdminRights();
@@ -1503,14 +1665,14 @@ PackagesList PackageManagerCore::remotePackages()
*/
bool PackageManagerCore::fetchCompressedPackagesTree()
{
- const LocalPackagesHash installedPackages = d->localInstalledPackages();
+ const LocalPackagesMap installedPackages = d->localInstalledPackages();
if (!isInstaller() && status() == Failure)
return false;
if (!d->fetchMetaInformationFromRepositories(DownloadType::CompressedPackage))
return false;
- if (!d->addUpdateResourcesFromRepositories(true, true)) {
+ if (!d->addUpdateResourcesFromRepositories(true)) {
return false;
}
@@ -1521,11 +1683,42 @@ bool PackageManagerCore::fetchCompressedPackagesTree()
return fetchPackagesTree(packages, installedPackages);
}
+bool PackageManagerCore::fetchPackagesWithFallbackRepositories(const QStringList& components, bool &fallBackReposFetched)
+{
+ auto checkComponents = [&]() {
+ if (!fetchRemotePackagesTree(components))
+ return false;
+ return true;
+ };
+
+ if (!checkComponents()) {
+ // error when fetching packages tree
+ if (status() != NoPackagesFound)
+ return false;
+ //retry fetching packages with all categories enabled
+ fallBackReposFetched = true;
+ if (!d->enableAllCategories())
+ return false;
+
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote()
+ << "Components not found with the current selection."
+ << "Searching from additional repositories";
+ if (!ProductKeyCheck::instance()->securityWarning().isEmpty()) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << ProductKeyCheck::instance()->securityWarning();
+ }
+ if (!checkComponents()) {
+ return false;
+ }
+ }
+ return true;
+}
+
/*!
Checks for packages to install. Returns \c true if newer versions exist
- and they can be installed.
+ and they can be installed. Returns \c false if not \a components are found
+ for install, or if error occurred when fetching and generating package tree.
*/
-bool PackageManagerCore::fetchRemotePackagesTree()
+bool PackageManagerCore::fetchRemotePackagesTree(const QStringList& components)
{
d->setStatus(Running);
@@ -1539,7 +1732,7 @@ bool PackageManagerCore::fetchRemotePackagesTree()
return false;
}
- const LocalPackagesHash installedPackages = d->localInstalledPackages();
+ const LocalPackagesMap installedPackages = d->localInstalledPackages();
if (!isInstaller() && status() == Failure)
return false;
@@ -1549,17 +1742,22 @@ bool PackageManagerCore::fetchRemotePackagesTree()
if (!d->fetchMetaInformationFromRepositories(DownloadType::CompressedPackage))
return false;
- if (!d->addUpdateResourcesFromRepositories(true))
+ if (!d->addUpdateResourcesFromRepositories())
return false;
const PackagesList &packages = d->remotePackages();
- if (packages.isEmpty())
+ if (packages.isEmpty()) {
+ d->setStatus(PackageManagerCore::NoPackagesFound);
+ return false;
+ }
+
+ if (!d->installablePackagesFound(components))
return false;
return fetchPackagesTree(packages, installedPackages);
}
-bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages) {
+bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const LocalPackagesMap installedPackages) {
bool success = false;
if (!isUpdater()) {
@@ -1804,24 +2002,82 @@ void PackageManagerCore::setTemporaryRepositories(const QStringList &repositorie
settings().setTemporaryRepositories(repositorySet, replace);
}
-/*!
- Checks whether the downloader should try to download SHA-1 checksums for
- archives and returns the checksums.
-*/
-bool PackageManagerCore::testChecksum() const
+bool PackageManagerCore::addQBspRepositories(const QStringList &repositories)
{
- return d->m_testChecksum;
+ QSet<Repository> set;
+ foreach (QString fileName, repositories) {
+ Repository repository = Repository::fromUserInput(fileName, true);
+ repository.setEnabled(true);
+ set.insert(repository);
+ }
+ if (set.count() > 0) {
+ settings().addTemporaryRepositories(set, false);
+ return true;
+ }
+ return false;
}
-/*!
- The \a test argument determines whether the downloader should try to
- download SHA-1 checksums for archives.
-*/
-void PackageManagerCore::setTestChecksum(bool test)
+bool PackageManagerCore::validRepositoriesAvailable() const
+{
+ foreach (const Repository &repo, settings().repositories()) {
+ if (repo.isEnabled() && repo.isValid()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void PackageManagerCore::setAllowCompressedRepositoryInstall(bool allow)
+{
+ d->m_allowCompressedRepositoryInstall = allow;
+}
+
+bool PackageManagerCore::allowCompressedRepositoryInstall() const
+{
+ return d->m_allowCompressedRepositoryInstall;
+}
+
+bool PackageManagerCore::showRepositoryCategories() const
{
- d->m_testChecksum = test;
+ bool showCagetories = settings().repositoryCategories().count() > 0 && !isOfflineOnly() && !isUpdater();
+ if (showCagetories)
+ settings().setAllowUnstableComponents(true);
+ return showCagetories;
}
+QVariantMap PackageManagerCore::organizedRepositoryCategories() const
+{
+ QVariantMap map;
+ QSet<RepositoryCategory> categories = settings().repositoryCategories();
+ foreach (const RepositoryCategory &category, categories)
+ map.insert(category.displayname(), QVariant::fromValue(category));
+ return map;
+}
+
+void PackageManagerCore::enableRepositoryCategory(const QString &repositoryName, bool enable)
+{
+ QMap<QString, RepositoryCategory> organizedRepositoryCategories = settings().organizedRepositoryCategories();
+
+ QMap<QString, RepositoryCategory>::iterator i = organizedRepositoryCategories.find(repositoryName);
+ while (i != organizedRepositoryCategories.end() && i.key() == repositoryName) {
+ d->enableRepositoryCategory(i.value(), enable);
+ i++;
+ }
+}
+
+void PackageManagerCore::runProgram()
+{
+ const QString program = replaceVariables(value(scRunProgram));
+
+ const QStringList args = replaceVariables(values(scRunProgramArguments));
+ if (program.isEmpty())
+ return;
+
+ qCDebug(QInstaller::lcInstallerInstallLog) << "starting" << program << args;
+ QProcess::startDetached(program, args);
+}
+
+
/*!
Returns the script engine that prepares and runs the component scripts.
@@ -1850,6 +2106,10 @@ ScriptEngine *PackageManagerCore::controlScriptEngine() const
*/
void PackageManagerCore::appendRootComponent(Component *component)
{
+ // For normal installer runs components aren't appended after model reset
+ if (Q_UNLIKELY(!d->m_componentByNameHash.isEmpty()))
+ d->m_componentByNameHash.clear();
+
d->m_rootComponents.append(component);
emit componentAdded(component);
}
@@ -1915,7 +2175,7 @@ QList<Component *> PackageManagerCore::components(ComponentTypes mask, const QSt
QRegularExpression re(regexp);
QList<Component*>::iterator iter = components.begin();
while (iter != components.end()) {
- if (!re.match(iter.i->t()->name()).hasMatch())
+ if (!re.match((*iter)->name()).hasMatch())
iter = components.erase(iter);
else
iter++;
@@ -1931,6 +2191,10 @@ QList<Component *> PackageManagerCore::components(ComponentTypes mask, const QSt
*/
void PackageManagerCore::appendUpdaterComponent(Component *component)
{
+ // For normal installer runs components aren't appended after model reset
+ if (Q_UNLIKELY(!d->m_componentByNameHash.isEmpty()))
+ d->m_componentByNameHash.clear();
+
component->setUpdateAvailable(true);
d->m_updaterComponents.append(component);
emit componentAdded(component);
@@ -1944,7 +2208,39 @@ void PackageManagerCore::appendUpdaterComponent(Component *component)
*/
Component *PackageManagerCore::componentByName(const QString &name) const
{
- return componentByName(name, components(ComponentType::AllNoReplacements));
+ if (name.isEmpty())
+ return nullptr;
+
+ if (d->m_componentByNameHash.isEmpty()) {
+ // We can avoid the linear lookups from the component list by creating
+ // a <name,component> hash once, and reusing it on subsequent calls.
+ const QList<Component *> componentsList = components(ComponentType::AllNoReplacements);
+ for (Component *component : componentsList)
+ d->m_componentByNameHash.insert(component->name(), component);
+ }
+
+ QString fixedVersion;
+ QString fixedName;
+
+ parseNameAndVersion(name, &fixedName, &fixedVersion);
+
+ Component *component = d->m_componentByNameHash.value(fixedName);
+ if (!component)
+ return nullptr;
+
+ if (componentMatches(component, fixedName, fixedVersion))
+ return component;
+
+ return nullptr;
+}
+
+/*!
+ Searches for a component alias matching \a name and returns it.
+ If no alias matches the name, \c nullptr is returned.
+*/
+ComponentAlias *PackageManagerCore::aliasByName(const QString &name) const
+{
+ return d->m_componentAliases.value(name);
}
/*!
@@ -1973,6 +2269,18 @@ Component *PackageManagerCore::componentByName(const QString &name, const QList<
}
/*!
+ Returns an array of all components currently available. If the repository
+ metadata have not been fetched yet, the array will be empty. Optionally, a
+ \a regexp expression can be used to further filter the listed packages.
+
+ \sa {installer::components}{installer.components}
+ */
+QList<Component *> PackageManagerCore::components(const QString &regexp) const
+{
+ return components(PackageManagerCore::ComponentType::All, regexp);
+}
+
+/*!
Returns \c true if directory specified by \a path is writable by
the current user.
*/
@@ -2010,8 +2318,27 @@ QList<Component *> PackageManagerCore::componentsMarkedForInstallation() const
}
/*!
- Determines which components to install based on the current run mode and returns an
- ordered list of components to install. Also auto installed dependencies are resolved.
+ Returns a list of component aliases that are marked for installation.
+ The list can be empty.
+*/
+QList<ComponentAlias *> PackageManagerCore::aliasesMarkedForInstallation() const
+{
+ if (isUpdater()) // Aliases not supported on update at the moment
+ return QList<ComponentAlias *>();
+
+ QList<ComponentAlias *> markedForInstallation;
+ for (auto *alias : qAsConst(d->m_componentAliases)) {
+ if (alias && alias->isSelected())
+ markedForInstallation.append(alias);
+ }
+
+ return markedForInstallation;
+}
+
+/*!
+ Determines which components to install based on the current run mode, including component aliases,
+ dependencies and automatic dependencies. Returns \c true on success, \c false otherwise.
+
The aboutCalculateComponentsToInstall() signal is emitted
before the calculation starts, the finishedCalculateComponentsToInstall()
signal once all calculations are done.
@@ -2022,16 +2349,15 @@ QList<Component *> PackageManagerCore::componentsMarkedForInstallation() const
bool PackageManagerCore::calculateComponentsToInstall() const
{
emit aboutCalculateComponentsToInstall();
- if (!d->m_componentsToInstallCalculated) {
- d->clearInstallerCalculator();
- QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation();
- d->storeCheckState();
- d->m_componentsToInstallCalculated =
- d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall);
- }
+ d->clearInstallerCalculator();
+
+ const bool calculated = d->installerCalculator()->solve();
+
+ d->updateComponentInstallActions();
+
emit finishedCalculateComponentsToInstall();
- return d->m_componentsToInstallCalculated;
+ return calculated;
}
/*!
@@ -2039,45 +2365,56 @@ bool PackageManagerCore::calculateComponentsToInstall() const
*/
QList<Component*> PackageManagerCore::orderedComponentsToInstall() const
{
- return d->installerCalculator()->orderedComponentsToInstall();
+ return d->installerCalculator()->resolvedComponents();
}
/*!
- Calculates components to install and uninstall. In case of an error, returns \c false
- and and sets the \a displayString for error detail.
+ Returns a HTML-formatted description of the reasons each component is about
+ to be installed or uninstalled, or a description of the error occurred while
+ calculating components to install and uninstall.
*/
-
-bool PackageManagerCore::calculateComponents(QString *displayString)
+QString PackageManagerCore::componentResolveReasons() const
{
QString htmlOutput;
- QString lastInstallReason;
- if (!calculateComponentsToUninstall() ||
- !calculateComponentsToInstall()) {
+ if (!componentsToInstallError().isEmpty()) {
htmlOutput.append(QString::fromLatin1("<h2><font color=\"red\">%1</font></h2><ul>")
- .arg(tr("Cannot resolve all dependencies.")));
+ .arg(tr("Cannot resolve all dependencies.")));
//if we have a missing dependency or a recursion we can display it
- if (!componentsToInstallError().isEmpty()) {
- htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(
- componentsToInstallError()));
- }
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(
+ componentsToInstallError()));
htmlOutput.append(QLatin1String("</ul>"));
- if (displayString)
- *displayString = htmlOutput;
- return false;
+ return htmlOutput;
}
- // In case of updater mode we don't uninstall components.
- if (!isUpdater()) {
- QList<Component*> componentsToRemove = componentsToUninstall();
- if (!componentsToRemove.isEmpty()) {
- htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(tr("Components about to "
- "be removed.")));
- foreach (Component *component, componentsToRemove)
- htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
+ if (!componentsToUninstallError().isEmpty()) {
+ htmlOutput.append(QString::fromLatin1("<h2><font color=\"red\">%1</font></h2><ul>")
+ .arg(tr("Cannot resolve components to uninstall.")));
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(
+ componentsToUninstallError()));
+ htmlOutput.append(QLatin1String("</ul>"));
+ return htmlOutput;
+ }
+
+ QList<Component*> componentsToRemove = componentsToUninstall();
+ if (!componentsToRemove.isEmpty()) {
+ QMap<QString, QStringList> orderedUninstallReasons;
+ htmlOutput.append(QString::fromLatin1("<h3>%1</h3><ul>").arg(tr("Components about to "
+ "be removed:")));
+ foreach (Component *component, componentsToRemove) {
+ const QString reason = uninstallReason(component);
+ QStringList value = orderedUninstallReasons.value(reason);
+ orderedUninstallReasons.insert(reason, value << component->name());
+ }
+ for (auto &reason : orderedUninstallReasons.keys()) {
+ htmlOutput.append(QString::fromLatin1("<h4>%1</h4><ul>").arg(reason));
+ foreach (const QString componentName, orderedUninstallReasons.value(reason))
+ htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(componentName));
htmlOutput.append(QLatin1String("</ul>"));
}
+ htmlOutput.append(QLatin1String("</ul>"));
}
+ QString lastInstallReason;
foreach (Component *component, orderedComponentsToInstall()) {
const QString reason = installReason(component);
if (lastInstallReason != reason) {
@@ -2088,38 +2425,46 @@ bool PackageManagerCore::calculateComponents(QString *displayString)
}
htmlOutput.append(QString::fromLatin1("<li> %1 </li>").arg(component->name()));
}
- if (displayString)
- *displayString = htmlOutput;
- return true;
+ return htmlOutput;
}
/*!
- Calculates a list of components to uninstall based on the current run mode.
+ Calculates a list of components to uninstall.
+
The aboutCalculateComponentsToUninstall() signal is emitted
before the calculation starts, the finishedCalculateComponentsToUninstall() signal once all
- calculations are done. Always returns \c true.
+ calculations are done. Returns \c true on success, \c false otherwise.
\sa {installer::calculateComponentsToUninstall}{installer.calculateComponentsToUninstall}
*/
bool PackageManagerCore::calculateComponentsToUninstall() const
{
emit aboutCalculateComponentsToUninstall();
- if (!isUpdater()) {
- // hack to avoid removing needed dependencies
- QSet<Component*> componentsToInstall = d->installerCalculator()->orderedComponentsToInstall().toSet();
- QList<Component*> componentsToUninstall;
- foreach (Component *component, components(ComponentType::All)) {
- if (component->uninstallationRequested() && !componentsToInstall.contains(component))
- componentsToUninstall.append(component);
- }
+ d->clearUninstallerCalculator();
+ const QList<Component *> componentsToInstallList = d->installerCalculator()->resolvedComponents();
- d->clearUninstallerCalculator();
- d->storeCheckState();
- d->uninstallerCalculator()->appendComponentsToUninstall(componentsToUninstall);
+ QList<Component *> selectedComponentsToUninstall;
+ foreach (Component* component, components(PackageManagerCore::ComponentType::Replacements)) {
+ // Uninstall the component if replacement is selected for install or update
+ QPair<Component*, Component*> comp = d->componentsToReplace().value(component->name());
+ if (comp.first && d->m_installerCalculator->resolvedComponents().contains(comp.first)) {
+ d->uninstallerCalculator()->insertResolution(component,
+ CalculatorBase::Resolution::Replaced, comp.first->name());
+ selectedComponentsToUninstall.append(comp.second);
+ }
+ }
+ foreach (Component *component, components(PackageManagerCore::ComponentType::AllNoReplacements)) {
+ if (component->uninstallationRequested() && !componentsToInstallList.contains(component))
+ selectedComponentsToUninstall.append(component);
}
+ const bool componentsToUninstallCalculated =
+ d->uninstallerCalculator()->solve(selectedComponentsToUninstall);
+
+ d->updateComponentInstallActions();
+
emit finishedCalculateComponentsToUninstall();
- return true;
+ return componentsToUninstallCalculated;
}
/*!
@@ -2131,7 +2476,7 @@ bool PackageManagerCore::calculateComponentsToUninstall() const
*/
QList<Component *> PackageManagerCore::componentsToUninstall() const
{
- return d->uninstallerCalculator()->componentsToUninstall().toList();
+ return d->uninstallerCalculator()->resolvedComponents();
}
/*!
@@ -2139,7 +2484,15 @@ QList<Component *> PackageManagerCore::componentsToUninstall() const
*/
QString PackageManagerCore::componentsToInstallError() const
{
- return d->installerCalculator()->componentsToInstallError();
+ return d->installerCalculator()->error();
+}
+
+/*!
+ Returns errors found in the components that are marked for uninstallation.
+*/
+QString PackageManagerCore::componentsToUninstallError() const
+{
+ return d->uninstallerCalculator()->error();
}
/*!
@@ -2153,7 +2506,23 @@ QString PackageManagerCore::componentsToInstallError() const
*/
QString PackageManagerCore::installReason(Component *component) const
{
- return d->installerCalculator()->installReason(component);
+ return d->installerCalculator()->resolutionText(component);
+}
+
+/*!
+ Returns the reason why \a component needs to be uninstalled:
+
+ \list
+ \li The component was scheduled for uninstallation.
+ \li The component was replaced by another component.
+ \li The component is virtual and its dependencies are uninstalled.
+ \li The components dependencies are uninstalled.
+ \li The components autodependencies are uninstalled.
+ \endlist
+*/
+QString PackageManagerCore::uninstallReason(Component *component) const
+{
+ return d->uninstallerCalculator()->resolutionText(component);
}
/*!
@@ -2186,6 +2555,68 @@ QList<Component*> PackageManagerCore::dependees(const Component *_component) con
}
/*!
+ Returns true if components which are about to be installed or updated
+ are dependent on \a component.
+*/
+bool PackageManagerCore::isDependencyForRequestedComponent(const Component *component) const
+{
+ if (!component)
+ return false;
+
+ const QList<QInstaller::Component *> availableComponents = components(ComponentType::All);
+ if (availableComponents.isEmpty())
+ return false;
+
+ QString name;
+ QString version;
+ for (Component *availableComponent : availableComponents) {
+ if (!availableComponent) {
+ continue;
+ }
+ // 1. In updater mode, component to be updated might have new dependencies
+ // Check if the dependency is still needed
+ // 2. If component is selected and not installed, check if the dependency is needed
+ if (availableComponent->isSelected()
+ && ((isUpdater() && availableComponent->isInstalled())
+ || (isPackageManager() && !availableComponent->isInstalled()))) {
+ const QStringList &dependencies = availableComponent->dependencies();
+ foreach (const QString &dependency, dependencies) {
+ parseNameAndVersion(dependency, &name, &version);
+ if (componentMatches(component, name, version)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+/*!
+ Returns a list of local components which are dependent on \a component.
+*/
+QStringList PackageManagerCore::localDependenciesToComponent(const Component *component) const
+{
+ if (!component)
+ return QStringList();
+
+ QStringList dependents;
+ QString name;
+ QString version;
+
+ QMap<QString, LocalPackage> localPackages = d->m_localPackageHub->localPackages();
+ for (const KDUpdater::LocalPackage &localPackage : qAsConst(localPackages)) {
+ for (const QString &dependency : localPackage.dependencies) {
+ parseNameAndVersion(dependency, &name, &version);
+ if (componentMatches(component, name, version)) {
+ dependents.append(localPackage.name);
+ }
+ }
+ }
+ return dependents;
+}
+
+/*!
Returns the default component model.
*/
ComponentModel *PackageManagerCore::defaultComponentModel() const
@@ -2194,9 +2625,13 @@ ComponentModel *PackageManagerCore::defaultComponentModel() const
if (!d->m_defaultModel) {
d->m_defaultModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("AllComponentsModel"));
+
+ connect(this, &PackageManagerCore::startAllComponentsReset, [&] {
+ d->m_defaultModel->reset();
+ });
+ connect(this, &PackageManagerCore::finishAllComponentsReset, d->m_defaultModel,
+ &ComponentModel::reset);
}
- connect(this, &PackageManagerCore::finishAllComponentsReset, d->m_defaultModel,
- &ComponentModel::setRootComponents);
return d->m_defaultModel;
}
@@ -2209,40 +2644,70 @@ ComponentModel *PackageManagerCore::updaterComponentModel() const
if (!d->m_updaterModel) {
d->m_updaterModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("UpdaterComponentsModel"));
+
+ connect(this, &PackageManagerCore::startUpdaterComponentsReset, [&] {
+ d->m_updaterModel->reset();
+ });
+ connect(this, &PackageManagerCore::finishUpdaterComponentsReset, d->m_updaterModel,
+ &ComponentModel::reset);
}
- connect(this, &PackageManagerCore::finishUpdaterComponentsReset, d->m_updaterModel,
- &ComponentModel::setRootComponents);
return d->m_updaterModel;
}
/*!
+ Returns the proxy model
+*/
+
+ComponentSortFilterProxyModel *PackageManagerCore::componentSortFilterProxyModel()
+{
+ if (!d->m_componentSortFilterProxyModel) {
+ d->m_componentSortFilterProxyModel = new ComponentSortFilterProxyModel(this);
+ d->m_componentSortFilterProxyModel->setRecursiveFilteringEnabled(true);
+ d->m_componentSortFilterProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ }
+ return d->m_componentSortFilterProxyModel;
+}
+
+/*!
Lists available packages filtered with \a regexp without GUI. Virtual
components are not listed unless set visible. Optionally, a \a filters
hash containing package information elements and regular expressions
can be used to further filter listed packages.
+ Returns \c true if matching packages were found, \c false otherwise.
+
\sa setVirtualComponentsVisible()
*/
-void PackageManagerCore::listAvailablePackages(const QString &regexp, const QHash<QString, QString> &filters)
+bool PackageManagerCore::listAvailablePackages(const QString &regexp, const QHash<QString, QString> &filters)
{
setPackageViewer();
+ d->enableAllCategories();
qCDebug(QInstaller::lcInstallerInstallLog)
<< "Searching packages with regular expression:" << regexp;
ComponentModel *model = defaultComponentModel();
- d->fetchMetaInformationFromRepositories(DownloadType::UpdatesXML);
+ PackagesList packages;
- d->addUpdateResourcesFromRepositories(true);
- QRegularExpression re(regexp);
- const PackagesList &packages = d->remotePackages();
- if (!fetchAllPackages(packages, LocalPackagesHash())) {
- qCWarning(QInstaller::lcInstallerInstallLog)
- << "There was a problem with loading the package data.";
- return;
+ if (!d->m_updates) {
+ d->fetchMetaInformationFromRepositories();
+ d->addUpdateResourcesFromRepositories();
+
+ packages = d->remotePackages();
+ if (!fetchAllPackages(packages, LocalPackagesMap())) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "There was a problem with loading the package data.";
+ return false;
+ }
+ } else {
+ // No need to fetch metadata again
+ packages = d->remotePackages();
}
+ QRegularExpression re(regexp);
+ re.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+
PackagesList matchedPackages;
- foreach (Package *package, packages) {
+ foreach (Package *package, qAsConst(packages)) {
const QString name = package->data(scName).toString();
Component *component = componentByName(name);
if (!component)
@@ -2254,6 +2719,7 @@ void PackageManagerCore::listAvailablePackages(const QString &regexp, const QHas
for (auto &key : filters.keys()) {
const QString elementValue = component->value(key);
QRegularExpression elementRegexp(filters.value(key));
+ elementRegexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
if (elementValue.isEmpty() || !elementRegexp.match(elementValue).hasMatch()) {
ignoreComponent = true;
break;
@@ -2263,10 +2729,68 @@ void PackageManagerCore::listAvailablePackages(const QString &regexp, const QHas
matchedPackages.append(package);
}
}
- if (matchedPackages.count() == 0)
+ if (matchedPackages.count() == 0) {
qCDebug(QInstaller::lcInstallerInstallLog) << "No matching packages found.";
- else
- LoggingHandler::instance().printPackageInformation(matchedPackages, localInstalledPackages());
+ return false;
+ }
+
+ LoggingHandler::instance().printPackageInformation(matchedPackages, localInstalledPackages());
+ return true;
+}
+
+/*!
+ Lists available component aliases filtered with \a regexp without GUI. Virtual
+ aliases are not listed unless set visible.
+
+ Returns \c true if matching package aliases were found, \c false otherwise.
+
+ \sa setVirtualComponentsVisible()
+*/
+bool PackageManagerCore::listAvailableAliases(const QString &regexp)
+{
+ setPackageViewer();
+ d->enableAllCategories();
+ qCDebug(QInstaller::lcInstallerInstallLog)
+ << "Searching aliases with regular expression:" << regexp;
+
+ ComponentModel *model = defaultComponentModel();
+ Q_UNUSED(model);
+
+ if (!d->m_updates) {
+ d->fetchMetaInformationFromRepositories();
+ d->addUpdateResourcesFromRepositories();
+
+ const PackagesList &packages = d->remotePackages();
+ if (!fetchAllPackages(packages, LocalPackagesMap())) {
+ qCWarning(QInstaller::lcInstallerInstallLog)
+ << "There was a problem with loading the package data.";
+ return false;
+ }
+ }
+
+ QRegularExpression re(regexp);
+ re.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+
+ QList<ComponentAlias *> matchedAliases;
+ for (auto *alias : qAsConst(d->m_componentAliases)) {
+ if (!alias)
+ continue;
+
+ if (re.match(alias->name()).hasMatch() && !alias->isUnstable()) {
+ if (alias->isVirtual() && !virtualComponentsVisible())
+ continue;
+
+ matchedAliases.append(alias);
+ }
+ }
+
+ if (matchedAliases.isEmpty()) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "No matching package aliases found.";
+ return false;
+ }
+
+ LoggingHandler::instance().printAliasInformation(matchedAliases);
+ return true;
}
bool PackageManagerCore::componentUninstallableFromCommandLine(const QString &componentName)
@@ -2280,7 +2804,7 @@ bool PackageManagerCore::componentUninstallableFromCommandLine(const QString &co
}
ComponentModel *model = defaultComponentModel();
const QModelIndex &idx = model->indexFromComponentName(component->treeName());
- if (model->data(idx, Qt::CheckStateRole) == QVariant::Invalid) {
+ if (model->data(idx, Qt::CheckStateRole) == QVariant()) {
// Component cannot be unselected, check why
if (component->forcedInstallation()) {
qCWarning(QInstaller::lcInstallerInstallLog).noquote().nospace()
@@ -2304,35 +2828,58 @@ bool PackageManagerCore::componentUninstallableFromCommandLine(const QString &co
/*!
\internal
- Tries to set \c Qt::CheckStateRole to \c Qt::Checked for given \a components in the
- default component model. Returns \c true if \a components contains at least one component
+ Tries to set \c Qt::CheckStateRole to \c Qt::Checked for given component \a names in the
+ default component model, and select given aliases in the \c names list.
+
+ Returns \c true if \a names contains at least one component or component alias
eligible for installation, otherwise returns \c false. An error message can be retrieved
with \a errorMessage.
*/
-bool PackageManagerCore::checkComponentsForInstallation(const QStringList &components, QString &errorMessage)
+bool PackageManagerCore::checkComponentsForInstallation(const QStringList &names, QString &errorMessage, bool &unstableAliasFound)
{
bool installComponentsFound = false;
ComponentModel *model = defaultComponentModel();
- foreach (const QString &name, components) {
+ foreach (const QString &name, names) {
Component *component = componentByName(name);
if (!component) {
- errorMessage.append(tr("Cannot install %1. Component not found.\n").arg(name));
+ // No such component, check if we have an alias by the name
+ if (ComponentAlias *alias = aliasByName(name)) {
+ if (alias->isUnstable()) {
+ errorMessage.append(tr("Cannot select alias %1. There was a problem loading this alias, "
+ "so it is marked unstable and cannot be selected.").arg(name) + QLatin1Char('\n'));
+ unstableAliasFound = true;
+ continue;
+ } else if (alias->isVirtual()) {
+ errorMessage.append(tr("Cannot select %1. Alias is marked virtual, meaning it cannot "
+ "be selected manually.").arg(name) + QLatin1Char('\n'));
+ continue;
+ }
+
+ alias->setSelected(true);
+ installComponentsFound = true;
+ } else {
+ errorMessage.append(tr("Cannot install %1. Component not found.").arg(name) + QLatin1Char('\n'));
+ }
+
continue;
}
const QModelIndex &idx = model->indexFromComponentName(component->treeName());
if (idx.isValid()) {
- if ((model->data(idx, Qt::CheckStateRole) == QVariant::Invalid) && !component->forcedInstallation()) {
+ if ((model->data(idx, Qt::CheckStateRole) == QVariant()) && !component->forcedInstallation()) {
// User cannot select the component, check why
if (component->autoDependencies().count() > 0) {
errorMessage.append(tr("Cannot install component %1. Component is installed only as automatic "
- "dependency to %2.\n").arg(name, component->autoDependencies().join(QLatin1Char(','))));
+ "dependency to %2.").arg(name, component->autoDependencies().join(QLatin1Char(','))) + QLatin1Char('\n'));
} else if (!component->isCheckable()) {
errorMessage.append(tr("Cannot install component %1. Component is not checkable, meaning you "
- "have to select one of the subcomponents.\n").arg(name));
+ "have to select one of the subcomponents.").arg(name) + QLatin1Char('\n'));
+ } else if (component->isUnstable()) {
+ errorMessage.append(tr("Cannot install component %1. There was a problem loading this component, "
+ "so it is marked unstable and cannot be selected.").arg(name) + QLatin1Char('\n'));
}
} else if (component->isInstalled()) {
- errorMessage.append(tr("Component %1 already installed\n").arg(name));
+ errorMessage.append(tr("Component %1 already installed").arg(name) + QLatin1Char('\n'));
} else {
model->setData(idx, Qt::Checked, Qt::CheckStateRole);
installComponentsFound = true;
@@ -2347,16 +2894,16 @@ bool PackageManagerCore::checkComponentsForInstallation(const QStringList &compo
return false;
} else if (trace->isVirtual()) {
errorMessage.append(tr("Cannot install %1. Component is a descendant "
- "of a virtual component %2.\n").arg(name, trace->name()));
+ "of a virtual component %2.").arg(name, trace->name()) + QLatin1Char('\n'));
return true;
}
}
};
// idx is invalid and component valid when we have invisible virtual component
if (component->isVirtual())
- errorMessage.append(tr("Cannot install %1. Component is virtual.\n").arg(name));
+ errorMessage.append(tr("Cannot install %1. Component is virtual.").arg(name) + QLatin1Char('\n'));
else if (!isDescendantOfVirtual())
- errorMessage.append(tr("Cannot install %1. Component not found.\n").arg(name));
+ errorMessage.append(tr("Cannot install %1. Component not found.").arg(name) + QLatin1Char('\n'));
}
}
if (!installComponentsFound)
@@ -2371,14 +2918,14 @@ bool PackageManagerCore::checkComponentsForInstallation(const QStringList &compo
void PackageManagerCore::listInstalledPackages(const QString &regexp)
{
setPackageViewer();
- LocalPackagesHash installedPackages = this->localInstalledPackages();
+ LocalPackagesMap installedPackages = this->localInstalledPackages();
if (!regexp.isEmpty()) {
qCDebug(QInstaller::lcInstallerInstallLog)
<< "Searching packages with regular expression:" << regexp;
}
- const QRegularExpression re(regexp);
-
+ QRegularExpression re(regexp);
+ re.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
const QStringList &keys = installedPackages.keys();
QList<LocalPackage> packages;
foreach (const QString &key, keys) {
@@ -2389,6 +2936,25 @@ void PackageManagerCore::listInstalledPackages(const QString &regexp)
LoggingHandler::instance().printLocalPackageInformation(packages);
}
+PackageManagerCore::Status PackageManagerCore::searchAvailableUpdates()
+{
+ setUpdater();
+ d->enableAllCategories();
+ if (!fetchRemotePackagesTree()) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << error();
+ return status();
+ }
+
+ const QList<QInstaller::Component *> availableUpdates =
+ components(QInstaller::PackageManagerCore::ComponentType::Root);
+ if (availableUpdates.isEmpty()) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << "There are currently no updates available.";
+ return status();
+ }
+ QInstaller::LoggingHandler::instance().printUpdateInformation(availableUpdates);
+ return status();
+}
+
/*!
Updates the selected components \a componentsToUpdate without GUI.
If essential components are found, then only those will be updated.
@@ -2396,13 +2962,25 @@ void PackageManagerCore::listInstalledPackages(const QString &regexp)
*/
PackageManagerCore::Status PackageManagerCore::updateComponentsSilently(const QStringList &componentsToUpdate)
{
- if (d->runningProcessesFound())
- throw Error(tr("Running processes found."));
setUpdater();
ComponentModel *model = updaterComponentModel();
- fetchRemotePackagesTree();
+ if (componentsToUpdate.isEmpty()) {
+ d->enableAllCategories();
+ fetchRemotePackagesTree();
+ } else {
+ bool fallbackReposFetched = false;
+ bool packagesFound = fetchPackagesWithFallbackRepositories(componentsToUpdate, fallbackReposFetched);
+
+ if (!packagesFound) {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace()
+ << "No components available for update with the current selection.";
+ d->setStatus(Canceled);
+ return status();
+ }
+ }
+
// List contains components containing update, if essential found contains only essential component
const QList<QInstaller::Component*> componentList = componentsMarkedForInstallation();
@@ -2508,15 +3086,44 @@ void PackageManagerCore::addLicenseItem(const QHash<QString, QVariantMap> &licen
}
}
+bool PackageManagerCore::hasLicenses() const
+{
+ foreach (Component* component, orderedComponentsToInstall()) {
+ if (isMaintainer() && component->isInstalled())
+ continue; // package manager or updater, hide as long as the component is installed
+
+ // The component is about to be installed and provides a license, so the page needs to
+ // be shown.
+ if (!component->licenses().isEmpty())
+ return true;
+ }
+ return false;
+}
+
+/*!
+ * Adds \a component local \a dependencies to a hash table for quicker search for
+ * uninstall dependency components.
+ */
+void PackageManagerCore::createLocalDependencyHash(const QString &component, const QString &dependencies) const
+{
+ d->createLocalDependencyHash(component, dependencies);
+}
+
+/*!
+ * Adds \a component \a newDependencies to a hash table for quicker search for
+ * install and uninstall autodependency components. Removes \a oldDependencies
+ * from the hash table if dependencies have changed.
+ */
+void PackageManagerCore::createAutoDependencyHash(const QString &component, const QString &oldDependencies, const QString &newDependencies) const
+{
+ d->createAutoDependencyHash(component, oldDependencies, newDependencies);
+}
/*!
Uninstalls the selected components \a components without GUI.
Returns PackageManagerCore installation status.
*/
PackageManagerCore::Status PackageManagerCore::uninstallComponentsSilently(const QStringList& components)
{
- if (d->runningProcessesFound())
- throw Error(tr("Running processes found."));
-
if (components.isEmpty()) {
qCDebug(QInstaller::lcInstallerInstallLog) << "No components selected for uninstallation.";
return PackageManagerCore::Canceled;
@@ -2555,8 +3162,6 @@ PackageManagerCore::Status PackageManagerCore::uninstallComponentsSilently(const
PackageManagerCore::Status PackageManagerCore::removeInstallationSilently()
{
setCompleteUninstallation(true);
- if (d->runningProcessesFound())
- throw Error(tr("Running processes found."));
qCDebug(QInstaller::lcInstallerInstallLog) << "Complete uninstallation was chosen.";
if (!(d->m_autoConfirmCommand || d->askUserConfirmCommand())) {
@@ -2578,22 +3183,7 @@ PackageManagerCore::Status PackageManagerCore::removeInstallationSilently()
PackageManagerCore::Status PackageManagerCore::createOfflineInstaller(const QStringList &componentsToAdd)
{
setOfflineGenerator();
- // init default model before fetching remote packages tree
- ComponentModel *model = defaultComponentModel();
- Q_UNUSED(model);
- if (!fetchRemotePackagesTree())
- return status();
-
- QString errorMessage;
- if (checkComponentsForInstallation(componentsToAdd, errorMessage)) {
- if (d->calculateComponentsAndRun()) {
- qCDebug(QInstaller::lcInstallerInstallLog)
- << "Created installer to:" << offlineBinaryName();
- }
- } else {
- qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace() << errorMessage;
- }
- return status();
+ return d->fetchComponentsAndInstall(componentsToAdd);
}
/*!
@@ -2605,13 +3195,10 @@ PackageManagerCore::Status PackageManagerCore::createOfflineInstaller(const QStr
PackageManagerCore::Status PackageManagerCore::installSelectedComponentsSilently(const QStringList& components)
{
if (!isInstaller()) {
- // Check if there are processes running in the install if maintenancetool is used.
- if (d->runningProcessesFound())
- throw Error(tr("Running processes found."));
setPackageManager();
//Check that packages are not already installed
- const LocalPackagesHash installedPackages = this->localInstalledPackages();
+ const LocalPackagesMap installedPackages = this->localInstalledPackages();
QStringList helperStrList;
helperStrList << components << installedPackages.keys();
helperStrList.removeDuplicates();
@@ -2620,21 +3207,7 @@ PackageManagerCore::Status PackageManagerCore::installSelectedComponentsSilently
return PackageManagerCore::Canceled;
}
}
-
- // init default model before fetching remote packages tree
- ComponentModel *model = defaultComponentModel();
- Q_UNUSED(model);
- if (!fetchRemotePackagesTree())
- return status();
-
- QString errorMessage;
- if (checkComponentsForInstallation(components, errorMessage)) {
- if (d->calculateComponentsAndRun())
- qCDebug(QInstaller::lcInstallerInstallLog) << "Components installed successfully";
- } else {
- qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace() << errorMessage;
- }
- return status();
+ return d->fetchComponentsAndInstall(components);
}
/*!
@@ -2700,6 +3273,21 @@ void PackageManagerCore::dropAdminRights()
}
/*!
+ Returns \c true if the installer has admin rights. For example, if the installer
+ was started with a root account, or the internal admin rights elevation is active.
+
+ Returns \c false otherwise.
+
+ \sa {installer::hasAdminRights}{installer.hasAdminRights}
+ \sa gainAdminRights()
+ \sa dropAdminRights()
+*/
+bool PackageManagerCore::hasAdminRights() const
+{
+ return AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive();
+}
+
+/*!
Sets checkAvailableSpace based on value of \a check.
*/
void PackageManagerCore::setCheckAvailableSpace(bool check)
@@ -2708,12 +3296,22 @@ void PackageManagerCore::setCheckAvailableSpace(bool check)
}
/*!
- Checks available disk space if the feature is not explicitly disabled. Informative
- text about space status can be retrieved by passing \a message parameter. Returns
+ * Returns informative text about disk space status
+ */
+QString PackageManagerCore::availableSpaceMessage() const
+{
+ return m_availableSpaceMessage;
+}
+
+/*!
+ Checks available disk space if the feature is not explicitly disabled. Returns
\c true if there is sufficient free space on installation and temporary volumes.
+
+ \sa availableSpaceMessage()
*/
-bool PackageManagerCore::checkAvailableSpace(QString &message) const
+bool PackageManagerCore::checkAvailableSpace()
{
+ m_availableSpaceMessage.clear();
const quint64 extraSpace = 256 * 1024 * 1024LL;
quint64 required(requiredDiskSpace());
quint64 tempRequired(requiredTemporaryDiskSpace());
@@ -2741,10 +3339,10 @@ bool PackageManagerCore::checkAvailableSpace(QString &message) const
<< humanReadableSize(repositorySize);
if (d->m_checkAvailableSpace) {
- const VolumeInfo tempVolume = VolumeInfo::fromPath(QDir::tempPath());
+ const VolumeInfo cacheVolume = VolumeInfo::fromPath(settings().localCachePath());
const VolumeInfo targetVolume = VolumeInfo::fromPath(value(scTargetDir));
- const quint64 tempVolumeAvailableSize = tempVolume.availableSize();
+ const quint64 cacheVolumeAvailableSize = cacheVolume.availableSize();
const quint64 installVolumeAvailableSize = targetVolume.availableSize();
// at the moment there is no better way to check this
@@ -2755,58 +3353,62 @@ bool PackageManagerCore::checkAvailableSpace(QString &message) const
return true;
}
- const bool tempOnSameVolume = (targetVolume == tempVolume);
- if (tempOnSameVolume) {
- qDebug() << "Tmp and install directories are on the same volume. Volume mount point:"
+ const bool cacheOnSameVolume = (targetVolume == cacheVolume);
+ if (cacheOnSameVolume) {
+ qDebug() << "Cache and install directories are on the same volume. Volume mount point:"
<< targetVolume.mountPath() << "Free space available:"
<< humanReadableSize(installVolumeAvailableSize);
} else {
- qDebug() << "Tmp is on a different volume than the installation directory. Tmp volume mount point:"
- << tempVolume.mountPath() << "Free space available:"
- << humanReadableSize(tempVolumeAvailableSize) << "Install volume mount point:"
+ qDebug() << "Cache is on a different volume than the installation directory. Cache volume mount point:"
+ << cacheVolume.mountPath() << "Free space available:"
+ << humanReadableSize(cacheVolumeAvailableSize) << "Install volume mount point:"
<< targetVolume.mountPath() << "Free space available:"
<< humanReadableSize(installVolumeAvailableSize);
}
- if (tempOnSameVolume && (installVolumeAvailableSize <= (required + tempRequired))) {
- message = tr("Not enough disk space to store temporary files and the "
+ if (cacheOnSameVolume && (installVolumeAvailableSize <= (required + tempRequired))) {
+ m_availableSpaceMessage = tr("Not enough disk space to store temporary files and the "
"installation. %1 are available, while the minimum required is %2.").arg(
humanReadableSize(installVolumeAvailableSize), humanReadableSize(required + tempRequired));
return false;
}
if (installVolumeAvailableSize < required) {
- message = tr("Not enough disk space to store all selected components! %1 are "
+ m_availableSpaceMessage = tr("Not enough disk space to store all selected components! %1 are "
"available, while the minimum required is %2.").arg(humanReadableSize(installVolumeAvailableSize),
humanReadableSize(required));
return false;
}
- if (tempVolumeAvailableSize < tempRequired) {
- message = tr("Not enough disk space to store temporary files! %1 are available, "
- "while the minimum required is %2.").arg(humanReadableSize(tempVolumeAvailableSize),
- humanReadableSize(tempRequired));
+ if (cacheVolumeAvailableSize < tempRequired) {
+ m_availableSpaceMessage = tr("Not enough disk space to store temporary files! %1 are available, "
+ "while the minimum required is %2. You may select another location for the "
+ "temporary files by modifying the local cache path from the installer settings.")
+ .arg(humanReadableSize(cacheVolumeAvailableSize), humanReadableSize(tempRequired));
return false;
}
if (installVolumeAvailableSize - required < 0.01 * targetVolume.size()) {
// warn for less than 1% of the volume's space being free
- message = tr("The volume you selected for installation seems to have sufficient space for "
+ m_availableSpaceMessage = tr("The volume you selected for installation seems to have sufficient space for "
"installation, but there will be less than 1% of the volume's space available afterwards.");
} else if (installVolumeAvailableSize - required < 100 * 1024 * 1024LL) {
// warn for less than 100MB being free
- message = tr("The volume you selected for installation seems to have sufficient "
+ m_availableSpaceMessage = tr("The volume you selected for installation seems to have sufficient "
"space for installation, but there will be less than 100 MB available afterwards.");
}
#ifdef Q_OS_WIN
if (isOfflineGenerator() && (required > UINT_MAX)) {
- message = tr("The estimated installer size %1 would exceed the supported executable "
+ m_availableSpaceMessage = tr("The estimated installer size %1 would exceed the supported executable "
"size limit of %2. The application may not be able to run.")
.arg(humanReadableSize(required), humanReadableSize(UINT_MAX));
}
#endif
}
- message = QString::fromLatin1("%1 %2").arg(message, tr("Installation will use %1 of disk space.")
+ m_availableSpaceMessage = QString::fromLatin1("%1 %2").arg(m_availableSpaceMessage,
+ (isOfflineGenerator()
+ ? tr("Created installer will use %1 of disk space.")
+ : tr("Installation will use %1 of disk space."))
.arg(humanReadableSize(requiredDiskSpace()))).simplified();
return true;
@@ -2865,6 +3467,10 @@ bool PackageManagerCore::killProcess(const QString &absoluteFilePath) const
}
/*!
+ \deprecated [4.6] Maintenance tool no longer automatically checks for all running processes
+ in the installation directory for CLI runs. To manually check for a process to stop, use
+ \l {component::addStopProcessForUpdateRequest}{component.addStopProcessForUpdateRequest} instead.
+
Sets additional \a processes that can run when
updating with the maintenance tool.
@@ -2876,6 +3482,10 @@ void PackageManagerCore::setAllowedRunningProcesses(const QStringList &processes
}
/*!
+ \deprecated [4.6] Maintenance tool no longer automatically checks for all running processes
+ in the installation directory for CLI runs. To manually check for a process to stop, use
+ \l {component::addStopProcessForUpdateRequest}{component.addStopProcessForUpdateRequest} instead.
+
Returns processes that are allowed to run when
updating with the maintenance tool.
@@ -3083,9 +3693,10 @@ bool PackageManagerCore::performOperation(const QString &name, const QStringList
*/
bool PackageManagerCore::versionMatches(const QString &version, const QString &requirement)
{
- QRegExp compEx(QLatin1String("([<=>]+)(.*)"));
- const QString comparator = compEx.exactMatch(requirement) ? compEx.cap(1) : QLatin1String("=");
- const QString ver = compEx.exactMatch(requirement) ? compEx.cap(2) : requirement;
+ static const QRegularExpression compEx(QLatin1String("^([<=>]+)(.*)$"));
+ const QRegularExpressionMatch match = compEx.match(requirement);
+ const QString comparator = match.hasMatch() ? match.captured(1) : QLatin1String("=");
+ const QString ver = match.hasMatch() ? match.captured(2) : requirement;
const bool allowEqual = comparator.contains(QLatin1Char('='));
const bool allowLess = comparator.contains(QLatin1Char('<'));
@@ -3181,6 +3792,17 @@ void PackageManagerCore::setInstallerBaseBinary(const QString &path)
}
/*!
+ Returns the value of \c installerbase binary which is used when writing
+ the maintenance tool. Value can be empty.
+
+ \sa setInstallerBaseBinary()
+*/
+QString PackageManagerCore::installerBaseBinary() const
+{
+ return d->m_installerBaseBinaryUnreplaced;
+}
+
+/*!
Sets the \c installerbase binary located at \a path to use when writing the
offline installer. Setting this makes it possible to run the offline generator
in cases where we are not running a real installer, i.e. when executing autotests.
@@ -3203,14 +3825,18 @@ void PackageManagerCore::addResourcesForOfflineGeneration(const QString &rcPath)
/*!
Returns the installer value for \a key. If \a key is not known to the system, \a defaultValue is
- returned. Additionally, on Windows, \a key can be a registry key.
+ returned. Additionally, on Windows, \a key can be a registry key. Optionally, you can specify the
+ \a format of the registry key. By default the \a format is QSettings::NativeFormat.
+ For accessing the 32-bit system registry from a 64-bit application running on 64-bit Windows,
+ use QSettings::Registry32Format. For accessing the 64-bit system registry from a 32-bit
+ application running on 64-bit Windows, use QSettings::Registry64Format.
\sa {installer::value}{installer.value}
\sa setValue(), containsValue(), valueChanged()
*/
-QString PackageManagerCore::value(const QString &key, const QString &defaultValue) const
+QString PackageManagerCore::value(const QString &key, const QString &defaultValue, const int &format) const
{
- return d->m_data.value(key, defaultValue).toString();
+ return d->m_data.value(key, defaultValue, static_cast<QSettings::Format>(format)).toString();
}
/*!
@@ -3375,6 +4001,14 @@ QString PackageManagerCore::offlineBinaryName() const
}
/*!
+ Add new \a source for looking component aliases.
+*/
+void PackageManagerCore::addAliasSource(const AliasSource &source)
+{
+ d->m_aliasSources.insert(source);
+}
+
+/*!
\sa {installer::setInstaller}{installer.setInstaller}
\sa isInstaller(), setUpdater(), setPackageManager()
*/
@@ -3433,6 +4067,7 @@ bool PackageManagerCore::isUninstaller() const
void PackageManagerCore::setUpdater()
{
d->m_magicBinaryMarker = BinaryContent::MagicUpdaterMarker;
+ d->m_componentByNameHash.clear();
emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
@@ -3453,6 +4088,7 @@ bool PackageManagerCore::isUpdater() const
void PackageManagerCore::setPackageManager()
{
d->m_magicBinaryMarker = BinaryContent::MagicPackageManagerMarker;
+ d->m_componentByNameHash.clear();
emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
@@ -3474,6 +4110,7 @@ bool PackageManagerCore::isPackageManager() const
void PackageManagerCore::setOfflineGenerator()
{
d->m_magicMarkerSupplement = BinaryContent::OfflineGenerator;
+ emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
/*!
@@ -3492,6 +4129,7 @@ bool PackageManagerCore::isOfflineGenerator() const
void PackageManagerCore::setPackageViewer()
{
d->m_magicMarkerSupplement = BinaryContent::PackageViewer;
+ emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
/*!
@@ -3505,6 +4143,17 @@ bool PackageManagerCore::isPackageViewer() const
}
/*!
+ Resets the binary marker supplement of the installer to \c Default.
+ The supplement enables or disables additional features on top of the binary
+ marker state (\c Installer, \c Updater, \c PackageManager, \c Uninstaller).
+*/
+void PackageManagerCore::resetBinaryMarkerSupplement()
+{
+ d->m_magicMarkerSupplement = BinaryContent::Default;
+ emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
+}
+
+/*!
Sets the installer magic binary marker based on \a magicMarker and
userSetBinaryMarker to \c true.
*/
@@ -3641,55 +4290,56 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
try {
// Check if we already added the component to the available components list.
// Component treenames and names must be unique.
- QString name = data.package->data(scTreeName).toString();
- if (name.isEmpty())
- name = data.package->data(scName).toString();
+ const QString packageName = data.package->data(scName).toString();
+ const QString packageTreeName = data.package->data(scTreeName).value<QPair<QString, bool>>().first;
+
+ QString name = packageTreeName.isEmpty() ? packageName : packageTreeName;
if (data.components->contains(name)) {
- d->setStatus(Failure, tr("Cannot register component! Component with identifier %1 "
- "already exists.").arg(name));
- return false;
+ qCritical() << "Cannot register component" << packageName << "with name" << name
+ << "! Component with identifier" << name << "already exists.";
+ // Conflicting original name, skip.
+ if (packageTreeName.isEmpty())
+ return false;
+
+ // Conflicting tree name, check if we can add with original name.
+ if (!settings().allowUnstableComponents() || data.components->contains(packageName))
+ return false;
+
+ qCDebug(lcInstallerInstallLog)
+ << "Registering component with the original indetifier:" << packageName;
+
+ component->removeValue(scTreeName);
+ const QString errorString = QLatin1String("Tree name conflicts with an existing indentifier");
+ d->m_pendingUnstableComponents.insert(component->name(),
+ QPair<Component::UnstableError, QString>(Component::InvalidTreeName, errorString));
}
- name = data.package->data(scName).toString();
+ name = packageName;
if (settings().allowUnstableComponents()) {
// Check if there are sha checksum mismatch. Component will still show in install tree
// but is unselectable.
- foreach (const QString packageName, d->m_metadataJob.shaMismatchPackages()) {
- if (packageName == component->name()) {
- QString errorString = QLatin1String("SHA mismatch detected for component ") + packageName;
- component->setUnstable(Component::UnstableError::ShaMismatch, errorString);
+ foreach (const QString pkgName, d->m_metadataJob.shaMismatchPackages()) {
+ if (pkgName == component->name()) {
+ const QString errorString = QLatin1String("SHA mismatch detected for component ") + pkgName;
+ d->m_pendingUnstableComponents.insert(component->name(),
+ QPair<Component::UnstableError, QString>(Component::ShaMismatch, errorString));
}
}
}
component->setUninstalled();
const QString localPath = component->localTempPath();
- if (LoggingHandler::instance().verboseLevel() == LoggingHandler::Detailed) {
- static QString lastLocalPath;
- if (lastLocalPath != localPath)
- qCDebug(QInstaller::lcDeveloperBuild()) << "Url is:" << localPath;
- lastLocalPath = localPath;
- }
-
- const Repository repo = d->m_metadataJob.repositoryForDirectory(localPath);
+ const Repository repo = d->m_metadataJob.repositoryForCacheDirectory(localPath);
if (repo.isValid()) {
component->setRepositoryUrl(repo.url());
component->setValue(QLatin1String("username"), repo.username());
component->setValue(QLatin1String("password"), repo.password());
}
- // add downloadable archive from xml
- const QStringList downloadableArchives = data.package->data(scDownloadableArchives).toString()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
-
- if (component->isFromOnlineRepository()) {
- foreach (const QString downloadableArchive, downloadableArchives)
- component->addDownloadableArchive(downloadableArchive);
- }
-
- const QStringList componentsToReplace = data.package->data(scReplaces).toString()
- .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ if (component->isFromOnlineRepository())
+ component->addDownloadableArchives(data.package->data(scDownloadableArchives).toString());
+ const QStringList componentsToReplace = QInstaller::splitStringWithComma(data.package->data(scReplaces).toString());
if (!componentsToReplace.isEmpty()) {
// Store the component (this is a component that replaces others) and all components that
// this one will replace.
@@ -3707,6 +4357,8 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
// a possible component to replace that might be installed (to mark the replacement as installed).
component->setInstalled();
component->setValue(scInstalledVersion, data.installedPackages->value(name).version);
+ component->setValue(scLocalDependencies, data.installedPackages->value(name).
+ dependencies.join(QLatin1String(",")));
return true;
}
@@ -3714,8 +4366,8 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
foreach (const QString &componentName, componentsToReplace) {
if (data.installedPackages->contains(componentName)) {
// We found a replacement that is installed.
- if (isPackageManager()) {
- // Mark the replacement component as installed as well. Only do this in package manager
+ if (isUpdater()) {
+ // Mark the replacement component as installed as well. Only do this in updater
// mode, otherwise it would not show up in the updaters component list.
component->setInstalled();
component->setValue(scInstalledVersion, data.installedPackages->value(componentName).version);
@@ -3730,13 +4382,21 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
return true;
}
-void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &components, const struct Data &data)
+void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &components,
+ const struct Data &data, QMap<QString, QString> *const treeNameComponents)
{
QHash<Component*, QStringList>::const_iterator it = data.replacementToExchangeables.constBegin();
// remember all components that got a replacement, required for uninstall
for (; it != data.replacementToExchangeables.constEnd(); ++it) {
foreach (const QString &componentName, it.value()) {
- Component *componentToReplace = components.take(componentName);
+ QString key = componentName;
+ if (treeNameComponents && treeNameComponents->contains(componentName)) {
+ // The exchangeable component is stored with a tree name key,
+ // remove from the list of components with tree name.
+ key = treeNameComponents->value(componentName);
+ treeNameComponents->remove(componentName);
+ }
+ Component *componentToReplace = components.value(key);
if (!componentToReplace) {
// If a component replaces another component which is not existing in the
// installer binary or the installed component list, just ignore it. This
@@ -3745,180 +4405,283 @@ void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &co
qCWarning(QInstaller::lcDeveloperBuild) << componentName << "- Does not exist in the repositories anymore.";
continue;
}
- if (!d->componentsToReplace().contains(componentName)) {
- componentToReplace = new Component(this);
- componentToReplace->setValue(scName, componentName);
- } else {
- // This case can happen when in installer mode as well, a component
- // is in the installer binary and its replacement component as well.
- d->replacementDependencyComponents().append(componentToReplace);
+ // Remove the replaced component from instal tree if
+ // 1. Running installer (component is replaced by other component)
+ // 2. Replacement is already installed but replacable is not
+ // Do not remove the replaced component from install tree
+ // in updater so that would show as an update
+ // Also do not remove the replaced component from install tree
+ // if it is already installed together with replacable component,
+ // otherwise it does not match what we have defined in components.xml
+ if (!isUpdater()
+ && (isInstaller() || (it.key() && it.key()->isInstalled() && !componentToReplace->isInstalled()))) {
+ components.remove(key);
+ d->m_deletedReplacedComponents.append(componentToReplace);
}
+ d->replacementDependencyComponents().append(componentToReplace);
+
+ //Following hashes are created for quicker search of components
d->componentsToReplace().insert(componentName, qMakePair(it.key(), componentToReplace));
+ QStringList oldValue = d->componentReplaces().value(it.key()->name());
+ d->componentReplaces().insert(it.key()->name(), oldValue << componentToReplace->name());
}
}
}
-bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const LocalPackagesHash &locals)
+bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const LocalPackagesMap &locals)
{
emit startAllComponentsReset();
- d->clearAllComponentLists();
- QHash<QString, QInstaller::Component*> components;
+ try {
+ d->clearAllComponentLists();
+ QHash<QString, QInstaller::Component*> allComponents;
- Data data;
- data.components = &components;
- data.installedPackages = &locals;
+ Data data;
+ data.components = &allComponents;
+ data.installedPackages = &locals;
- QMap<QString, QString> treeNameComponents;
- foreach (Package *const package, remotes) {
- if (d->statusCanceledOrFailed())
- return false;
+ QMap<QString, QString> remoteTreeNameComponents;
+ QMap<QString, QString> allTreeNameComponents;
- if (!ProductKeyCheck::instance()->isValidPackage(package->data(scName).toString()))
- continue;
+ std::function<bool(PackagesList *, bool)> loadRemotePackages;
+ loadRemotePackages = [&](PackagesList *treeNamePackages, bool firstRun) -> bool {
+ foreach (Package *const package, (firstRun ? remotes : *treeNamePackages)) {
+ if (d->statusCanceledOrFailed())
+ return false;
- QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
- data.package = package;
- component->loadDataFromPackage(*package);
- if (updateComponentData(data, component.data())) {
- // Create a list where is name and treename. Repo can contain a package with
- // a different treename of component which is already installed. We don't want
- // to move already installed local packages.
- const QString treeName = component->value(scTreeName);
- if (!treeName.isEmpty())
- treeNameComponents.insert(component->name(), treeName);
- QString name = component->treeName();
- components.insert(name, component.take());
- } else {
- return false;
+ if (!ProductKeyCheck::instance()->isValidPackage(package->data(scName).toString()))
+ continue;
+
+ if (firstRun && !package->data(scTreeName)
+ .value<QPair<QString, bool>>().first.isEmpty()) {
+ // Package has a tree name, leave for later
+ treeNamePackages->append(package);
+ continue;
+ }
+
+ std::unique_ptr<QInstaller::Component> remoteComponent(new QInstaller::Component(this));
+ data.package = package;
+ remoteComponent->loadDataFromPackage(*package);
+ if (updateComponentData(data, remoteComponent.get())) {
+ // Create a list where is name and treename. Repo can contain a package with
+ // a different treename of component which is already installed. We don't want
+ // to move already installed local packages.
+ const QString treeName = remoteComponent->value(scTreeName);
+ if (!treeName.isEmpty())
+ remoteTreeNameComponents.insert(remoteComponent->name(), treeName);
+ const QString name = remoteComponent->treeName();
+ allComponents.insert(name, remoteComponent.release());
+ }
+ }
+ // Second pass with leftover packages
+ return firstRun ? loadRemotePackages(treeNamePackages, false) : true;
+ };
+
+ {
+ // Loading remote package data is performed in two steps: first, components without
+ // - and then components with tree names. This is to ensure components with tree
+ // names do not replace other components when registering fails to a name conflict.
+ PackagesList treeNamePackagesTmp;
+ if (!loadRemotePackages(&treeNamePackagesTmp, true))
+ return false;
}
- }
+ allTreeNameComponents = remoteTreeNameComponents;
+
+ foreach (auto &package, locals) {
+ if (package.virtualComp && package.autoDependencies.isEmpty()) {
+ if (!d->m_localVirtualComponents.contains(package.name))
+ d->m_localVirtualComponents.append(package.name);
+ }
- foreach (const QString &key, locals.keys()) {
- QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
- component->loadDataFromPackage(locals.value(key));
- QString treeName = component->treeName();
-
- // 1. Component has a treename in local but not in remote
- if (!treeNameComponents.contains(component->name()) && !component->value(scTreeName).isEmpty()) {
- Component *comp = components.take(component->name());
- delete comp;
- components.insert(treeName, component.take());
- // 2. Component has different treename in local and remote, add with local treename
- } else if (treeNameComponents.contains(component->name())) {
- QString remoteTreeName = treeNameComponents.value(component->name());
- QString componentTreeName = component->value(scTreeName);
- if (remoteTreeName != componentTreeName) {
- Component *comp = components.take(treeNameComponents.value(component->name()));
- delete comp;
- components.insert(treeName, component.take());
+ std::unique_ptr<QInstaller::Component> localComponent(new QInstaller::Component(this));
+ localComponent->loadDataFromPackage(package);
+ const QString name = localComponent->treeName();
+
+ // 1. Component has a treename in local but not in remote, add with local treename
+ if (!remoteTreeNameComponents.contains(localComponent->name()) && !localComponent->value(scTreeName).isEmpty()) {
+ delete allComponents.take(localComponent->name());
+ // 2. Component has different treename in local and remote, add with local treename
+ } else if (remoteTreeNameComponents.contains(localComponent->name())) {
+ const QString remoteTreeName = remoteTreeNameComponents.value(localComponent->name());
+ const QString localTreeName = localComponent->value(scTreeName);
+ if (remoteTreeName != localTreeName) {
+ delete allComponents.take(remoteTreeNameComponents.value(localComponent->name()));
+ } else {
+ // 3. Component has same treename in local and remote, don't add the component again.
+ continue;
+ }
+ // 4. Component does not have treename in local or remote, don't add the component again.
+ } else if (allComponents.contains(localComponent->name())) {
+ Component *const component = allComponents.value(localComponent->name());
+ if (component->value(scTreeName).isEmpty() && localComponent->value(scTreeName).isEmpty())
+ continue;
+ }
+ // 5. Remote has treename for a different component that is already reserved
+ // by this local component, Or, remote adds component without treename
+ // but it conflicts with a local treename.
+ if (allComponents.contains(name)) {
+ const QString key = remoteTreeNameComponents.key(name);
+ qCritical() << "Cannot register component" << (key.isEmpty() ? name : key)
+ << "with name" << name << "! Component with identifier" << name
+ << "already exists.";
+
+ if (!key.isEmpty())
+ allTreeNameComponents.remove(key);
+
+ // Try to re-add the remote component as unstable
+ if (!key.isEmpty() && !allComponents.contains(key) && settings().allowUnstableComponents()) {
+ qCDebug(lcInstallerInstallLog)
+ << "Registering component with the original indetifier:" << key;
+
+ Component *component = allComponents.take(name);
+ component->removeValue(scTreeName);
+ const QString errorString = QLatin1String("Tree name conflicts with an existing indentifier");
+ d->m_pendingUnstableComponents.insert(component->name(),
+ QPair<Component::UnstableError, QString>(Component::InvalidTreeName, errorString));
+
+ allComponents.insert(key, component);
+ } else {
+ delete allComponents.take(name);
+ }
}
- // 3. Component has same treename in local and remote, don't add the component again.
- } else if (!components.contains(treeName)) {
- components.insert(treeName, component.take());
+
+ const QString treeName = localComponent->value(scTreeName);
+ if (!treeName.isEmpty())
+ allTreeNameComponents.insert(localComponent->name(), treeName);
+ allComponents.insert(name, localComponent.release());
}
- }
- // store all components that got a replacement
- storeReplacedComponents(components, data);
+ // store all components that got a replacement
+ storeReplacedComponents(allComponents, data, &allTreeNameComponents);
+
+ // Move children of treename components
+ createAutoTreeNames(allComponents, allTreeNameComponents);
+
+ if (!d->buildComponentTree(allComponents, true))
+ return false;
+
+ d->commitPendingUnstableComponents();
+
+ if (!d->buildComponentAliases())
+ return false;
+
+ } catch (const Error &error) {
+ d->clearAllComponentLists();
+ d->setStatus(PackageManagerCore::Failure, error.message());
- if (!d->buildComponentTree(components, true))
+ // TODO: make sure we remove all message boxes inside the library at some point.
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
+ tr("Error"), error.message());
return false;
+ }
emit finishAllComponentsReset(d->m_rootComponents);
return true;
}
-bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const LocalPackagesHash &locals)
+bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const LocalPackagesMap &locals)
{
emit startUpdaterComponentsReset();
- d->clearUpdaterComponentLists();
- QHash<QString, QInstaller::Component *> components;
+ try {
+ d->clearUpdaterComponentLists();
+ QHash<QString, QInstaller::Component *> components;
- Data data;
- data.components = &components;
- data.installedPackages = &locals;
+ Data data;
+ data.components = &components;
+ data.installedPackages = &locals;
- setFoundEssentialUpdate(false);
- LocalPackagesHash installedPackages = locals;
- QStringList replaceMes;
+ setFoundEssentialUpdate(false);
+ LocalPackagesMap installedPackages = locals;
+ QStringList replaceMes;
- foreach (Package *const update, remotes) {
- if (d->statusCanceledOrFailed())
- return false;
+ foreach (Package *const update, remotes) {
+ if (d->statusCanceledOrFailed())
+ return false;
- if (!ProductKeyCheck::instance()->isValidPackage(update->data(scName).toString()))
- continue;
+ if (!ProductKeyCheck::instance()->isValidPackage(update->data(scName).toString()))
+ continue;
- QScopedPointer<QInstaller::Component> component(new QInstaller::Component(this));
- data.package = update;
- component->loadDataFromPackage(*update);
- if (updateComponentData(data, component.data())) {
- // Keep a reference so we can resolve dependencies during update.
- d->m_updaterComponentsDeps.append(component.take());
-
-// const QString isNew = update->data(scNewComponent).toString();
-// if (isNew.toLower() != scTrue)
-// continue;
-
- const QString &name = d->m_updaterComponentsDeps.last()->name();
- const QString replaces = data.package->data(scReplaces).toString();
- installedPackages.take(name); // remove from local installed packages
-
- bool isValidUpdate = locals.contains(name);
- if (!isValidUpdate && !replaces.isEmpty()) {
- const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
- QString::SkipEmptyParts);
- foreach (const QString &possibleName, possibleNames) {
- if (locals.contains(possibleName)) {
- isValidUpdate = true;
- replaceMes << possibleName;
+ std::unique_ptr<QInstaller::Component> component(new QInstaller::Component(this));
+ data.package = update;
+ component->loadDataFromPackage(*update);
+ if (updateComponentData(data, component.get())) {
+ // Keep a reference so we can resolve dependencies during update.
+ d->m_updaterComponentsDeps.append(component.release());
+
+ // const QString isNew = update->data(scNewComponent).toString();
+ // if (isNew.toLower() != scTrue)
+ // continue;
+
+ const QString &name = d->m_updaterComponentsDeps.last()->name();
+ const QString replaces = data.package->data(scReplaces).toString();
+ installedPackages.take(name); // remove from local installed packages
+
+ bool isValidUpdate = locals.contains(name);
+ if (!replaces.isEmpty()) {
+ const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
+ Qt::SkipEmptyParts);
+ foreach (const QString &possibleName, possibleNames) {
+ if (locals.contains(possibleName)) {
+ isValidUpdate = true;
+ replaceMes << possibleName;
+ }
}
}
- }
- // break if the update is not valid and if it's not the maintenance tool (we might get an update
- // for the maintenance tool even if it's not currently installed - possible offline installation)
- if (!isValidUpdate && (update->data(scEssential, scFalse).toString().toLower() == scFalse))
- continue; // Update for not installed package found, skip it.
-
- const LocalPackage &localPackage = locals.value(name);
- if (!d->packageNeedsUpdate(localPackage, update))
- continue;
- // It is quite possible that we may have already installed the update. Lets check the last
- // update date of the package and the release date of the update. This way we can compare and
- // figure out if the update has been installed or not.
- const QDate updateDate = update->data(scReleaseDate).toDate();
- if (localPackage.lastUpdateDate > updateDate)
- continue;
+ // break if the update is not valid and if it's not the maintenance tool (we might get an update
+ // for the maintenance tool even if it's not currently installed - possible offline installation)
+ if (!isValidUpdate && (update->data(scEssential, scFalse).toString().toLower() == scFalse))
+ continue; // Update for not installed package found, skip it.
+
+ const LocalPackage &localPackage = locals.value(name);
+ if (!d->packageNeedsUpdate(localPackage, update))
+ continue;
+ // It is quite possible that we may have already installed the update. Lets check the last
+ // update date of the package and the release date of the update. This way we can compare and
+ // figure out if the update has been installed or not.
+ const QDate updateDate = update->data(scReleaseDate).toDate();
+ if (localPackage.lastUpdateDate > updateDate)
+ continue;
+
+ if (update->data(scEssential, scFalse).toString().toLower() == scTrue ||
+ update->data(scForcedUpdate, scFalse).toString().toLower() == scTrue) {
+ setFoundEssentialUpdate(true);
+ }
- if (update->data(scEssential, scFalse).toString().toLower() == scTrue ||
- update->data(scForcedUpdate, scFalse).toString().toLower() == scTrue) {
- setFoundEssentialUpdate(true);
+ // this is not a dependency, it is a real update
+ components.insert(name, d->m_updaterComponentsDeps.takeLast());
}
+ }
- // this is not a dependency, it is a real update
- components.insert(name, d->m_updaterComponentsDeps.takeLast());
- } else {
- return false;
+ QHash<QString, QInstaller::Component *> localReplaceMes;
+ foreach (const QString &key, installedPackages.keys()) {
+ QInstaller::Component *component = new QInstaller::Component(this);
+ component->loadDataFromPackage(installedPackages.value(key));
+ d->m_updaterComponentsDeps.append(component);
}
- }
- QHash<QString, QInstaller::Component *> localReplaceMes;
- foreach (const QString &key, installedPackages.keys()) {
- QInstaller::Component *component = new QInstaller::Component(this);
- component->loadDataFromPackage(installedPackages.value(key));
- d->m_updaterComponentsDeps.append(component);
- // Keep a list of local components that should be replaced
- if (replaceMes.contains(component->name()))
- localReplaceMes.insert(component->name(), component);
- }
+ foreach (const QString &key, locals.keys()) {
+ LocalPackage package = locals.value(key);
+ if (package.virtualComp && package.autoDependencies.isEmpty()) {
+ if (!d->m_localVirtualComponents.contains(package.name))
+ d->m_localVirtualComponents.append(package.name);
+ }
+ // Keep a list of local components that should be replaced
+ // Remove from components list - we don't want to update the component
+ // as it is replaced by other component
+ if (replaceMes.contains(key)) {
+ QInstaller::Component *component = new QInstaller::Component(this);
+ component->loadDataFromPackage(locals.value(key));
+ localReplaceMes.insert(component->name(), component);
+ delete components.take(component->name());
+ }
+ }
- // store all components that got a replacement, but do not modify the components list
- storeReplacedComponents(localReplaceMes.unite(components), data);
+ // store all components that got a replacement, but do not modify the components list
+ localReplaceMes.insert(components);
+ storeReplacedComponents(localReplaceMes, data);
- try {
if (!components.isEmpty()) {
// append all components w/o parent to the direct list
foreach (QInstaller::Component *component, components) {
@@ -3926,21 +4689,25 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
}
// after everything is set up, load the scripts
+ if (!d->loadComponentScripts(components))
+ return false;
+
foreach (QInstaller::Component *component, components) {
if (d->statusCanceledOrFailed())
return false;
- component->loadComponentScript();
if (!component->isUnstable())
component->setCheckState(Qt::Checked);
}
+ // even for possible dependencies we need to load the scripts for example to get archives
+ if (!d->loadComponentScripts(d->m_updaterComponentsDeps))
+ return false;
+
// after everything is set up, check installed components
foreach (QInstaller::Component *component, d->m_updaterComponentsDeps) {
if (d->statusCanceledOrFailed())
return false;
- // even for possible dependency we need to load the script for example to get archives
- component->loadComponentScript();
if (component->isInstalled()) {
// since we do not put them into the model, which would force a update of e.g. tri state
// components, we have to check all installed components ourselves
@@ -3948,7 +4715,6 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
component->setCheckState(Qt::Checked);
}
}
-
if (foundEssentialUpdate()) {
foreach (QInstaller::Component *component, components) {
if (d->statusCanceledOrFailed())
@@ -3976,7 +4742,6 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
}
} catch (const Error &error) {
d->clearUpdaterComponentLists();
- emit finishUpdaterComponentsReset(QList<QInstaller::Component*>());
d->setStatus(Failure, error.message());
// TODO: make sure we remove all message boxes inside the library at some point.
@@ -3989,6 +4754,80 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
return true;
}
+/*!
+ \internal
+
+ Creates automatic tree names for \a components that have a parent declaring
+ an explicit tree name. The child components keep the relative location
+ to their parent component.
+
+ The \a treeNameComponents is a map of original component names and new tree names.
+*/
+void PackageManagerCore::createAutoTreeNames(QHash<QString, Component *> &components
+ , const QMap<QString, QString> &treeNameComponents)
+{
+ if (treeNameComponents.isEmpty())
+ return;
+
+ QHash<QString, Component *> componentsTemp;
+ QMutableHashIterator<QString, Component* > i(components);
+ while (i.hasNext()) {
+ i.next();
+ Component *component = i.value();
+ if (component->treeName() != component->name()) // already handled
+ continue;
+
+ QString newName;
+ // Check treename candidates, keep the name closest to a leaf component
+ QMap<QString, QString>::const_iterator j;
+ for (j = treeNameComponents.begin(); j != treeNameComponents.end(); ++j) {
+ const QString name = j.key();
+ if (!component->name().startsWith(name))
+ continue;
+
+ const Component *parent = components.value(treeNameComponents.value(name));
+ if (!(parent && parent->treeNameMoveChildren()))
+ continue; // TreeName only applied to parent
+
+ if (newName.split(QLatin1Char('.'), Qt::SkipEmptyParts).count()
+ > name.split(QLatin1Char('.'), Qt::SkipEmptyParts).count()) {
+ continue;
+ }
+ newName = name;
+ }
+ if (newName.isEmpty()) // Nothing to do
+ continue;
+
+ const QString treeName = component->name()
+ .replace(newName, treeNameComponents.value(newName));
+
+ if (components.contains(treeName) || treeNameComponents.contains(treeName)) {
+ // Can happen if the parent was moved to an existing identifier (which did not
+ // have a component) and contains child that has a conflicting name with a component
+ // in the existing branch.
+ qCritical() << "Cannot register component" << component->name() << "with automatic "
+ "tree name" << treeName << "! Component with identifier" << treeName << "already exists.";
+
+ if (settings().allowUnstableComponents()) {
+ qCDebug(lcInstallerInstallLog)
+ << "Falling back to using the original indetifier:" << component->name();
+
+ const QString errorString = QLatin1String("Tree name conflicts with an existing indentifier");
+ d->m_pendingUnstableComponents.insert(component->name(),
+ QPair<Component::UnstableError, QString>(Component::InvalidTreeName, errorString));
+ } else {
+ i.remove();
+ }
+ continue;
+ }
+ component->setValue(scAutoTreeName, treeName);
+
+ i.remove();
+ componentsTemp.insert(treeName, component);
+ }
+ components.insert(componentsTemp);
+}
+
void PackageManagerCore::restoreCheckState()
{
d->restoreCheckState();
@@ -4053,8 +4892,6 @@ ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, con
ComponentModel::tr("Release Date"));
model->setHeaderData(ComponentModelHelper::UncompressedSizeColumn, Qt::Horizontal,
ComponentModel::tr("Size"));
- connect(model, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
- SLOT(componentsToInstallNeedsRecalculation()));
return model;
}
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index 6698155c3..170ddf557 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,6 +29,8 @@
#define PACKAGEMANAGERCORE_H
#include "binaryformat.h"
+#include "binarycontent.h"
+#include "component.h"
#include "protocol.h"
#include "repository.h"
#include "qinstallerglobal.h"
@@ -38,16 +40,20 @@
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtCore/QStringList>
-#include <QtCore/QVector>
+#include <QtCore/QList>
+#include <QSettings>
+#include <QModelIndex>
namespace QInstaller {
-class Component;
+struct AliasSource;
class ComponentModel;
+class ComponentAlias;
class ScriptEngine;
class PackageManagerCorePrivate;
class PackageManagerProxyFactory;
class Settings;
+class ComponentSortFilterProxyModel;
// -- PackageManagerCore
@@ -62,6 +68,7 @@ class INSTALLER_EXPORT PackageManagerCore : public QObject
public:
PackageManagerCore();
PackageManagerCore(qint64 magicmaker, const QList<OperationBlob> &ops,
+ const QString &datFilename = QString(),
const QString &socketName = QString(),
const QString &key = QLatin1String(Protocol::DefaultAuthorizationKey),
Protocol::Mode mode = Protocol::Mode::Production,
@@ -77,7 +84,8 @@ public:
Canceled = 3,
Unfinished = 4,
ForceUpdate = 5,
- EssentialUpdated = 6
+ EssentialUpdated = 6,
+ NoPackagesFound = 7
};
Status status() const;
QString error() const;
@@ -102,6 +110,14 @@ public:
AllNoReplacements = (Root | Descendants | Dependencies),
All = (Root | Descendants | Dependencies | Replacements)
};
+
+ struct DownloadItem
+ {
+ QString fileName;
+ QString sourceUrl;
+ bool checkSha1CheckSum;
+ };
+
Q_DECLARE_FLAGS(ComponentTypes, ComponentType)
static QFont virtualComponentsFont();
@@ -119,20 +135,24 @@ public:
static bool createLocalRepositoryFromBinary();
static void setCreateLocalRepositoryFromBinary(bool create);
+ static int maxConcurrentOperations();
+ static void setMaxConcurrentOperations(int count);
+
static Component *componentByName(const QString &name, const QList<Component *> &components);
bool directoryWritable(const QString &path) const;
bool fetchLocalPackagesTree();
- LocalPackagesHash localInstalledPackages();
+ LocalPackagesMap localInstalledPackages();
void networkSettingsChanged();
PackageManagerProxyFactory *proxyFactory() const;
void setProxyFactory(PackageManagerProxyFactory *factory);
PackagesList remotePackages();
- bool fetchRemotePackagesTree();
+ bool fetchRemotePackagesTree(const QStringList& components = QStringList());
bool fetchCompressedPackagesTree();
+ bool fetchPackagesWithFallbackRepositories(const QStringList& components, bool &fallBackReposFetched);
bool run();
void reset();
@@ -161,6 +181,7 @@ public:
Q_INVOKABLE static QString findPath(const QString &name, const QStringList &paths = QStringList());
Q_INVOKABLE void setInstallerBaseBinary(const QString &path);
+ QString installerBaseBinary() const;
void setOfflineBaseBinary(const QString &path);
void addResourcesForOfflineGeneration(const QString &rcPath);
@@ -168,7 +189,7 @@ public:
// parameter handling
Q_INVOKABLE bool containsValue(const QString &key) const;
Q_INVOKABLE void setValue(const QString &key, const QString &value);
- Q_INVOKABLE QString value(const QString &key, const QString &defaultValue = QString()) const;
+ Q_INVOKABLE QString value(const QString &key, const QString &defaultValue = QString(), const int &format = QSettings::NativeFormat) const;
Q_INVOKABLE QStringList values(const QString &key, const QStringList &defaultValue = QStringList()) const;
Q_INVOKABLE QString key(const QString &value) const;
@@ -187,12 +208,20 @@ public:
void setOfflineBinaryName(const QString &name);
QString offlineBinaryName() const;
- bool testChecksum() const;
- void setTestChecksum(bool test);
+ void addAliasSource(const AliasSource &source);
Q_INVOKABLE void addUserRepositories(const QStringList &repositories);
Q_INVOKABLE void setTemporaryRepositories(const QStringList &repositories,
bool replace = false, bool compressed = false);
+ bool addQBspRepositories(const QStringList &repositories);
+ bool validRepositoriesAvailable() const;
+ Q_INVOKABLE void setAllowCompressedRepositoryInstall(bool allow);
+ bool allowCompressedRepositoryInstall() const;
+ bool showRepositoryCategories() const;
+ QVariantMap organizedRepositoryCategories() const;
+ void enableRepositoryCategory(const QString &repositoryName, bool enable);
+ void runProgram();
+
Q_INVOKABLE void autoAcceptMessageBoxes();
Q_INVOKABLE void autoRejectMessageBoxes();
Q_INVOKABLE void setMessageBoxAutomaticAnswer(const QString &identifier, int button);
@@ -216,7 +245,7 @@ public:
Q_INVOKABLE QString toNativeSeparators(const QString &path);
Q_INVOKABLE QString fromNativeSeparators(const QString &path);
- bool checkTargetDir(const QString &targetDirectory);
+ bool installationAllowedToDirectory(const QString &targetDirectory);
QString targetDirWarning(const QString &targetDirectory) const;
public:
@@ -229,25 +258,42 @@ public:
void appendUpdaterComponent(Component *components);
QList<Component *> components(ComponentTypes mask, const QString &regexp = QString()) const;
- Component *componentByName(const QString &identifier) const;
+ Q_INVOKABLE QInstaller::Component *componentByName(const QString &identifier) const;
+ Q_INVOKABLE QList<QInstaller::Component *> components(const QString &regexp = QString()) const;
+
+ ComponentAlias *aliasByName(const QString &name) const;
Q_INVOKABLE bool calculateComponentsToInstall() const;
QList<Component*> orderedComponentsToInstall() const;
- bool calculateComponents(QString *displayString);
+
+ Q_INVOKABLE bool recalculateAllComponents();
+ QString componentResolveReasons() const;
Q_INVOKABLE bool calculateComponentsToUninstall() const;
QList<Component*> componentsToUninstall() const;
+ QList<Component *> componentsMarkedForInstallation() const;
+ QList<ComponentAlias *> aliasesMarkedForInstallation() const;
+
QString componentsToInstallError() const;
+ QString componentsToUninstallError() const;
QString installReason(Component *component) const;
+ QString uninstallReason(Component *component) const;
QList<Component*> dependees(const Component *component) const;
+ bool isDependencyForRequestedComponent(const Component *component) const;
+ QStringList localDependenciesToComponent(const Component *component) const;
ComponentModel *defaultComponentModel() const;
ComponentModel *updaterComponentModel() const;
+ ComponentSortFilterProxyModel *componentSortFilterProxyModel();
+
void listInstalledPackages(const QString &regexp = QString());
- void listAvailablePackages(const QString &regexp = QString(),
+ bool listAvailablePackages(const QString &regexp = QString(),
const QHash<QString, QString> &filters = QHash<QString, QString>());
+ bool listAvailableAliases(const QString &regexp = QString());
+
+ PackageManagerCore::Status searchAvailableUpdates();
PackageManagerCore::Status updateComponentsSilently(const QStringList &componentsToUpdate);
PackageManagerCore::Status installSelectedComponentsSilently(const QStringList& components);
PackageManagerCore::Status installDefaultComponentsSilently();
@@ -275,6 +321,8 @@ public:
void setPackageViewer();
Q_INVOKABLE bool isPackageViewer() const;
+ void resetBinaryMarkerSupplement();
+
void setUserSetBinaryMarker(qint64 magicMarker);
Q_INVOKABLE bool isUserSetBinaryMarker() const;
@@ -289,9 +337,11 @@ public:
Q_INVOKABLE bool gainAdminRights();
Q_INVOKABLE void dropAdminRights();
+ Q_INVOKABLE bool hasAdminRights() const;
void setCheckAvailableSpace(bool check);
- bool checkAvailableSpace(QString &message) const;
+ bool checkAvailableSpace();
+ QString availableSpaceMessage() const;
Q_INVOKABLE quint64 requiredDiskSpace() const;
Q_INVOKABLE quint64 requiredTemporaryDiskSpace() const;
@@ -335,6 +385,19 @@ public:
void clearLicenses();
QHash<QString, QMap<QString, QString>> sortedLicenses();
void addLicenseItem(const QHash<QString, QVariantMap> &licenses);
+ bool hasLicenses() const;
+ void createLocalDependencyHash(const QString &component, const QString &dependencies) const;
+ void createAutoDependencyHash(const QString &component, const QString &oldDependencies, const QString &newDependencies) const;
+
+ bool resetLocalCache(bool init = false);
+ bool clearLocalCache(QString *error = nullptr);
+ bool isValidCache() const;
+
+ template <typename T>
+ bool loadComponentScripts(const T &components, const bool postScript = false);
+
+ void saveGivenArguments(const QStringList &args);
+ QStringList givenArguments() const;
public Q_SLOTS:
bool runInstaller();
@@ -346,8 +409,8 @@ public Q_SLOTS:
void languageChanged();
void setCompleteUninstallation(bool complete);
void cancelMetaInfoJob();
- void componentsToInstallNeedsRecalculation();
- void clearComponentsToInstallCalculated();
+ void componentsToInstallNeedsRecalculation(); // TODO: deprecated, remove
+ void clearComponentsToInstallCalculated() {} // TODO: deprecated, remove
Q_SIGNALS:
void aboutCalculateComponentsToInstall() const;
@@ -355,11 +418,9 @@ Q_SIGNALS:
void aboutCalculateComponentsToUninstall() const;
void finishedCalculateComponentsToUninstall() const;
void componentAdded(QInstaller::Component *comp);
- void rootComponentsAdded(QList<QInstaller::Component*> components);
- void updaterComponentsAdded(QList<QInstaller::Component*> components);
void valueChanged(const QString &key, const QString &value);
void statusChanged(QInstaller::PackageManagerCore::Status);
- void defaultTranslationsLoadedForLanguage(QLocale::Language);
+ void defaultTranslationsLoadedForLanguage(QLocale lang);
void currentPageChanged(int page);
void finishButtonClicked();
@@ -382,6 +443,7 @@ Q_SIGNALS:
void offlineGenerationStarted();
void offlineGenerationFinished();
void titleMessageChanged(const QString &title);
+ void downloadArchivesFinished();
void wizardPageInsertionRequested(QWidget *widget, QInstaller::PackageManagerCore::WizardPage page);
void wizardPageRemovalRequested(QWidget *widget);
@@ -404,29 +466,35 @@ private:
struct Data {
Package *package;
QHash<QString, Component*> *components;
- const LocalPackagesHash *installedPackages;
+ const LocalPackagesMap *installedPackages;
QHash<Component*, QStringList> replacementToExchangeables;
};
bool updateComponentData(struct Data &data, QInstaller::Component *component);
- void storeReplacedComponents(QHash<QString, Component*> &components, const struct Data &data);
- bool fetchAllPackages(const PackagesList &remotePackages, const LocalPackagesHash &localPackages);
- bool fetchUpdaterPackages(const PackagesList &remotePackages, const LocalPackagesHash &localPackages);
+ void storeReplacedComponents(QHash<QString, Component*> &components, const struct Data &data,
+ QMap<QString, QString> *const treeNameComponents = nullptr);
+ bool fetchAllPackages(const PackagesList &remotePackages, const LocalPackagesMap &localPackages);
+ bool fetchUpdaterPackages(const PackagesList &remotePackages, const LocalPackagesMap &localPackages);
+
+ void createAutoTreeNames(QHash<QString, Component *> &components,
+ const QMap<QString, QString> &treeNameComponents);
void updateDisplayVersions(const QString &displayKey);
QString findDisplayVersion(const QString &componentName, const QHash<QString, QInstaller::Component*> &components,
const QString& versionKey, QHash<QString, bool> &visited);
ComponentModel *componentModel(PackageManagerCore *core, const QString &objectName) const;
- QList<Component *> componentsMarkedForInstallation() const;
- bool fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages);
+ bool fetchPackagesTree(const PackagesList &packages, const LocalPackagesMap installedPackages);
bool componentUninstallableFromCommandLine(const QString &componentName);
- bool checkComponentsForInstallation(const QStringList &components, QString &errorMessage);
+ bool checkComponentsForInstallation(const QStringList &names, QString &errorMessage, bool &unstableAliasFound);
private:
PackageManagerCorePrivate *const d;
friend class PackageManagerCorePrivate;
QHash<QString, QString> m_fileDialogAutomaticAnswers;
+ QHash<QString, QStringList> m_localVirtualWithDependants;
+ QString m_availableSpaceMessage;
+ QStringList m_arguments;
private:
// remove once we deprecate isSelected, setSelected etc...
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 51c044356..10ca27d00 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,7 +31,6 @@
#include "binarycontent.h"
#include "binaryformatenginehandler.h"
#include "binarylayout.h"
-#include "component.h"
#include "scriptengine.h"
#include "componentmodel.h"
#include "errors.h"
@@ -46,19 +45,25 @@
#include "qsettingswrapper.h"
#include "installercalculator.h"
#include "uninstallercalculator.h"
+#include "componentalias.h"
#include "componentchecker.h"
#include "globals.h"
#include "binarycreator.h"
#include "loggingutils.h"
+#include "concurrentoperationrunner.h"
+#include "remoteclient.h"
+#include "operationtracer.h"
#include "selfrestarter.h"
#include "filedownloaderfactory.h"
#include "updateoperationfactory.h"
+#include "constants.h"
#include <productkeycheck.h>
#include <QSettings>
#include <QtConcurrentRun>
+#include <QtConcurrent>
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
@@ -87,36 +92,6 @@ namespace QInstaller {
\internal
*/
-class OperationTracer
-{
-public:
- OperationTracer(Operation *operation) : m_operation(nullptr)
- {
- // don't create output for that hacky pseudo operation
- if (operation->name() != QLatin1String("MinimumProgress"))
- m_operation = operation;
- }
- void trace(const QString &state)
- {
- if (!m_operation)
- return;
- qCDebug(QInstaller::lcInstallerInstallLog).noquote() << QString::fromLatin1("%1 %2 operation: %3")
- .arg(state, m_operation->value(QLatin1String("component")).toString(), m_operation->name());
- QStringList args = m_operation->arguments();
- if (m_operation->requiresUnreplacedVariables())
- args = m_operation->packageManager()->replaceVariables(m_operation->arguments());
- qCDebug(QInstaller::lcInstallerInstallLog).noquote() << QString::fromLatin1("\t- arguments: %1")
- .arg(args.join(QLatin1String(", ")));
- }
- ~OperationTracer() {
- if (!m_operation)
- return;
- qCDebug(QInstaller::lcInstallerInstallLog) << "Done";
- }
-private:
- Operation *m_operation;
-};
-
static bool runOperation(Operation *operation, Operation::OperationType type)
{
OperationTracer tracer(operation);
@@ -151,54 +126,27 @@ static QStringList checkRunningProcessesFromList(const QStringList &processList)
static void deferredRename(const QString &oldName, const QString &newName, bool restart = false)
{
#ifdef Q_OS_WIN
- QStringList arguments;
-
- // Check if .vbs extension can be used for running renaming script. If not, create own extension
- QString extension = QLatin1String(".vbs");
- QSettingsWrapper settingRoot(QLatin1String("HKEY_CLASSES_ROOT\\.vbs"), QSettingsWrapper::NativeFormat);
- if (settingRoot.value(QLatin1String(".")).toString() != QLatin1String("VBSFile")) {
- extension = QLatin1String(".qtInstaller");
- QSettingsWrapper settingsUser(QLatin1String("HKEY_CURRENT_USER\\Software\\Classes"), QSettingsWrapper::NativeFormat);
- QString value = settingsUser.value(extension).toString();
- if (value != QLatin1String("VBSFile"))
- settingsUser.setValue(extension, QLatin1String("VBSFile"));
- }
- QTemporaryFile f(QDir::temp().absoluteFilePath(QLatin1String("deferredrenameXXXXXX%1")).arg(extension));
-
- QInstaller::openForWrite(&f);
- f.setAutoRemove(false);
-
- arguments << QDir::toNativeSeparators(f.fileName()) << QDir::toNativeSeparators(oldName)
- << QDir::toNativeSeparators(QFileInfo(oldName).dir().absoluteFilePath(QFileInfo(newName)
- .fileName()));
+ const QString currentExecutable = QCoreApplication::applicationFilePath();
+ const QString tmpExecutable = generateTemporaryFileName(currentExecutable);
- QTextStream batch(&f);
- batch.setCodec("UTF-16");
- batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n";
- batch << "Set tmp = WScript.CreateObject(\"WScript.Shell\")\n";
- batch << QString::fromLatin1("file = \"%1\"\n").arg(arguments[2]);
- batch << "on error resume next\n";
+ QFile::rename(currentExecutable, tmpExecutable);
+ QFile::rename(oldName, newName);
- batch << "while fso.FileExists(file)\n";
- batch << " fso.DeleteFile(file)\n";
- batch << " WScript.Sleep(1000)\n";
- batch << "wend\n";
- batch << QString::fromLatin1("fso.MoveFile \"%1\", file\n").arg(arguments[1]);
+ QStringList arguments;
if (restart) {
- //Restart with same command line arguments as first executable
- QStringList commandLineArguments = QCoreApplication::arguments();
- batch << QString::fromLatin1("tmp.exec \"%1 --%2")
- .arg(arguments[2]).arg(CommandLineOptions::scStartUpdaterLong);
- //Skip the first argument as that is executable itself
- for (int i = 1; i < commandLineArguments.count(); i++) {
- batch << QString::fromLatin1(" %1").arg(commandLineArguments.at(i));
- }
- batch << QString::fromLatin1("\"\n");
+ // Restart with same command line arguments as first executable
+ arguments = QCoreApplication::arguments();
+ arguments.removeFirst(); // Remove program name
+ arguments.prepend(tmpExecutable);
+ arguments.prepend(QLatin1String("--")
+ + CommandLineOptions::scCleanupUpdate);
+ } else {
+ arguments.append(QLatin1String("--")
+ + CommandLineOptions::scCleanupUpdateOnly);
+ arguments.append(tmpExecutable);
}
- batch << "fso.DeleteFile(WScript.ScriptFullName)\n";
+ QProcessWrapper::startDetached2(newName, arguments);
- QProcessWrapper::startDetached(QLatin1String("cscript"), QStringList() << QLatin1String("//Nologo")
- << arguments[0]);
#else
QFile::remove(newName);
QFile::rename(oldName, newName);
@@ -206,26 +154,56 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
#endif
}
+static bool filterMissingAliasesToInstall(const QString& component, const QList<ComponentAlias *> packages)
+{
+ bool packageFound = false;
+ for (qsizetype i = 0; i < packages.size(); ++i) {
+ packageFound = (packages.at(i)->name() == component);
+ if (packageFound)
+ break;
+ }
+ return !packageFound;
+}
+
+static bool filterMissingPackagesToInstall(const QString& component, const PackagesList& packages)
+{
+ bool packageFound = false;
+ for (qsizetype i = 0; i < packages.size(); ++i) {
+ packageFound = (packages.at(i)->data(scName).toString() == component);
+ if (packageFound)
+ break;
+ }
+ return !packageFound;
+}
// -- PackageManagerCorePrivate
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
: m_updateFinder(nullptr)
+ , m_aliasFinder(nullptr)
, m_localPackageHub(std::make_shared<LocalPackageHub>())
, m_status(PackageManagerCore::Unfinished)
, m_needsHardRestart(false)
, m_testChecksum(false)
, m_launchedAsRoot(AdminAuthorization::hasAdminRights())
+ , m_commandLineInstance(false)
+ , m_defaultInstall(false)
+ , m_userSetBinaryMarker(false)
+ , m_checkAvailableSpace(true)
, m_completeUninstall(false)
, m_needToWriteMaintenanceTool(false)
, m_dependsOnLocalInstallerBinary(false)
+ , m_autoAcceptLicenses(false)
+ , m_disableWriteMaintenanceTool(false)
+ , m_autoConfirmCommand(false)
, m_core(core)
, m_updates(false)
+ , m_aliases(false)
, m_repoFetched(false)
, m_updateSourcesAdded(false)
, m_magicBinaryMarker(0) // initialize with pseudo marker
, m_magicMarkerSupplement(BinaryContent::Default)
- , m_componentsToInstallCalculated(false)
+ , m_foundEssentialUpdate(false)
, m_componentScriptEngine(nullptr)
, m_controlScriptEngine(nullptr)
, m_installerCalculator(nullptr)
@@ -233,37 +211,46 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
, m_proxyFactory(nullptr)
, m_defaultModel(nullptr)
, m_updaterModel(nullptr)
+ , m_componentSortFilterProxyModel(nullptr)
, m_guiObject(nullptr)
, m_remoteFileEngineHandler(nullptr)
- , m_foundEssentialUpdate(false)
- , m_commandLineInstance(false)
- , m_defaultInstall(false)
- , m_userSetBinaryMarker(false)
- , m_checkAvailableSpace(true)
- , m_autoAcceptLicenses(false)
- , m_disableWriteMaintenanceTool(false)
- , m_autoConfirmCommand(false)
+ , m_datFileName(QString())
+#ifdef INSTALLCOMPRESSED
+ , m_allowCompressedRepositoryInstall(true)
+#else
+ , m_allowCompressedRepositoryInstall(false)
+#endif
+ , m_connectedOperations(0)
{
}
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
- const QList<OperationBlob> &performedOperations)
+ const QList<OperationBlob> &performedOperations, const QString &datFileName)
: m_updateFinder(nullptr)
+ , m_aliasFinder(nullptr)
, m_localPackageHub(std::make_shared<LocalPackageHub>())
, m_status(PackageManagerCore::Unfinished)
, m_needsHardRestart(false)
, m_testChecksum(false)
, m_launchedAsRoot(AdminAuthorization::hasAdminRights())
+ , m_commandLineInstance(false)
+ , m_defaultInstall(false)
+ , m_userSetBinaryMarker(false)
+ , m_checkAvailableSpace(true)
, m_completeUninstall(false)
, m_needToWriteMaintenanceTool(false)
, m_dependsOnLocalInstallerBinary(false)
+ , m_autoAcceptLicenses(false)
+ , m_disableWriteMaintenanceTool(false)
+ , m_autoConfirmCommand(false)
, m_core(core)
, m_updates(false)
+ , m_aliases(false)
, m_repoFetched(false)
, m_updateSourcesAdded(false)
, m_magicBinaryMarker(magicInstallerMaker)
, m_magicMarkerSupplement(BinaryContent::Default)
- , m_componentsToInstallCalculated(false)
+ , m_foundEssentialUpdate(false)
, m_componentScriptEngine(nullptr)
, m_controlScriptEngine(nullptr)
, m_installerCalculator(nullptr)
@@ -271,21 +258,21 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_proxyFactory(nullptr)
, m_defaultModel(nullptr)
, m_updaterModel(nullptr)
+ , m_componentSortFilterProxyModel(nullptr)
, m_guiObject(nullptr)
, m_remoteFileEngineHandler(new RemoteFileEngineHandler)
- , m_foundEssentialUpdate(false)
- , m_commandLineInstance(false)
- , m_defaultInstall(false)
- , m_userSetBinaryMarker(false)
- , m_checkAvailableSpace(true)
- , m_autoAcceptLicenses(false)
- , m_disableWriteMaintenanceTool(false)
- , m_autoConfirmCommand(false)
+ , m_datFileName(datFileName)
+#ifdef INSTALLCOMPRESSED
+ , m_allowCompressedRepositoryInstall(true)
+#else
+ , m_allowCompressedRepositoryInstall(false)
+#endif
+ , m_connectedOperations(0)
{
foreach (const OperationBlob &operation, performedOperations) {
- QScopedPointer<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance()
+ std::unique_ptr<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance()
.create(operation.name, core));
- if (op.isNull()) {
+ if (!op) {
qCWarning(QInstaller::lcInstallerInstallLog) << "Failed to load unknown operation"
<< operation.name;
continue;
@@ -296,7 +283,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
<< operation.name;
continue;
}
- m_performedOperationsOld.append(op.take());
+ m_performedOperationsOld.append(op.release());
}
connect(this, &PackageManagerCorePrivate::installationStarted,
@@ -325,6 +312,7 @@ PackageManagerCorePrivate::~PackageManagerCorePrivate()
qDeleteAll(m_performedOperationsCurrentSession);
delete m_updateFinder;
+ delete m_aliasFinder;
delete m_proxyFactory;
delete m_defaultModel;
@@ -366,7 +354,8 @@ bool PackageManagerCorePrivate::isProcessRunning(const QString &name,
}
/* static */
-bool PackageManagerCorePrivate::performOperationThreaded(Operation *operation, Operation::OperationType type)
+bool PackageManagerCorePrivate::performOperationThreaded(Operation *operation,
+ Operation::OperationType type)
{
QFutureWatcher<bool> futureWatcher;
const QFuture<bool> future = QtConcurrent::run(runOperation, operation, type);
@@ -427,11 +416,10 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
m_core->appendRootComponent(component);
}
- // after everything is set up, load the scripts if needed
- if (loadScript) {
- foreach (QInstaller::Component *component, components)
- component->loadComponentScript();
- }
+ // after everything is set up, load the scripts if needed and create helper hashes
+ // for autodependency and dependency components for quicker search later
+ if (loadScript && !loadComponentScripts(components))
+ return false;
// now we can preselect components in the tree
foreach (QInstaller::Component *component, components) {
@@ -456,10 +444,10 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
component->setCheckState(Qt::Checked);
clearInstallerCalculator();
- if (installerCalculator()->appendComponentsToInstall(components.values()) == false) {
- setStatus(PackageManagerCore::Failure, installerCalculator()->componentsToInstallError());
+ if (installerCalculator()->solve(components.values()) == false) {
+ setStatus(PackageManagerCore::Failure, installerCalculator()->error());
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
- tr("Unresolved dependencies"), installerCalculator()->componentsToInstallError());
+ tr("Unresolved dependencies"), installerCalculator()->error());
return false;
}
@@ -475,7 +463,6 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
} catch (const Error &error) {
clearAllComponentLists();
- emit m_core->finishAllComponentsReset(QList<QInstaller::Component*>());
setStatus(PackageManagerCore::Failure, error.message());
// TODO: make sure we remove all message boxes inside the library at some point.
@@ -486,8 +473,120 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
return true;
}
+bool PackageManagerCorePrivate::buildComponentAliases()
+{
+ // For now, aliases are only used for command line runs
+ if (!m_core->isCommandLineInstance())
+ return true;
+
+ {
+ const QList<ComponentAlias *> aliasList = componentAliases();
+ if (aliasList.isEmpty())
+ return true;
+
+ for (const auto *alias : aliasList) {
+ // Create a new alias object for package manager core to take ownership of
+ ComponentAlias *newAlias = new ComponentAlias(m_core);
+ for (const QString &key : alias->keys())
+ newAlias->setValue(key, alias->value(key));
+
+ m_componentAliases.insert(alias->name(), newAlias);
+ }
+ }
+ // After aliases are loaded, perform sanity checks:
+
+ // 1. Component check state is changed by alias selection, so store the initial state
+ storeCheckState();
+
+ Graph<QString> aliasGraph;
+ for (auto *alias : qAsConst(m_componentAliases)) {
+ aliasGraph.addNode(alias->name());
+ aliasGraph.addEdges(alias->name(),
+ QInstaller::splitStringWithComma(alias->value(scRequiredAliases)) <<
+ QInstaller::splitStringWithComma(alias->value(scOptionalAliases)));
+
+ if (!m_core->componentByName(alias->name())) {
+ // Name ok, select for sanity check calculation
+ alias->setSelected(true);
+ } else {
+ alias->setUnstable(ComponentAlias::ComponentNameConfict,
+ tr("Alias declares name that conflicts with an existing component \"%1\"")
+ .arg(alias->name()));
+ }
+ }
+
+ const QList<QString> sortedAliases = aliasGraph.sort();
+ // 2. Check for cyclic dependency errors
+ if (aliasGraph.hasCycle()) {
+ setStatus(PackageManagerCore::Failure, installerCalculator()->error());
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
+ tr("Unresolved component aliases"),
+ tr("Cyclic dependency between aliases \"%1\" and \"%2\" detected.")
+ .arg(aliasGraph.cycle().first, aliasGraph.cycle().second));
+
+ return false;
+ }
+
+ // 3. Test for required aliases and components, this triggers setting the
+ // alias unstable in case of a broken reference.
+ for (const auto &aliasName : sortedAliases) {
+ ComponentAlias *alias = m_componentAliases.value(aliasName);
+ if (!alias) // sortedAliases may contain dependencies that don't exist, we don't know it yet
+ continue;
+
+ alias->components();
+ alias->aliases();
+ }
+
+ clearInstallerCalculator();
+ // 4. Check for other errors preventing resolving components to install
+ if (!installerCalculator()->solve(m_componentAliases.values())) {
+ setStatus(PackageManagerCore::Failure, installerCalculator()->error());
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
+ tr("Unresolved component aliases"), installerCalculator()->error());
+
+ return false;
+ }
+
+ for (auto *alias : qAsConst(m_componentAliases))
+ alias->setSelected(false);
+
+ // 5. Restore original state
+ restoreCheckState();
+
+ return true;
+}
+
+template <typename T>
+bool PackageManagerCorePrivate::loadComponentScripts(const T &components, const bool postScript)
+{
+ infoMessage(nullptr, tr("Loading component scripts..."));
+
+ quint64 loadedComponents = 0;
+ for (auto *component : components) {
+ if (statusCanceledOrFailed())
+ return false;
+
+ component->loadComponentScript(postScript);
+ ++loadedComponents;
+
+ const int currentProgress = qRound(double(loadedComponents) / components.count() * 100);
+ infoProgress(nullptr, currentProgress, 100);
+ qApp->processEvents();
+ }
+ return true;
+}
+
+template bool PackageManagerCorePrivate::loadComponentScripts<QList<Component *>>(const QList<Component *> &, const bool);
+template bool PackageManagerCorePrivate::loadComponentScripts<QHash<QString, Component *>>(const QHash<QString, Component *> &, const bool);
+
void PackageManagerCorePrivate::cleanUpComponentEnvironment()
{
+ m_componentReplaces.clear();
+ m_autoDependencyComponentHash.clear();
+ m_localDependencyComponentHash.clear();
+ m_localVirtualComponents.clear();
+ m_componentByNameHash.clear();
// clean up registered (downloaded) data
if (m_core->isMaintainer())
BinaryFormatEngineHandler::instance()->clear();
@@ -496,6 +595,10 @@ void PackageManagerCorePrivate::cleanUpComponentEnvironment()
// so we need to remove the current component script engine
delete m_componentScriptEngine;
m_componentScriptEngine = nullptr;
+
+ // Calculators become invalid after clearing components
+ clearInstallerCalculator();
+ clearUninstallerCalculator();
}
ScriptEngine *PackageManagerCorePrivate::componentScriptEngine() const
@@ -514,18 +617,18 @@ ScriptEngine *PackageManagerCorePrivate::controlScriptEngine() const
void PackageManagerCorePrivate::clearAllComponentLists()
{
+ qDeleteAll(m_componentAliases);
+ m_componentAliases.clear();
+
QList<QInstaller::Component*> toDelete;
- toDelete << m_rootComponents;
+ toDelete << m_rootComponents << m_deletedReplacedComponents;
m_rootComponents.clear();
-
m_rootDependencyReplacements.clear();
+ m_deletedReplacedComponents.clear();
- const QList<QPair<Component*, Component*> > list = m_componentsToReplaceAllMode.values();
- for (int i = 0; i < list.count(); ++i)
- toDelete << list.at(i).second;
m_componentsToReplaceAllMode.clear();
- m_componentsToInstallCalculated = false;
+ m_foundEssentialUpdate = false;
qDeleteAll(toDelete);
cleanUpComponentEnvironment();
@@ -533,8 +636,10 @@ void PackageManagerCorePrivate::clearAllComponentLists()
void PackageManagerCorePrivate::clearUpdaterComponentLists()
{
- QSet<Component*> usedComponents =
- QSet<Component*>::fromList(m_updaterComponents + m_updaterComponentsDeps);
+
+ QSet<Component*> usedComponents(m_updaterComponents.begin(), m_updaterComponents.end());
+ usedComponents.unite(QSet<Component*>(m_updaterComponentsDeps.begin(),
+ m_updaterComponentsDeps.end()));
const QList<QPair<Component*, Component*> > list = m_componentsToReplaceUpdaterMode.values();
for (int i = 0; i < list.count(); ++i) {
@@ -550,7 +655,7 @@ void PackageManagerCorePrivate::clearUpdaterComponentLists()
m_updaterDependencyReplacements.clear();
m_componentsToReplaceUpdaterMode.clear();
- m_componentsToInstallCalculated = false;
+ m_foundEssentialUpdate = false;
qDeleteAll(usedComponents);
cleanUpComponentEnvironment();
@@ -566,6 +671,11 @@ QHash<QString, QPair<Component*, Component*> > &PackageManagerCorePrivate::compo
return (!isUpdater()) ? m_componentsToReplaceAllMode : m_componentsToReplaceUpdaterMode;
}
+QHash<QString, QStringList> &PackageManagerCorePrivate::componentReplaces()
+{
+ return m_componentReplaces;
+}
+
void PackageManagerCorePrivate::clearInstallerCalculator()
{
delete m_installerCalculator;
@@ -576,8 +686,7 @@ InstallerCalculator *PackageManagerCorePrivate::installerCalculator() const
{
if (!m_installerCalculator) {
PackageManagerCorePrivate *const pmcp = const_cast<PackageManagerCorePrivate *> (this);
- pmcp->m_installerCalculator = new InstallerCalculator(
- m_core->components(PackageManagerCore::ComponentType::AllNoReplacements));
+ pmcp->m_installerCalculator = new InstallerCalculator(m_core, pmcp->m_autoDependencyComponentHash);
}
return m_installerCalculator;
}
@@ -601,7 +710,8 @@ UninstallerCalculator *PackageManagerCorePrivate::uninstallerCalculator() const
}
}
- pmcp->m_uninstallerCalculator = new UninstallerCalculator(installedComponents);
+ pmcp->m_uninstallerCalculator = new UninstallerCalculator(m_core,
+ pmcp->m_autoDependencyComponentHash, pmcp->m_localDependencyComponentHash, pmcp->m_localVirtualComponents);
}
return m_uninstallerCalculator;
}
@@ -610,10 +720,9 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
{
m_coreCheckedHash.clear();
m_data = PackageManagerCoreData(params, isInstaller());
- m_componentsToInstallCalculated = false;
#ifdef Q_OS_LINUX
- if (m_launchedAsRoot)
+ if (m_launchedAsRoot && isInstaller())
m_data.setValue(scTargetDir, replaceVariables(m_data.settings().adminTargetDir()));
#endif
@@ -668,11 +777,16 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
m_localPackageHub->setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
if (isInstaller())
- m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 0));
+ m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 1));
+
+ const QString aliasFilePath = m_core->settings().aliasDefinitionsFile();
+ if (!aliasFilePath.isEmpty())
+ m_aliasSources.insert(AliasSource(AliasSource::SourceFileFormat::Xml, aliasFilePath, -1));
m_metadataJob.disconnect();
m_metadataJob.setAutoDelete(false);
m_metadataJob.setPackageManagerCore(m_core);
+
connect(&m_metadataJob, &Job::infoMessage, this, &PackageManagerCorePrivate::infoMessage);
connect(&m_metadataJob, &Job::progress, this, &PackageManagerCorePrivate::infoProgress);
connect(&m_metadataJob, &Job::totalProgress, this, &PackageManagerCorePrivate::totalProgress);
@@ -775,7 +889,12 @@ Operation *PackageManagerCorePrivate::takeOwnedOperation(Operation *operation)
QString PackageManagerCorePrivate::maintenanceToolName() const
{
- QString filename = m_data.settings().maintenanceToolName();
+ QString filename;
+ if (isInstaller())
+ filename = m_data.settings().maintenanceToolName();
+ else
+ filename = QCoreApplication::applicationName();
+
#if defined(Q_OS_MACOS)
if (QInstaller::isInBundle(QCoreApplication::applicationDirPath()))
filename += QLatin1String(".app/Contents/MacOS/") + filename;
@@ -785,6 +904,27 @@ QString PackageManagerCorePrivate::maintenanceToolName() const
return QString::fromLatin1("%1/%2").arg(targetDir()).arg(filename);
}
+QString PackageManagerCorePrivate::maintenanceToolAliasPath() const
+{
+#ifdef Q_OS_MACOS
+ const QString aliasName = m_data.settings().maintenanceToolAlias();
+ if (aliasName.isEmpty())
+ return QString();
+
+ const bool isRoot = m_core->hasAdminRights();
+ const QString applicationsDir = m_core->value(
+ isRoot ? QLatin1String("ApplicationsDir") : QLatin1String("ApplicationsDirUser")
+ );
+ QString maintenanceToolAlias = QString::fromLatin1("%1/%2")
+ .arg(applicationsDir, aliasName);
+ if (!maintenanceToolAlias.endsWith(QLatin1String(".app")))
+ maintenanceToolAlias += QLatin1String(".app");
+
+ return maintenanceToolAlias;
+#endif
+ return QString();
+}
+
QString PackageManagerCorePrivate::offlineBinaryName() const
{
QString filename = m_core->value(scOfflineBinaryName, qApp->applicationName()
@@ -797,6 +937,13 @@ QString PackageManagerCorePrivate::offlineBinaryName() const
return QString::fromLatin1("%1/%2").arg(targetDir()).arg(filename);
}
+QString PackageManagerCorePrivate::datFileName()
+{
+ if (m_datFileName.isEmpty())
+ m_datFileName = targetDir() + QLatin1Char('/') + m_data.settings().maintenanceToolName() + QLatin1String(".dat");
+ return m_datFileName;
+}
+
static QNetworkProxy readProxy(QXmlStreamReader &reader)
{
QNetworkProxy proxy(QNetworkProxy::HttpProxy);
@@ -850,12 +997,12 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
QVariantHash variables; // Do not change to QVariantMap! Breaks existing .ini files,
// cause the variant types do not match while restoring the variables from the file.
- QSettingsWrapper cfg(iniPath, QSettingsWrapper::IniFormat);
+ QSettingsWrapper cfg(iniPath, QSettings::IniFormat);
foreach (const QString &key, m_data.keys()) {
if (key == scRunProgramDescription || key == scRunProgram || key == scRunProgramArguments)
continue;
QVariant value = m_data.value(key);
- if (value.canConvert(QVariant::String))
+ if (value.canConvert<QString>())
value = replacePath(value.toString(), targetDir(), QLatin1String(scRelocatable));
variables.insert(key, value);
}
@@ -879,8 +1026,8 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
QFile file(targetDir() + QLatin1Char('/') + QLatin1String("network.xml"));
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- QXmlStreamWriter writer(&file);
- writer.setCodec("UTF-8");
+ QString outputStr;
+ QXmlStreamWriter writer(&outputStr);
writer.setAutoFormatting(true);
writer.writeStartDocument();
@@ -911,7 +1058,10 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
writer.writeEndElement();
}
writer.writeEndElement();
+ writer.writeTextElement(QLatin1String("LocalCachePath"), m_data.settings().localCachePath());
writer.writeEndElement();
+
+ file.write(outputStr.toUtf8());
}
setDefaultFilePermissions(&file, DefaultFilePermissions::NonExecutable);
}
@@ -919,7 +1069,7 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &targetDir)
{
QSettingsWrapper cfg(targetDir + QLatin1Char('/') + m_data.settings().maintenanceToolIniFile(),
- QSettingsWrapper::IniFormat);
+ QSettings::IniFormat);
const QVariantHash v = cfg.value(QLatin1String("Variables")).toHash(); // Do not change to
// QVariantMap! Breaks reading from existing .ini files, cause the variant types do not match.
for (QVariantHash::const_iterator it = v.constBegin(); it != v.constEnd(); ++it) {
@@ -951,7 +1101,7 @@ void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &target
case QXmlStreamReader::StartElement: {
if (reader.name() == QLatin1String("Network")) {
while (reader.readNextStartElement()) {
- const QStringRef name = reader.name();
+ const QStringView name = reader.name();
if (name == QLatin1String("Ftp")) {
m_data.settings().setFtpProxy(readProxy(reader));
} else if (name == QLatin1String("Http")) {
@@ -960,6 +1110,8 @@ void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &target
m_data.settings().addUserRepositories(readRepositories(reader, false));
} else if (name == QLatin1String("ProxyType")) {
m_data.settings().setProxyType(Settings::ProxyType(reader.readElementText().toInt()));
+ } else if (name == QLatin1String("LocalCachePath")) {
+ m_data.settings().setLocalCachePath(reader.readElementText());
} else {
reader.skipCurrentElement();
}
@@ -1058,8 +1210,11 @@ void PackageManagerCorePrivate::connectOperationToInstaller(Operation *const ope
connect(m_core, SIGNAL(installationInterrupted()), operationObject, SLOT(cancelOperation()));
if (mo->indexOfSignal(QMetaObject::normalizedSignature("progressChanged(double)")) > -1) {
+ // create unique object names for progress information track
+ operationObject->setObjectName(QLatin1String("operation_%1").arg(QString::number(m_connectedOperations)));
ProgressCoordinator::instance()->registerPartProgress(operationObject,
SIGNAL(progressChanged(double)), operationPartSize);
+ m_connectedOperations++;
}
}
}
@@ -1138,12 +1293,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
// other code a lot (since installers don't have any appended data either)
QFile dataOut(generateTemporaryFileName());
QInstaller::openForWrite(&dataOut);
- QInstaller::appendInt64(&dataOut, 0); // operations start
- QInstaller::appendInt64(&dataOut, 0); // operations end
- QInstaller::appendInt64(&dataOut, 0); // resource count
- QInstaller::appendInt64(&dataOut, 4 * sizeof(qint64)); // data block size
- QInstaller::appendInt64(&dataOut, BinaryContent::MagicUninstallerMarker);
- QInstaller::appendInt64(&dataOut, BinaryContent::MagicCookie);
+ QInstallerTools::createMTDatFile(dataOut);
{
QFile dummy(resourcePath.filePath(QLatin1String("installer.dat")));
@@ -1248,19 +1398,9 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *outp
QInstaller::appendInt64(output, BinaryContent::MagicUninstallerMarker);
}
-void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOperations)
+void PackageManagerCorePrivate::writeMaintenanceToolAppBundle(OperationList &performedOperations)
{
- if (m_disableWriteMaintenanceTool) {
- qCDebug(QInstaller::lcInstallerInstallLog()) << "Maintenance tool writing disabled.";
- return;
- }
-
- bool gainedAdminRights = false;
- if (!directoryWritable(targetDir())) {
- m_core->gainAdminRights();
- gainedAdminRights = true;
- }
-
+#ifdef Q_OS_MACOS
const QString targetAppDirPath = QFileInfo(maintenanceToolName()).path();
if (!QDir().exists(targetAppDirPath)) {
// create the directory containing the maintenance tool (like a bundle structure on macOS...)
@@ -1270,8 +1410,6 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
performOperationThreaded(op);
performedOperations.append(takeOwnedOperation(op));
}
-
-#ifdef Q_OS_MACOS
// if it is a bundle, we need some stuff in it...
const QString sourceAppDirPath = QCoreApplication::applicationDirPath();
if (isInstaller() && QInstaller::isInBundle(sourceAppDirPath)) {
@@ -1301,7 +1439,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
const QString after = QLatin1String("<string>") + QFileInfo(maintenanceToolName()).baseName()
+ QLatin1String("</string>");
while (!in.atEnd())
- out << in.readLine().replace(before, after) << endl;
+ out << in.readLine().replace(before, after) << Qt::endl;
// copy qt_menu.nib if it exists
op = createOwnedOperation(QLatin1String("Mkdir"));
@@ -1341,7 +1479,23 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
<< (targetAppDirPath + QLatin1String("/../plugins")));
performOperationThreaded(op);
}
+#else
+ Q_UNUSED(performedOperations);
#endif
+}
+
+void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOperations)
+{
+ if (m_disableWriteMaintenanceTool) {
+ qCDebug(QInstaller::lcInstallerInstallLog()) << "Maintenance tool writing disabled.";
+ return;
+ }
+
+ bool gainedAdminRights = false;
+ if (!directoryWritable(targetDir())) {
+ m_core->gainAdminRights();
+ gainedAdminRights = true;
+ }
try {
// 1 - check if we have a installer base replacement
@@ -1377,45 +1531,71 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
// 5.1 - this will only happen -if- we wrote out a new binary
bool newBinaryWritten = false;
- bool replacementExists = false;
+ QString mtName = maintenanceToolName();
const QString installerBaseBinary = replaceVariables(m_installerBaseBinaryUnreplaced);
- if (!installerBaseBinary.isEmpty() && QFileInfo(installerBaseBinary).exists()) {
+ if (!installerBaseBinary.isEmpty() && QFileInfo::exists(installerBaseBinary)) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Got a replacement installer base binary:"
<< installerBaseBinary;
-
- QFile replacementBinary(installerBaseBinary);
- try {
- QInstaller::openForRead(&replacementBinary);
- writeMaintenanceToolBinary(&replacementBinary, replacementBinary.size(), true);
- qCDebug(QInstaller::lcInstallerInstallLog) << "Wrote the binary with the new replacement.";
-
- newBinaryWritten = true;
- replacementExists = true;
- } catch (const Error &error) {
- qCWarning(QInstaller::lcInstallerInstallLog) << error.message();
- }
-
- if (!replacementBinary.remove()) {
- // Is there anything more sensible we can do with this error? I think not. It's not serious
- // enough for throwing / aborting the process.
- qCDebug(QInstaller::lcInstallerInstallLog) << "Cannot remove installer base binary"
- << installerBaseBinary << "after updating the maintenance tool:"
- << replacementBinary.errorString();
+ if (QInstaller::isInBundle(installerBaseBinary)) {
+ // In macOS the installerbase is a whole app bundle. We do not modify the maintenancetool name in app bundle
+ // so that possible signing and notarization will remain. Therefore, the actual maintenance tool name might
+ // differ from the one defined in the settings.
+ try {
+ const QString maintenanceToolRenamedName = installerBaseBinary + QLatin1String(".new");
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Writing maintenance tool " << maintenanceToolRenamedName;
+ QInstaller::copyDirectoryContents(installerBaseBinary, maintenanceToolRenamedName);
+
+ newBinaryWritten = true;
+ mtName = installerBaseBinary;
+ } catch (const Error &error) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << error.message();
+ }
+ try {
+ QInstaller::removeDirectory(installerBaseBinary);
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Removed installer base binary"
+ << installerBaseBinary << "after updating the maintenance tool.";
+ } catch (const Error &error) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Cannot remove installer base binary"
+ << installerBaseBinary << "after updating the maintenance tool:"
+ << error.message();
+ }
} else {
- qCDebug(QInstaller::lcInstallerInstallLog) << "Removed installer base binary"
- << installerBaseBinary << "after updating the maintenance tool.";
+ writeMaintenanceToolAppBundle(performedOperations);
+ QFile replacementBinary(installerBaseBinary);
+ try {
+ QInstaller::openForRead(&replacementBinary);
+ writeMaintenanceToolBinary(&replacementBinary, replacementBinary.size(), true);
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Wrote the binary with the new replacement.";
+
+ newBinaryWritten = true;
+ } catch (const Error &error) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << error.message();
+ }
+
+ if (!replacementBinary.remove()) {
+ // Is there anything more sensible we can do with this error? I think not. It's not serious
+ // enough for throwing / aborting the process.
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Cannot remove installer base binary"
+ << installerBaseBinary << "after updating the maintenance tool:"
+ << replacementBinary.errorString();
+ } else {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Removed installer base binary"
+ << installerBaseBinary << "after updating the maintenance tool.";
+ }
}
m_installerBaseBinaryUnreplaced.clear();
- } else if (!installerBaseBinary.isEmpty() && !QFileInfo(installerBaseBinary).exists()) {
+ } else if (!installerBaseBinary.isEmpty() && !QFileInfo::exists(installerBaseBinary)) {
qCWarning(QInstaller::lcInstallerInstallLog) << "The current maintenance tool could not be updated."
<< installerBaseBinary << "does not exist. Please fix the \"setInstallerBaseBinary"
"(<temp_installer_base_binary_path>)\" call in your script.";
+ writeMaintenanceToolAppBundle(performedOperations);
+ } else {
+ writeMaintenanceToolAppBundle(performedOperations);
}
QFile input;
BinaryLayout layout;
- const QString dataFile = targetDir() + QLatin1Char('/') + m_data.settings().maintenanceToolName()
- + QLatin1String(".dat");
+ const QString dataFile = datFileName();
try {
if (isInstaller()) {
if (QFile::exists(dataFile)) {
@@ -1496,14 +1676,38 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
input.close();
if (m_core->isInstaller())
registerMaintenanceTool();
+#ifdef Q_OS_MACOS
+ if (newBinaryWritten) {
+ // Remove old alias as the name may have changed.
+ deleteMaintenanceToolAlias();
+ const QString aliasPath = maintenanceToolAliasPath();
+ if (!aliasPath.isEmpty()) {
+ // The new alias file is created after the maintenance too binary is renamed,
+ // but we need to set the value before the variables get written to disk.
+ m_core->setValue(QLatin1String("CreatedMaintenanceToolAlias"), aliasPath);
+ }
+ }
+#endif
writeMaintenanceConfigFiles();
- deferredRename(dataFile + QLatin1String(".new"), dataFile, false);
+
+ QFile::remove(dataFile);
+ QFileInfo fi(mtName);
+ //Rename the dat file according to maintenancetool name
+ QFile::rename(dataFile + QLatin1String(".new"), targetDir() + QLatin1Char('/') + fi.baseName() + QLatin1String(".dat"));
+
+ const bool restart = !statusCanceledOrFailed() && m_needsHardRestart;
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Maintenance tool hard restart:"
+ << (restart ? "true." : "false.");
if (newBinaryWritten) {
- const bool restart = replacementExists && isUpdater() && (!statusCanceledOrFailed()) && m_needsHardRestart;
- deferredRename(maintenanceToolName() + QLatin1String(".new"), maintenanceToolName(), restart);
- qCDebug(QInstaller::lcInstallerInstallLog) << "Maintenance tool restart:"
- << (restart ? "true." : "false.");
+ if (isInstaller())
+ QFile::rename(mtName + QLatin1String(".new"), mtName);
+ else
+ deferredRename(mtName + QLatin1String(".new"), mtName, restart);
+ QFileInfo mtFileName(mtName);
+ writeMaintenanceToolAlias(mtFileName.fileName());
+ } else if (restart) {
+ SelfRestarter::setRestartOnQuit(true);
}
} catch (const Error &err) {
setStatus(PackageManagerCore::Failure);
@@ -1573,6 +1777,28 @@ void PackageManagerCorePrivate::writeOfflineBaseBinary()
}
}
+void PackageManagerCorePrivate::writeMaintenanceToolAlias(const QString &maintenanceToolName)
+{
+#ifdef Q_OS_MACOS
+ const QString aliasPath = maintenanceToolAliasPath();
+ if (aliasPath.isEmpty())
+ return;
+
+ QString maintenanceToolBundle = QString::fromLatin1("%1/%2")
+ .arg(targetDir(), maintenanceToolName);
+ if (!maintenanceToolBundle.endsWith(QLatin1String(".app")))
+ maintenanceToolBundle += QLatin1String(".app");
+
+ const QDir targetDir(QFileInfo(aliasPath).absolutePath());
+ if (!targetDir.exists())
+ targetDir.mkpath(targetDir.absolutePath());
+
+ mkalias(maintenanceToolBundle, aliasPath);
+#else
+ Q_UNUSED(maintenanceToolName)
+#endif
+}
+
QString PackageManagerCorePrivate::registerPath()
{
#ifdef Q_OS_WIN
@@ -1657,7 +1883,7 @@ bool PackageManagerCorePrivate::runInstaller()
throw Error(tr("It is not possible to install from network location"));
}
- if (!adminRightsGained) {
+ if (!m_core->hasAdminRights()) {
foreach (Component *component, componentsToInstall) {
if (component->value(scRequiresAdminRights, scFalse) == scFalse)
continue;
@@ -1690,8 +1916,8 @@ bool PackageManagerCorePrivate::runInstaller()
+ (PackageManagerCore::createLocalRepositoryFromBinary() ? 1 : 0);
double progressOperationSize = componentsInstallPartProgressSize / progressOperationCount;
- foreach (Component *component, componentsToInstall)
- installComponent(component, progressOperationSize, adminRightsGained);
+ // Now install the requested components
+ unpackAndInstallComponents(componentsToInstall, progressOperationSize);
if (m_core->isOfflineOnly() && PackageManagerCore::createLocalRepositoryFromBinary()) {
emit m_core->titleMessageChanged(tr("Creating local repository"));
@@ -1750,7 +1976,8 @@ bool PackageManagerCorePrivate::runInstaller()
if (progress < 100)
ProgressCoordinator::instance()->addManualPercentagePoints(100 - progress);
- ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("\nInstallation finished!"));
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Installation finished!"));
if (adminRightsGained)
m_core->dropAdminRights();
@@ -1768,7 +1995,9 @@ bool PackageManagerCorePrivate::runInstaller()
m_core->rollBackInstallation();
- ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("\nInstallation aborted!"));
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Installation aborted!"));
+
if (adminRightsGained)
m_core->dropAdminRights();
emit installationFinished();
@@ -1846,7 +2075,7 @@ bool PackageManagerCorePrivate::runPackageUpdater()
// There is a replacement, but the replacement is not scheduled for update, keep it as well.
if (m_componentsToReplaceUpdaterMode.contains(name)
- && !m_componentsToReplaceUpdaterMode.value(name).first->updateRequested()) {
+ && !m_installerCalculator->resolvedComponents().contains(m_componentsToReplaceUpdaterMode.value(name).first)) {
nonRevertedOperations.append(operation);
continue;
}
@@ -1886,7 +2115,7 @@ bool PackageManagerCorePrivate::runPackageUpdater()
}
// we did not request admin rights till we found out that a component/ undo needs admin rights
- if (updateAdminRights && !adminRightsGained) {
+ if (updateAdminRights && !m_core->hasAdminRights()) {
m_core->gainAdminRights();
m_core->dropAdminRights();
}
@@ -1907,15 +2136,15 @@ bool PackageManagerCorePrivate::runPackageUpdater()
if (undoOperations.count() > 0) {
ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("Removing deselected components..."));
- runUndoOperations(undoOperations, undoOperationProgressSize, adminRightsGained, true);
+ runUndoOperations(undoOperations, undoOperationProgressSize, true);
}
m_performedOperationsOld = nonRevertedOperations; // these are all operations left: those not reverted
const double progressOperationCount = countProgressOperations(componentsToInstall);
const double progressOperationSize = componentsInstallPartProgressSize / progressOperationCount;
- foreach (Component *component, componentsToInstall)
- installComponent(component, progressOperationSize, adminRightsGained);
+ // Now install the requested new components
+ unpackAndInstallComponents(componentsToInstall, progressOperationSize);
emit m_core->titleMessageChanged(tr("Creating Maintenance Tool"));
@@ -1927,7 +2156,8 @@ bool PackageManagerCorePrivate::runPackageUpdater()
// usually this should be only the reserved one from the beginning
if (progress < 100)
ProgressCoordinator::instance()->addManualPercentagePoints(100 - progress);
- ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("\nUpdate finished!"));
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Update finished!"));
if (adminRightsGained)
m_core->dropAdminRights();
@@ -1947,7 +2177,9 @@ bool PackageManagerCorePrivate::runPackageUpdater()
m_core->rollBackInstallation();
- ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("\nUpdate aborted!"));
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Update aborted!"));
+
if (adminRightsGained)
m_core->dropAdminRights();
emit installationFinished();
@@ -1981,7 +2213,7 @@ bool PackageManagerCorePrivate::runUninstaller()
}
// We did not yet request elevated permissions but they are required.
- if (updateAdminRights && !adminRightsGained) {
+ if (updateAdminRights && !m_core->hasAdminRights()) {
m_core->gainAdminRights();
m_core->dropAdminRights();
}
@@ -1989,15 +2221,16 @@ bool PackageManagerCorePrivate::runUninstaller()
const int uninstallOperationCount = countProgressOperations(undoOperations);
const double undoOperationProgressSize = double(1) / double(uninstallOperationCount);
- runUndoOperations(undoOperations, undoOperationProgressSize, adminRightsGained, false);
+ runUndoOperations(undoOperations, undoOperationProgressSize, false);
// No operation delete here, as all old undo operations are deleted in the destructor.
deleteMaintenanceTool(); // this will also delete the TargetDir on Windows
+ deleteMaintenanceToolAlias();
// If not on Windows, we need to remove TargetDir manually.
#ifndef Q_OS_WIN
if (QVariant(m_core->value(scRemoveTargetDir)).toBool() && !targetDir().isEmpty()) {
- if (updateAdminRights && !adminRightsGained)
+ if (updateAdminRights && !m_core->hasAdminRights())
adminRightsGained = m_core->gainAdminRights();
removeDirectoryThreaded(targetDir(), true);
qCDebug(QInstaller::lcInstallerInstallLog) << "Complete uninstallation was chosen.";
@@ -2073,7 +2306,7 @@ bool PackageManagerCorePrivate::runOfflineGenerator()
m_core->downloadNeededArchives(double(1));
const QString installerBaseReplacement = replaceVariables(m_offlineBaseBinaryUnreplaced);
- if (!installerBaseReplacement.isEmpty() && QFileInfo(installerBaseReplacement).exists()) {
+ if (!installerBaseReplacement.isEmpty() && QFileInfo::exists(installerBaseReplacement)) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Got a replacement installer base binary:"
<< offlineBinaryTempName;
@@ -2158,10 +2391,151 @@ bool PackageManagerCorePrivate::runOfflineGenerator()
return success;
}
-void PackageManagerCorePrivate::installComponent(Component *component, double progressOperationSize,
- bool adminRightsGained)
+void PackageManagerCorePrivate::unpackComponents(const QList<Component *> &components,
+ double progressOperationSize)
+{
+ OperationList unpackOperations;
+ bool becameAdmin = false;
+
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Preparing to unpack components..."));
+
+ // 1. Collect operations
+ quint64 totalOperationsSizeHint = 0;
+ for (auto *component : components) {
+ const OperationList operations = component->operations(Operation::Unpack);
+ if (!component->operationsCreatedSuccessfully())
+ m_core->setCanceled();
+
+ for (auto &op : operations) {
+ if (statusCanceledOrFailed())
+ throw Error(tr("Installation canceled by user"));
+
+ unpackOperations.append(op);
+ totalOperationsSizeHint += op->sizeHint();
+
+ // There's currently no way to control this on a per-operation basis, so
+ // any op requesting execution as admin means all extracts are done as admin.
+ if (!m_core->hasAdminRights() && op->value(QLatin1String("admin")).toBool())
+ becameAdmin = m_core->gainAdminRights();
+ }
+ }
+
+ // 2. Calculate proportional progress sizes
+ const double totalOperationsSize = progressOperationSize * unpackOperations.size();
+ for (auto *op : unpackOperations) {
+ const double ratio = static_cast<double>(op->sizeHint()) / totalOperationsSizeHint;
+ const double proportionalProgressOperationSize = totalOperationsSize * ratio;
+
+ connectOperationToInstaller(op, proportionalProgressOperationSize);
+ connectOperationCallMethodRequest(op);
+ }
+
+ // 3. Backup operations
+ ConcurrentOperationRunner runner(&unpackOperations, Operation::Backup);
+ runner.setMaxThreadCount(m_core->maxConcurrentOperations());
+
+ connect(m_core, &PackageManagerCore::installationInterrupted,
+ &runner, &ConcurrentOperationRunner::cancel);
+
+ connect(&runner, &ConcurrentOperationRunner::progressChanged, [](const int completed, const int total) {
+ const QString statusText = tr("%1 of %2 operations completed.")
+ .arg(QString::number(completed), QString::number(total));
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(statusText);
+ });
+ connect(&runner, &ConcurrentOperationRunner::finished, [] {
+ // Clear the status text to not cause confusion when installations begin.
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(QLatin1String(""));
+ });
+
+ const QHash<Operation *, bool> backupResults = runner.run();
+ const OperationList backupOperations = backupResults.keys();
+
+ for (auto &operation : backupOperations) {
+ if (m_core->status() == PackageManagerCore::Canceled)
+ break; // User canceled, no need to print warnings
+
+ if (!backupResults.value(operation) || operation->error() != Operation::NoError) {
+ // For Extract, backup stops only on read errors. That means the perform step will
+ // also fail later on, which handles the user selection on what to do with the error.
+ qCWarning(QInstaller::lcInstallerInstallLog) << QString::fromLatin1("Backup of operation "
+ "\"%1\" with arguments \"%2\" failed: %3").arg(operation->name(), operation->arguments()
+ .join(QLatin1String("; ")), operation->errorString());
+ continue;
+ }
+ // Backup may request performing operation as admin
+ if (!m_core->hasAdminRights() && operation->value(QLatin1String("admin")).toBool())
+ becameAdmin = m_core->gainAdminRights();
+ }
+
+ // TODO: Do we need to rollback backups too? For Extract op this works without,
+ // as the backup files are not used in Undo step.
+ if (statusCanceledOrFailed())
+ throw Error(tr("Installation canceled by user"));
+
+ // 4. Perform operations
+ std::sort(unpackOperations.begin(), unpackOperations.end(), [](Operation *lhs, Operation *rhs) {
+ // We want to run the longest taking operations first
+ return lhs->sizeHint() > rhs->sizeHint();
+ });
+
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Unpacking components..."));
+
+ runner.setType(Operation::Perform);
+ const QHash<Operation *, bool> results = runner.run();
+ const OperationList performedOperations = results.keys();
+
+ QString error;
+ for (auto &operation : performedOperations) {
+ const QString component = operation->value(QLatin1String("component")).toString();
+
+ bool ignoreError = false;
+ bool ok = results.value(operation);
+
+ while (!ok && !ignoreError && m_core->status() != PackageManagerCore::Canceled) {
+ qCDebug(QInstaller::lcInstallerInstallLog) << QString::fromLatin1("Operation \"%1\" with arguments "
+ "\"%2\" failed: %3").arg(operation->name(), operation->arguments()
+ .join(QLatin1String("; ")), operation->errorString());
+
+ const QMessageBox::StandardButton button =
+ MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(),
+ QLatin1String("installationErrorWithCancel"), tr("Installer Error"),
+ tr("Error during installation process (%1):\n%2").arg(component, operation->errorString()),
+ QMessageBox::Retry | QMessageBox::Ignore | QMessageBox::Cancel, QMessageBox::Cancel);
+
+ if (button == QMessageBox::Retry)
+ ok = performOperationThreaded(operation);
+ else if (button == QMessageBox::Ignore)
+ ignoreError = true;
+ else if (button == QMessageBox::Cancel)
+ m_core->interrupt();
+ }
+
+ if (ok || operation->error() > Operation::InvalidArguments) {
+ // Remember that the operation was performed, that allows us to undo it
+ // if this operation failed but still needs an undo call to cleanup.
+ addPerformed(operation);
+ }
+
+ // Catch the error message from first failure, but throw only after all
+ // operations requiring undo step are marked as performed.
+ if (!ok && !ignoreError && error.isEmpty())
+ error = operation->errorString();
+ }
+
+ if (becameAdmin)
+ m_core->dropAdminRights();
+
+ if (!error.isEmpty())
+ throw Error(error);
+
+ ProgressCoordinator::instance()->emitDetailTextChanged(tr("Done"));
+}
+
+void PackageManagerCorePrivate::installComponent(Component *component, double progressOperationSize)
{
- const OperationList operations = component->operations();
+ OperationList operations = component->operations(Operation::Install);
if (!component->operationsCreatedSuccessfully())
m_core->setCanceled();
@@ -2169,8 +2543,8 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
// show only components which do something, MinimumProgress is only for progress calculation safeness
bool showDetailsLog = false;
if (opCount > 1 || (opCount == 1 && operations.at(0)->name() != QLatin1String("MinimumProgress"))) {
- ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("\nInstalling component %1")
- .arg(component->displayName()));
+ ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(QLatin1Char('\n')
+ + tr("Installing component %1").arg(component->displayName()));
showDetailsLog = true;
}
@@ -2180,7 +2554,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
// maybe this operations wants us to be admin...
bool becameAdmin = false;
- if (!adminRightsGained && operation->value(QLatin1String("admin")).toBool()) {
+ if (!m_core->hasAdminRights() && operation->value(QLatin1String("admin")).toBool()) {
becameAdmin = m_core->gainAdminRights();
qCDebug(QInstaller::lcInstallerInstallLog) << operation->name() << "as admin:" << becameAdmin;
}
@@ -2223,11 +2597,13 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
if (!ok && !ignoreError)
throw Error(operation->errorString());
+ }
- if (((component->value(scEssential, scFalse) == scTrue) || (component->value(scForcedUpdate, scFalse) == scTrue))
- && !m_core->isCommandLineInstance()) {
+ if (!m_core->isCommandLineInstance()) {
+ if ((component->value(scEssential, scFalse) == scTrue) && !isInstaller())
+ m_needsHardRestart = true;
+ else if ((component->value(scForcedUpdate, scFalse) == scTrue) && isUpdater())
m_needsHardRestart = true;
- }
}
registerPathsForUninstallation(component->pathsForUninstallation(), component->name());
@@ -2245,8 +2621,10 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
m_localPackageHub->addPackage(component->name(),
component->value(scVersion),
component->value(scDisplayName),
- component->value(scTreeName),
+ QPair<QString, bool>(component->value(scTreeName),
+ component->treeNameMoveChildren()),
component->value(scDescription),
+ component->value(scSortingPriority).toInt(),
component->dependencies(),
component->autoDependencies(),
component->forcedInstallation(),
@@ -2265,23 +2643,54 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
ProgressCoordinator::instance()->emitDetailTextChanged(tr("Done"));
}
-bool PackageManagerCorePrivate::runningProcessesFound()
+PackageManagerCore::Status PackageManagerCorePrivate::fetchComponentsAndInstall(const QStringList& components)
{
- //Check if there are processes running in the install
- QStringList excludeFiles = m_allowedRunningProcesses;
- excludeFiles.append(maintenanceToolName());
+ // init default model before fetching remote packages tree
+ ComponentModel *model = m_core->defaultComponentModel();
+ Q_UNUSED(model);
- const QString performModeWarning = m_completeUninstall
- ? QLatin1String("Unable to remove components.")
- : QLatin1String("Unable to update components.");
+ bool fallbackReposFetched = false;
+ auto fetchComponents = [&]() {
+ bool packagesFound = m_core->fetchPackagesWithFallbackRepositories(components, fallbackReposFetched);
- QStringList runningProcesses = runningInstallerProcesses(excludeFiles);
- if (!runningProcesses.isEmpty()) {
- qCWarning(QInstaller::lcInstallerInstallLog).noquote().nospace() << performModeWarning
- << " Please stop these processes: " << runningProcesses << " and try again.";
+ if (!packagesFound) {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace()
+ << "No components available with the current selection.";
+ setStatus(PackageManagerCore::Canceled);
+ return false;
+ }
+ QString errorMessage;
+ bool unstableAliasFound = false;
+ if (m_core->checkComponentsForInstallation(components, errorMessage, unstableAliasFound)) {
+ if (!errorMessage.isEmpty())
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace() << errorMessage;
+ if (calculateComponentsAndRun()) {
+ if (m_core->isOfflineGenerator())
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Created installer to:" << offlineBinaryName();
+ else
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Components installed successfully";
+ }
+ } else {
+ // We found unstable alias and all repos were not fetched. Alias might have dependency to component
+ // which exists in non-default repository. Fetch all repositories now.
+ if (unstableAliasFound && !fallbackReposFetched) {
+ return false;
+ }
+ else {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace() << errorMessage
+ << "No components available with the current selection.";
+ }
+ }
return true;
+ };
+
+ if (!fetchComponents() && !fallbackReposFetched) {
+ setStatus(PackageManagerCore::Running);
+ enableAllCategories();
+ fetchComponents();
}
- return false;
+
+ return m_core->status();
}
void PackageManagerCorePrivate::setComponentSelection(const QString &id, Qt::CheckState state)
@@ -2302,6 +2711,14 @@ void PackageManagerCorePrivate::setComponentSelection(const QString &id, Qt::Che
void PackageManagerCorePrivate::deleteMaintenanceTool()
{
+ QDir resourcePath(QFileInfo(maintenanceToolName()).dir());
+ resourcePath.remove(QLatin1String("installer.dat"));
+ QDir installDir(targetDir());
+ installDir.remove(m_data.settings().maintenanceToolName() + QLatin1String(".dat"));
+ installDir.remove(QLatin1String("network.xml"));
+ installDir.remove(m_data.settings().maintenanceToolIniFile());
+ QInstaller::VerboseWriter::instance()->setFileName(QString());
+ installDir.remove(m_core->value(QLatin1String("LogFileName"), QLatin1String("InstallationLog.txt")));
#ifdef Q_OS_WIN
// Since Windows does not support that the maintenance tool deletes itself we have to go with a rather dirty
// hack. What we do is to create a batchfile that will try to remove the maintenance tool once per second. Then
@@ -2314,6 +2731,7 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
throw Error(tr("Cannot prepare removal"));
+ const bool removeTargetDir = QVariant(m_core->value(scRemoveTargetDir)).toBool();
QTextStream batch(&f);
batch << "Set fso = WScript.CreateObject(\"Scripting.FileSystemObject\")\n";
batch << "file = WScript.Arguments.Item(0)\n";
@@ -2325,10 +2743,12 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
batch << " fso.DeleteFile(file)\n";
batch << " WScript.Sleep(1000)\n";
batch << "wend\n";
-// batch << "if folder.SubFolders.Count = 0 and folder.Files.Count = 0 then\n";
+ if (!removeTargetDir)
+ batch << "if folder.SubFolders.Count = 0 and folder.Files.Count = 0 then\n";
batch << " Set folder = Nothing\n";
batch << " fso.DeleteFolder folderpath, true\n";
-// batch << "end if\n";
+ if (!removeTargetDir)
+ batch << "end if\n";
batch << "fso.DeleteFile(WScript.ScriptFullName)\n";
f.close();
@@ -2336,11 +2756,7 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
QStringList arguments;
arguments << QLatin1String("//Nologo") << batchfile; // execute the batchfile
arguments << QDir::toNativeSeparators(QFileInfo(installerBinaryPath()).absoluteFilePath());
- if (!m_performedOperationsOld.isEmpty()) {
- const Operation *const op = m_performedOperationsOld.first();
- if (op->name() == QLatin1String("Mkdir")) // the target directory name
- arguments << QDir::toNativeSeparators(QFileInfo(op->arguments().first()).absoluteFilePath());
- }
+ arguments << targetDir();
if (!QProcessWrapper::startDetached(QLatin1String("cscript"), arguments, QDir::rootPath()))
throw Error(tr("Cannot start removal"));
@@ -2364,10 +2780,27 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
}
}
+void PackageManagerCorePrivate::deleteMaintenanceToolAlias()
+{
+#ifdef Q_OS_MACOS
+ const QString maintenanceToolAlias = m_core->value(QLatin1String("CreatedMaintenanceToolAlias"));
+ QFile aliasFile(maintenanceToolAlias);
+ if (!maintenanceToolAlias.isEmpty() && !aliasFile.remove()) {
+ // Not fatal
+ qWarning(lcInstallerInstallLog) << "Cannot remove alias file"
+ << maintenanceToolAlias << "for maintenance tool:" << aliasFile.errorString();
+ }
+#endif
+}
+
void PackageManagerCorePrivate::registerMaintenanceTool()
{
#ifdef Q_OS_WIN
- QSettingsWrapper settings(registerPath(), QSettingsWrapper::NativeFormat);
+ auto quoted = [](const QString &s) {
+ return QString::fromLatin1("\"%1\"").arg(s);
+ };
+
+ QSettingsWrapper settings(registerPath(), QSettings::NativeFormat);
settings.setValue(scDisplayName, m_data.value(QLatin1String("ProductName")));
settings.setValue(QLatin1String("DisplayVersion"), m_data.value(QLatin1String("ProductVersion")));
const QString maintenanceTool = QDir::toNativeSeparators(maintenanceToolName());
@@ -2377,9 +2810,12 @@ void PackageManagerCorePrivate::registerMaintenanceTool()
settings.setValue(QLatin1String("Comments"), m_data.value(scTitle));
settings.setValue(QLatin1String("InstallDate"), QDateTime::currentDateTime().toString());
settings.setValue(QLatin1String("InstallLocation"), QDir::toNativeSeparators(targetDir()));
- settings.setValue(QLatin1String("UninstallString"), maintenanceTool);
- settings.setValue(QLatin1String("ModifyPath"), QString(maintenanceTool
- + QLatin1String(" --manage-packages")));
+ settings.setValue(QLatin1String("UninstallString"), QString(quoted(maintenanceTool)
+ + QLatin1String(" --") + CommandLineOptions::scStartUninstallerLong));
+ if (!isOfflineOnly()) {
+ settings.setValue(QLatin1String("ModifyPath"), QString(quoted(maintenanceTool)
+ + QLatin1String(" --") + CommandLineOptions::scStartPackageManagerLong));
+ }
// required disk space of the installed components
quint64 estimatedSizeKB = m_core->requiredDiskSpace() / 1024;
// add required space for the maintenance tool
@@ -2411,21 +2847,24 @@ void PackageManagerCorePrivate::registerMaintenanceTool()
void PackageManagerCorePrivate::unregisterMaintenanceTool()
{
#ifdef Q_OS_WIN
- QSettingsWrapper settings(registerPath(), QSettingsWrapper::NativeFormat);
+ QSettingsWrapper settings(registerPath(), QSettings::NativeFormat);
settings.remove(QString());
#endif
}
-void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOperations, double progressSize,
- bool adminRightsGained, bool deleteOperation)
+void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOperations,
+ double progressSize, bool deleteOperation)
{
try {
+ const int operationsCount = undoOperations.size();
+ int rolledBackOperations = 0;
+
foreach (Operation *undoOperation, undoOperations) {
if (statusCanceledOrFailed())
throw Error(tr("Installation canceled by user"));
bool becameAdmin = false;
- if (!adminRightsGained && undoOperation->value(QLatin1String("admin")).toBool())
+ if (!m_core->hasAdminRights() && undoOperation->value(QLatin1String("admin")).toBool())
becameAdmin = m_core->gainAdminRights();
connectOperationToInstaller(undoOperation, progressSize);
@@ -2458,6 +2897,10 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
}
}
+ ++rolledBackOperations;
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(tr("%1 of %2 operations rolled back.")
+ .arg(QString::number(rolledBackOperations), QString::number(operationsCount)));
+
if (becameAdmin)
m_core->dropAdminRights();
@@ -2472,6 +2915,7 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
throw Error(tr("Unknown error"));
}
m_localPackageHub->writeToDisk();
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(tr("Rollbacks complete."));
}
PackagesList PackageManagerCorePrivate::remotePackages()
@@ -2503,12 +2947,12 @@ PackagesList PackageManagerCorePrivate::remotePackages()
the application is running in installer mode or the local components file could not be parsed, the
hash is empty.
*/
-LocalPackagesHash PackageManagerCorePrivate::localInstalledPackages()
+LocalPackagesMap PackageManagerCorePrivate::localInstalledPackages()
{
if (isInstaller())
- return LocalPackagesHash();
+ return LocalPackagesMap();
+
- LocalPackagesHash installedPackages;
if (m_localPackageHub->error() != LocalPackageHub::NoError) {
if (m_localPackageHub->fileName().isEmpty())
m_localPackageHub->setFileName(componentsXmlPath());
@@ -2525,14 +2969,26 @@ LocalPackagesHash PackageManagerCorePrivate::localInstalledPackages()
setStatus(PackageManagerCore::Failure, tr("Failure to read packages from %1.")
.arg(componentsXmlPath()));
}
+ return m_localPackageHub->localPackages();
+}
- foreach (const LocalPackage &package, m_localPackageHub->packageInfos()) {
- if (statusCanceledOrFailed())
- break;
- installedPackages.insert(package.name, package);
+QList<ComponentAlias *> PackageManagerCorePrivate::componentAliases()
+{
+ if (m_aliases && m_aliasFinder)
+ return m_aliasFinder->aliases();
+
+ m_aliases = false;
+ delete m_aliasFinder;
+
+ m_aliasFinder = new AliasFinder(m_core);
+ m_aliasFinder->setAliasSources(m_aliasSources);
+ if (!m_aliasFinder->run()) {
+ qCDebug(lcDeveloperBuild) << "No component aliases found." << Qt::endl;
+ return QList<ComponentAlias *>();
}
- return installedPackages;
+ m_aliases = true;
+ return m_aliasFinder->aliases();
}
bool PackageManagerCorePrivate::fetchMetaInformationFromRepositories(DownloadType type)
@@ -2565,12 +3021,12 @@ bool PackageManagerCorePrivate::fetchMetaInformationFromRepositories(DownloadTyp
return m_repoFetched;
}
-bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChecksum, bool compressedRepository)
+bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool compressedRepository)
{
if (!compressedRepository && m_updateSourcesAdded)
return m_updateSourcesAdded;
- const QList<Metadata> metadata = m_metadataJob.metadata();
+ const QList<Metadata *> metadata = m_metadataJob.metadata();
if (metadata.isEmpty()) {
m_updateSourcesAdded = true;
return m_updateSourcesAdded;
@@ -2583,53 +3039,25 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
m_updates = false;
m_updateSourcesAdded = false;
if (isInstaller())
- m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 0));
+ m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 1));
}
- foreach (const Metadata &data, metadata) {
- if (compressedRepository && !data.repository.isCompressed()) {
+ foreach (const Metadata *data, metadata) {
+ if (compressedRepository && !data->repository().isCompressed()) {
continue;
}
if (statusCanceledOrFailed())
return false;
- if (data.directory.isEmpty())
+ if (data->path().isEmpty())
continue;
- if (parseChecksum) {
- const QString updatesXmlPath = data.directory + QLatin1String("/Updates.xml");
- QFile updatesFile(updatesXmlPath);
- try {
- QInstaller::openForRead(&updatesFile);
- } catch(const Error &e) {
- qCWarning(QInstaller::lcInstallerInstallLog) << "Error opening Updates.xml:"
- << e.message();
- setStatus(PackageManagerCore::Failure, tr("Cannot add temporary update source information."));
- return false;
- }
-
- int line = 0;
- int column = 0;
- QString error;
- QDomDocument doc;
- if (!doc.setContent(&updatesFile, &error, &line, &column)) {
- qCWarning(QInstaller::lcInstallerInstallLog).nospace() << "Parse error in file "
- << updatesFile.fileName() << ": " << error << " at line " << line
- << " col " << column;
- setStatus(PackageManagerCore::Failure, tr("Cannot add temporary update source information."));
- return false;
- }
-
- const QDomNode checksum = doc.documentElement().firstChildElement(QLatin1String("Checksum"));
- if (!checksum.isNull())
- m_core->setTestChecksum(checksum.toElement().text().toLower() == scTrue);
- }
- if (data.repository.isCompressed())
- m_compressedPackageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 2));
+ if (data->repository().isCompressed())
+ m_compressedPackageSources.insert(PackageSource(QUrl::fromLocalFile(data->path()), 2, data->repository().postLoadComponentScript()));
else
- m_packageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 1));
+ m_packageSources.insert(PackageSource(QUrl::fromLocalFile(data->path()), 0, data->repository().postLoadComponentScript()));
- ProductKeyCheck::instance()->addPackagesFromXml(data.directory + QLatin1String("/Updates.xml"));
+ ProductKeyCheck::instance()->addPackagesFromXml(data->path() + QLatin1String("/Updates.xml"));
}
if ((compressedRepository && m_compressedPackageSources.count() == 0 ) ||
(!compressedRepository && m_packageSources.count() == 0)) {
@@ -2655,7 +3083,6 @@ void PackageManagerCorePrivate::restoreCheckState()
}
m_coreCheckedHash.clear();
- m_componentsToInstallCalculated = false;
}
void PackageManagerCorePrivate::storeCheckState()
@@ -2668,6 +3095,76 @@ void PackageManagerCorePrivate::storeCheckState()
m_coreCheckedHash.insert(component, component->checkState());
}
+void PackageManagerCorePrivate::updateComponentInstallActions()
+{
+ for (Component *component : m_core->components(PackageManagerCore::ComponentType::All)) {
+ component->setInstallAction(component->isInstalled()
+ ? ComponentModelHelper::KeepInstalled
+ : ComponentModelHelper::KeepUninstalled);
+ }
+ for (Component *component : uninstallerCalculator()->resolvedComponents())
+ component->setInstallAction(ComponentModelHelper::Uninstall);
+ for (Component *component : installerCalculator()->resolvedComponents())
+ component->setInstallAction(ComponentModelHelper::Install);
+}
+
+bool PackageManagerCorePrivate::enableAllCategories()
+{
+ QSet<RepositoryCategory> repoCategories = m_data.settings().repositoryCategories();
+ bool additionalRepositoriesEnabled = false;
+ for (const auto &category : repoCategories) {
+ if (!category.isEnabled()) {
+ additionalRepositoriesEnabled = true;
+ enableRepositoryCategory(category, true);
+ }
+ }
+ return additionalRepositoriesEnabled;
+}
+
+void PackageManagerCorePrivate::enableRepositoryCategory(const RepositoryCategory &repoCategory, const bool enable)
+{
+ RepositoryCategory replacement = repoCategory;
+ replacement.setEnabled(enable);
+ QSet<RepositoryCategory> tmpRepoCategories = m_data.settings().repositoryCategories();
+ if (tmpRepoCategories.contains(repoCategory)) {
+ tmpRepoCategories.remove(repoCategory);
+ tmpRepoCategories.insert(replacement);
+ m_data.settings().addRepositoryCategories(tmpRepoCategories);
+ }
+}
+
+bool PackageManagerCorePrivate::installablePackagesFound(const QStringList& components)
+{
+ if (components.isEmpty())
+ return true;
+
+ PackagesList remotes = remotePackages();
+
+ auto componentsNotFoundForInstall = QtConcurrent::blockingFiltered(
+ components,
+ [remotes](const QString& installerPackage) {
+ return filterMissingPackagesToInstall(installerPackage, remotes);
+ }
+ );
+
+ if (componentsNotFoundForInstall.count() > 0) {
+ QList<ComponentAlias *> aliasList = componentAliases();
+ auto aliasesNotFoundForInstall = QtConcurrent::blockingFiltered(
+ components,
+ [aliasList](const QString& installerPackage) {
+ return filterMissingAliasesToInstall(installerPackage, aliasList);
+ }
+ );
+
+ if (aliasesNotFoundForInstall.count() > 0) {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote().nospace() << "Cannot select " << aliasesNotFoundForInstall.join(QLatin1String(", ")) << ". Component(s) not found.";
+ setStatus(PackageManagerCore::NoPackagesFound);
+ return false;
+ }
+ }
+ return true;
+}
+
void PackageManagerCorePrivate::connectOperationCallMethodRequest(Operation *const operation)
{
QObject *const operationObject = dynamic_cast<QObject *> (operation);
@@ -2718,6 +3215,34 @@ void PackageManagerCorePrivate::handleMethodInvocationRequest(const QString &inv
QMetaObject::invokeMethod(obj, qPrintable(invokableMethodName));
}
+/*
+ Adds the \a path for deletetion. Unlike files for delayed deletion, which are deleted
+ on the start of next installer run, these paths are deleted on exit.
+*/
+void PackageManagerCorePrivate::addPathForDeletion(const QString &path)
+{
+ m_tmpPathDeleter.add(path);
+}
+
+void PackageManagerCorePrivate::unpackAndInstallComponents(const QList<Component *> &components,
+ const double progressOperationSize)
+{
+ // Perform extract operations
+ unpackComponents(components, progressOperationSize);
+
+ // Perform rest of the operations and mark component as installed
+ const int componentsToInstallCount = components.size();
+ int installedComponents = 0;
+ foreach (Component *component, components) {
+ installComponent(component, progressOperationSize);
+
+ ++installedComponents;
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(tr("%1 of %2 components installed.")
+ .arg(QString::number(installedComponents), QString::number(componentsToInstallCount)));
+ }
+ ProgressCoordinator::instance()->emitAdditionalProgressStatus(tr("All components installed."));
+}
+
void PackageManagerCorePrivate::processFilesForDelayedDeletion()
{
if (m_filesForDelayedDeletion.isEmpty())
@@ -2735,36 +3260,24 @@ void PackageManagerCorePrivate::processFilesForDelayedDeletion()
}
}
-void PackageManagerCorePrivate::findExecutablesRecursive(const QString &path, const QStringList &excludeFiles, QStringList *result)
-{
- QDirIterator it(path, QDir::NoDotAndDotDot | QDir::Executable | QDir::Files | QDir::System, QDirIterator::Subdirectories );
-
- while (it.hasNext())
- result->append(QDir::toNativeSeparators(it.next().toLower()));
-
- foreach (const QString &process, excludeFiles)
- result->removeAll(QDir::toNativeSeparators(process.toLower()));
-}
-
-QStringList PackageManagerCorePrivate::runningInstallerProcesses(const QStringList &excludeFiles)
-{
- QStringList resultFiles;
- findExecutablesRecursive(QCoreApplication::applicationDirPath(), excludeFiles, &resultFiles);
- return checkRunningProcessesFromList(resultFiles);
-}
-
bool PackageManagerCorePrivate::calculateComponentsAndRun()
{
- QString htmlOutput;
- bool componentsOk = m_core->calculateComponents(&htmlOutput);
+ bool componentsOk = m_core->recalculateAllComponents();
+
if (statusCanceledOrFailed()) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Installation canceled.";
} else if (componentsOk && acceptLicenseAgreements()) {
- qCDebug(QInstaller::lcInstallerInstallLog).noquote() << htmlToString(htmlOutput);
+ try {
+ loadComponentScripts(installerCalculator()->resolvedComponents(), true);
+ } catch (const Error &error) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << error.message();
+ return false;
+ }
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote()
+ << htmlToString(m_core->componentResolveReasons());
- QString spaceInfo;
- const bool spaceOk = m_core->checkAvailableSpace(spaceInfo);
- qCDebug(QInstaller::lcInstallerInstallLog) << spaceInfo;
+ const bool spaceOk = m_core->checkAvailableSpace();
+ qCDebug(QInstaller::lcInstallerInstallLog) << m_core->availableSpaceMessage();
if (!spaceOk || !(m_autoConfirmCommand || askUserConfirmCommand())) {
qCDebug(QInstaller::lcInstallerInstallLog) << "Installation aborted.";
@@ -2791,6 +3304,13 @@ bool PackageManagerCorePrivate::acceptLicenseAgreements() const
m_core->addLicenseItem(component->licenses());
}
+ const QString acceptanceText = ProductKeyCheck::instance()->licenseAcceptanceText();
+ if (!acceptanceText.isEmpty()) {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote() << acceptanceText;
+ if (!m_autoAcceptLicenses && !acceptRejectCliQuery())
+ return false;
+ }
+
QHash<QString, QMap<QString, QString>> priorityHash = m_core->sortedLicenses();
QStringList priorities = priorityHash.keys();
priorities.sort();
@@ -2839,6 +3359,23 @@ bool PackageManagerCorePrivate::askUserAcceptLicense(const QString &name, const
}
}
+bool PackageManagerCorePrivate::acceptRejectCliQuery() const
+{
+ forever {
+ const QString input = m_core->readConsoleLine(QLatin1String("Accept|Reject"));
+
+ if (QString::compare(input, QLatin1String("Accept"), Qt::CaseInsensitive) == 0
+ || QString::compare(input, QLatin1String("A"), Qt::CaseInsensitive) == 0) {
+ return true;
+ } else if (QString::compare(input, QLatin1String("Reject"), Qt::CaseInsensitive) == 0
+ || QString::compare(input, QLatin1String("R"), Qt::CaseInsensitive) == 0) {
+ return false;
+ } else {
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Unknown answer:" << input;
+ }
+ }
+}
+
bool PackageManagerCorePrivate::askUserConfirmCommand() const
{
qCDebug(QInstaller::lcInstallerInstallLog) << "Do you want to continue?";
@@ -2873,4 +3410,60 @@ bool PackageManagerCorePrivate::packageNeedsUpdate(const LocalPackage &localPack
return updateNeeded;
}
+void PackageManagerCorePrivate::commitPendingUnstableComponents()
+{
+ if (m_pendingUnstableComponents.isEmpty())
+ return;
+
+ for (auto &componentName : m_pendingUnstableComponents.keys()) {
+ Component *const component = m_core->componentByName(componentName);
+ if (!component) {
+ qCWarning(lcInstallerInstallLog) << "Failure while marking component "
+ "unstable. No such component exists:" << componentName;
+ continue;
+ }
+
+ const QPair<Component::UnstableError, QString> unstableError
+ = m_pendingUnstableComponents.value(componentName);
+
+ component->setUnstable(unstableError.first, unstableError.second);
+ }
+ m_pendingUnstableComponents.clear();
+}
+
+void PackageManagerCorePrivate::createAutoDependencyHash(const QString &component, const QString &oldDependencies, const QString &newDependencies)
+{
+ // User might have changed autodependencies with setValue. Remove the old values.
+ const QStringList oldDependencyList = oldDependencies.split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+ for (const QString &removedDependency : oldDependencyList) {
+ QStringList value = m_autoDependencyComponentHash.value(removedDependency);
+ value.removeAll(component);
+ if (value.isEmpty())
+ m_autoDependencyComponentHash.remove(removedDependency);
+ else
+ m_autoDependencyComponentHash.insert(removedDependency, value);
+ }
+
+ const QStringList newDependencyList = newDependencies.split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+ for (const QString &autodepend : newDependencyList) {
+ QStringList value = m_autoDependencyComponentHash.value(autodepend);
+ if (!value.contains(component)) {
+ value.append(component);
+ m_autoDependencyComponentHash.insert(autodepend, value);
+ }
+ }
+}
+
+void PackageManagerCorePrivate::createLocalDependencyHash(const QString &component, const QString &dependencies)
+{
+ const QStringList localDependencies = dependencies.split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
+ for (const QString &depend : localDependencies) {
+ QStringList value = m_localDependencyComponentHash.value(depend);
+ if (!value.contains(component)) {
+ value.append(component);
+ m_localDependencyComponentHash.insert(depend, value);
+ }
+ }
+}
+
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 65f0e43eb..c0c55c4cc 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -35,6 +35,8 @@
#include "packagemanagerproxyfactory.h"
#include "packagesource.h"
#include "qinstallerglobal.h"
+#include "component.h"
+#include "fileutils.h"
#include "sysinfo.h"
#include "updatefinder.h"
@@ -52,13 +54,15 @@ using namespace KDUpdater;
namespace QInstaller {
struct BinaryLayout;
-class Component;
+struct AliasSource;
+class AliasFinder;
class ScriptEngine;
class ComponentModel;
-class TempDirDeleter;
+class ComponentAlias;
class InstallerCalculator;
class UninstallerCalculator;
class RemoteFileEngineHandler;
+class ComponentSortFilterProxyModel;
class PackageManagerCorePrivate : public QObject
{
@@ -69,7 +73,7 @@ class PackageManagerCorePrivate : public QObject
public:
explicit PackageManagerCorePrivate(PackageManagerCore *core);
explicit PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
- const QList<OperationBlob> &performedOperations);
+ const QList<OperationBlob> &performedOperations, const QString &datFileName);
~PackageManagerCorePrivate();
static bool isProcessRunning(const QString &name, const QList<ProcessInfo> &processes);
@@ -89,8 +93,10 @@ public:
bool directoryWritable(const QString &path) const;
QString maintenanceToolName() const;
+ QString maintenanceToolAliasPath() const;
QString installerBinaryPath() const;
QString offlineBinaryName() const;
+ QString datFileName();
void writeMaintenanceConfigFiles();
void readMaintenanceConfigFiles(const QString &targetDir);
@@ -98,10 +104,16 @@ public:
void writeMaintenanceTool(OperationList performedOperations);
void writeOfflineBaseBinary();
+ void writeMaintenanceToolAlias(const QString &maintenanceToolName);
+
QString componentsXmlPath() const;
QString configurationFileName() const;
bool buildComponentTree(QHash<QString, Component*> &components, bool loadScript);
+ bool buildComponentAliases();
+
+ template <typename T>
+ bool loadComponentScripts(const T &components, const bool postScript = false);
void cleanUpComponentEnvironment();
ScriptEngine *componentScriptEngine() const;
@@ -111,6 +123,7 @@ public:
void clearUpdaterComponentLists();
QList<Component*> &replacementDependencyComponents();
QHash<QString, QPair<Component*, Component*> > &componentsToReplace();
+ QHash<QString, QStringList > &componentReplaces();
void clearInstallerCalculator();
InstallerCalculator *installerCalculator() const;
@@ -161,10 +174,11 @@ public:
m_performedOperationsCurrentSession.clear();
}
- void installComponent(Component *component, double progressOperationSize,
- bool adminRightsGained = false);
+ void unpackComponents(const QList<Component *> &components, double progressOperationSize);
+
+ void installComponent(Component *component, double progressOperationSize);
+ PackageManagerCore::Status fetchComponentsAndInstall(const QStringList& components);
- bool runningProcessesFound();
void setComponentSelection(const QString &id, Qt::CheckState state);
signals:
@@ -177,8 +191,10 @@ signals:
public:
UpdateFinder *m_updateFinder;
+ AliasFinder *m_aliasFinder;
QSet<PackageSource> m_packageSources;
QSet<PackageSource> m_compressedPackageSources;
+ QSet<AliasSource> m_aliasSources;
std::shared_ptr<LocalPackageHub> m_localPackageHub;
QStringList m_filesForDelayedDeletion;
@@ -206,6 +222,8 @@ public:
QList<QInstaller::Component*> m_updaterComponentsDeps;
QList<QInstaller::Component*> m_updaterDependencyReplacements;
+ QHash<QString, QInstaller::ComponentAlias *> m_componentAliases;
+
OperationList m_ownedOperations;
OperationList m_performedOperationsOld;
OperationList m_performedOperationsCurrentSession;
@@ -229,44 +247,65 @@ private slots:
}
void handleMethodInvocationRequest(const QString &invokableMethodName);
+ void addPathForDeletion(const QString &path);
private:
+ void unpackAndInstallComponents(const QList<Component *> &components,
+ const double progressOperationSize);
+
void deleteMaintenanceTool();
+ void deleteMaintenanceToolAlias();
void registerMaintenanceTool();
void unregisterMaintenanceTool();
void writeMaintenanceToolBinary(QFile *const input, qint64 size, bool writeBinaryLayout);
void writeMaintenanceToolBinaryData(QFileDevice *output, QFile *const input,
const OperationList &performed, const BinaryLayout &layout);
+ void writeMaintenanceToolAppBundle(OperationList &performedOperations);
void runUndoOperations(const OperationList &undoOperations, double undoOperationProgressSize,
- bool adminRightsGained, bool deleteOperation);
+ bool deleteOperation);
PackagesList remotePackages();
- LocalPackagesHash localInstalledPackages();
+ LocalPackagesMap localInstalledPackages();
+ QList<ComponentAlias *> componentAliases();
+
bool fetchMetaInformationFromRepositories(DownloadType type = DownloadType::All);
- bool addUpdateResourcesFromRepositories(bool parseChecksum, bool compressedRepository = false);
+ bool addUpdateResourcesFromRepositories(bool compressedRepository = false);
void processFilesForDelayedDeletion();
- void findExecutablesRecursive(const QString &path, const QStringList &excludeFiles, QStringList *result);
- QStringList runningInstallerProcesses(const QStringList &exludeFiles);
bool calculateComponentsAndRun();
bool acceptLicenseAgreements() const;
bool askUserAcceptLicense(const QString &name, const QString &content) const;
+ bool acceptRejectCliQuery() const;
bool askUserConfirmCommand() const;
bool packageNeedsUpdate(const LocalPackage &localPackage, const Package *update) const;
+ void commitPendingUnstableComponents();
+ void createAutoDependencyHash(const QString &componentName, const QString &oldValue, const QString &newValue);
+ void createLocalDependencyHash(const QString &componentName, const QString &dependencies);
+ void updateComponentInstallActions();
+
+ bool enableAllCategories();
+ void enableRepositoryCategory(const RepositoryCategory &repoCategory, const bool enable);
+
+ bool installablePackagesFound(const QStringList& components);
+
+ // remove once we deprecate isSelected, setSelected etc...
+ void restoreCheckState();
+ void storeCheckState();
private:
PackageManagerCore *m_core;
MetadataJob m_metadataJob;
+ TempPathDeleter m_tmpPathDeleter;
bool m_updates;
+ bool m_aliases;
bool m_repoFetched;
bool m_updateSourcesAdded;
qint64 m_magicBinaryMarker;
int m_magicMarkerSupplement;
- bool m_componentsToInstallCalculated;
- bool m_foundEssentialUpdate;;
+ bool m_foundEssentialUpdate;
mutable ScriptEngine *m_componentScriptEngine;
mutable ScriptEngine *m_controlScriptEngine;
@@ -274,6 +313,8 @@ private:
QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceAllMode;
QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceUpdaterMode;
+ QHash<QString, QPair<Component::UnstableError, QString>> m_pendingUnstableComponents;
+
InstallerCalculator *m_installerCalculator;
UninstallerCalculator *m_uninstallerCalculator;
@@ -281,16 +322,26 @@ private:
ComponentModel *m_defaultModel;
ComponentModel *m_updaterModel;
+ ComponentSortFilterProxyModel *m_componentSortFilterProxyModel;
QObject *m_guiObject;
QScopedPointer<RemoteFileEngineHandler> m_remoteFileEngineHandler;
QHash<QString, QVariantMap> m_licenseItems;
-private:
- // remove once we deprecate isSelected, setSelected etc...
- void restoreCheckState();
- void storeCheckState();
QHash<Component*, Qt::CheckState> m_coreCheckedHash;
+ QList<Component*> m_deletedReplacedComponents;
+ AutoDependencyHash m_autoDependencyComponentHash;
+ LocalDependencyHash m_localDependencyComponentHash;
+ QHash<QString, Component *> m_componentByNameHash;
+
+ QStringList m_localVirtualComponents;
+
+ // < name (component replacing others), components to replace>
+ QHash<QString, QStringList > m_componentReplaces;
+
+ QString m_datFileName;
+ bool m_allowCompressedRepositoryInstall;
+ int m_connectedOperations;
};
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index 58782c03f..1113908bd 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -34,7 +34,9 @@
#include <QDesktopServices>
#include <QDir>
-#include <QRegExp>
+#include <QRegularExpression>
+#include <QSettings>
+#include <QStandardPaths>
#ifdef Q_OS_WIN
# include <windows.h>
@@ -76,7 +78,7 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
// fill the variables defined in the settings
addNewVariable(QLatin1String("ProductName"), m_settings.applicationName());
- addNewVariable(QLatin1String("ProductVersion"), m_settings.version());
+ addNewVariable(QLatin1String("ProductVersion"), replaceVariables(m_settings.version()));
addNewVariable(scTitle, replaceVariables(m_settings.title()));
addNewVariable(scPublisher, m_settings.publisher());
addNewVariable(QLatin1String("Url"), m_settings.url());
@@ -94,7 +96,7 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
if (isInstaller) {
addNewVariable(scTargetDir, replaceVariables(m_settings.targetDir()));
addNewVariable(scTargetConfigurationFile, m_settings.configurationFileName());
- addNewVariable(scStartMenuDir, m_settings.startMenuDir());
+ addNewVariable(scStartMenuDir, replaceVariables(m_settings.startMenuDir()));
} else {
#ifdef Q_OS_MACOS
addNewVariable(scTargetDir, QFileInfo(QCoreApplication::applicationDirPath() + QLatin1String("/../../..")).absoluteFilePath());
@@ -129,7 +131,9 @@ void PackageManagerCoreData::addDynamicPredefinedVariables()
SHGetFolderPath(nullptr, CSIDL_PROGRAM_FILES, nullptr, 0, buffer);
dir = QString::fromWCharArray(buffer);
#elif defined (Q_OS_MACOS)
- dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0);
+ dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(1);
+ if (dir.isEmpty())
+ dir = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).value(0);
#endif
addNewVariable(QLatin1String("ApplicationsDir"), dir);
@@ -143,7 +147,7 @@ void PackageManagerCoreData::addDynamicPredefinedVariables()
QString dirX64 = dir;
#ifdef Q_OS_WIN
QSettingsWrapper current(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion")
- , QSettingsWrapper::NativeFormat);
+ , QSettings::NativeFormat);
BOOL onWow64Or64bit = TRUE;
#ifndef Q_OS_WIN64
IsWow64Process(GetCurrentProcess(), &onWow64Or64bit);
@@ -165,9 +169,9 @@ void PackageManagerCoreData::addDynamicPredefinedVariables()
#ifdef Q_OS_WIN
QSettingsWrapper user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\User Shell Folders"), QSettingsWrapper::NativeFormat);
+ "CurrentVersion\\Explorer\\User Shell Folders"), QSettings::NativeFormat);
QSettingsWrapper system(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\Shell Folders"), QSettingsWrapper::NativeFormat);
+ "CurrentVersion\\Explorer\\Shell Folders"), QSettings::NativeFormat);
const QString programs = user.value(QLatin1String("Programs"), QString()).toString();
const QString allPrograms = system.value(QLatin1String("Common Programs"), QString())
@@ -230,7 +234,7 @@ bool PackageManagerCoreData::setValue(const QString &key, const QString &normali
return true;
}
-QVariant PackageManagerCoreData::value(const QString &key, const QVariant &_default) const
+QVariant PackageManagerCoreData::value(const QString &key, const QVariant &_default, const QSettings::Format &format) const
{
if (key == scTargetDir) {
QString dir = m_variables.value(key);
@@ -247,13 +251,15 @@ QVariant PackageManagerCoreData::value(const QString &key, const QVariant &_defa
#ifdef Q_OS_WIN
if (!m_variables.contains(key)) {
- static const QRegExp regex(QLatin1String("\\\\|/"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/"));
const QString filename = key.section(regex, 0, -2);
const QString regKey = key.section(regex, -1);
- const QSettingsWrapper registry(filename, QSettingsWrapper::NativeFormat);
+ const QSettingsWrapper registry(filename, format);
if (!filename.isEmpty() && !regKey.isEmpty() && registry.contains(regKey))
return registry.value(regKey).toString();
}
+#else
+ Q_UNUSED(format)
#endif
if (m_variables.contains(key))
@@ -290,7 +296,7 @@ QString PackageManagerCoreData::replaceVariables(const QString &str) const
QByteArray PackageManagerCoreData::replaceVariables(const QByteArray &ba) const
{
- static const QChar at = QLatin1Char('@');
+ static const char at = '@';
QByteArray res;
int pos = 0;
while (true) {
diff --git a/src/libs/installer/packagemanagercoredata.h b/src/libs/installer/packagemanagercoredata.h
index 3cfb77c95..2dcddf102 100644
--- a/src/libs/installer/packagemanagercoredata.h
+++ b/src/libs/installer/packagemanagercoredata.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,6 +30,7 @@
#define PACKAGEMANAGERCOREDATA_H
#include "settings.h"
+#include <QSettings>
namespace QInstaller {
@@ -53,7 +54,7 @@ public:
bool contains(const QString &key) const;
bool setValue(const QString &key, const QString &normalizedValue);
- QVariant value(const QString &key, const QVariant &_default = QVariant()) const;
+ QVariant value(const QString &key, const QVariant &_default = QVariant(), const QSettings::Format &format = QSettings::NativeFormat) const;
QString key(const QString &value) const;
QString replaceVariables(const QString &str) const;
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 67a2123af..1f0462eea 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -54,6 +54,7 @@
#include <QtCore/QTimer>
#include <QAbstractItemView>
+#include <QAction>
#include <QCheckBox>
#include <QComboBox>
#include <QDesktopServices>
@@ -64,6 +65,8 @@
#include <QLineEdit>
#include <QListWidget>
#include <QListWidgetItem>
+#include <QMenuBar>
+#include <QMenu>
#include <QMessageBox>
#include <QProgressBar>
#include <QPushButton>
@@ -71,18 +74,21 @@
#include <QSplitter>
#include <QStringListModel>
#include <QTextBrowser>
+#include <QFontDatabase>
#include <QVBoxLayout>
#include <QShowEvent>
#include <QFileDialog>
#include <QGroupBox>
-#include <QDesktopWidget>
+#include <QScreen>
#ifdef Q_OS_WIN
# include <qt_windows.h>
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QWinTaskbarButton>
# include <QWinTaskbarProgress>
#endif
+#endif
using namespace KDUpdater;
using namespace QInstaller;
@@ -125,7 +131,7 @@ public:
return m_widget;
}
- bool isComplete() const Q_DECL_OVERRIDE
+ bool isComplete() const override
{
return m_widget->property("complete").toBool();
}
@@ -206,8 +212,9 @@ Q_DECLARE_METATYPE(DynamicInstallerPage*)
class PackageManagerGui::Private
{
public:
- Private()
- : m_currentId(-1)
+ Private(PackageManagerGui *qq)
+ : q(qq)
+ , m_currentId(-1)
, m_modified(false)
, m_autoSwitchPage(true)
, m_showSettingsButton(false)
@@ -231,6 +238,20 @@ public:
QLatin1String("unknown button"));
}
+ void showSettingsButton(bool show)
+ {
+ if (m_showSettingsButton == show)
+ return;
+ q->setOption(QWizard::HaveCustomButton1, show);
+ q->setButtonText(QWizard::CustomButton1, tr("&Settings"));
+ q->button(QWizard::CustomButton1)->setToolTip(
+ PackageManagerGui::tr("Specify proxy settings and configure repositories for add-on components."));
+
+ q->updateButtonLayout();
+ m_showSettingsButton = show;
+ }
+
+ PackageManagerGui *q;
int m_currentId;
bool m_modified;
bool m_autoSwitchPage;
@@ -279,6 +300,11 @@ public:
*/
/*!
+ \fn void QInstaller::PackageManagerGui::aboutApplicationClicked()
+ \sa {gui::aboutApplicationClicked}{gui.aboutApplicationClicked}
+*/
+
+/*!
\fn void QInstaller::PackageManagerGui::packageManagerCore() const
Returns the package manager core.
@@ -290,7 +316,7 @@ public:
*/
PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
: QWizard(parent)
- , d(new Private)
+ , d(new Private(this))
, m_core(core)
{
if (m_core->isInstaller())
@@ -299,7 +325,17 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
setWindowTitle(tr("Maintain %1").arg(m_core->value(scTitle)));
setWindowFlags(windowFlags() &~ Qt::WindowContextHelpButtonHint);
-#ifndef Q_OS_MACOS
+#ifdef Q_OS_MACOS
+ QMenuBar *menuBar = new QMenuBar(this);
+ QMenu *applicationMenu = new QMenu(menuBar);
+ menuBar->addMenu(applicationMenu);
+
+ QAction *aboutAction = new QAction(applicationMenu);
+ aboutAction->setMenuRole(QAction::AboutRole);
+ applicationMenu->addAction(aboutAction);
+
+ connect(aboutAction, &QAction::triggered, this, &PackageManagerGui::aboutApplicationClicked);
+#else
setWindowIcon(QIcon(m_core->settings().installerWindowIcon()));
#endif
if (!m_core->settings().wizardShowPageList()) {
@@ -334,6 +370,11 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
setOption(QWizard::NoBackButtonOnStartPage);
setOption(QWizard::NoBackButtonOnLastPage);
+#ifdef Q_OS_MACOS
+ setOptions(options() & ~QWizard::NoDefaultButton);
+ if (QPushButton *nextButton = qobject_cast<QPushButton *>(button(QWizard::NextButton)))
+ nextButton->setFocusPolicy(Qt::StrongFocus);
+#endif
if (m_core->settings().wizardShowPageList()) {
QWidget *sideWidget = new QWidget(this);
@@ -349,6 +390,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
m_pageListWidget->setFocusPolicy(Qt::NoFocus);
m_pageListWidget->setSelectionMode(QAbstractItemView::NoSelection);
m_pageListWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ m_pageListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QVBoxLayout *sideWidgetLayout = new QVBoxLayout(sideWidget);
@@ -370,10 +412,13 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
connect(this, &QDialog::rejected, m_core, &PackageManagerCore::setCanceled);
connect(this, &PackageManagerGui::interrupted, m_core, &PackageManagerCore::interrupt);
- // both queued to show the finished page once everything is done
+ // all queued to show the finished page once everything is done
connect(m_core, &PackageManagerCore::installationFinished,
this, &PackageManagerGui::showFinishedPage,
Qt::QueuedConnection);
+ connect(m_core, &PackageManagerCore::offlineGenerationFinished,
+ this, &PackageManagerGui::showFinishedPage,
+ Qt::QueuedConnection);
connect(m_core, &PackageManagerCore::uninstallationFinished,
this, &PackageManagerGui::showFinishedPage,
Qt::QueuedConnection);
@@ -426,7 +471,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
*/
void PackageManagerGui::setMaxSize()
{
- QSize size = qApp->desktop()->availableGeometry(this).size();
+ QSize size = this->screen()->availableGeometry().size();
int windowFrameHeight = frameGeometry().height() - geometry().height();
int availableHeight = size.height() - windowFrameHeight;
@@ -469,7 +514,7 @@ void PackageManagerGui::updatePageListWidget()
itemText.replace(regExp2, QLatin1String("\\1 \\2"));
}
QListWidgetItem *item = new QListWidgetItem(itemText, m_pageListWidget);
- item->setSizeHint(QSize(item->sizeHint().width(), 30));
+ item->setSizeHint(QSize(m_pageListWidget->width(), 30));
// Give visual indication about current & non-visited pages
if (id == d->m_currentId) {
@@ -478,7 +523,7 @@ void PackageManagerGui::updatePageListWidget()
item->setFont(currentItemFont);
// Current item should be always visible on the list
m_pageListWidget->scrollToItem(item);
- } else if (id > d->m_currentId) {
+ } else {
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
}
}
@@ -647,6 +692,22 @@ bool PackageManagerGui::isButtonEnabled(int wb)
}
/*!
+ Sets \a buttonText for button specified by \a buttonId to a installer page \a pageId.
+
+ \note In some pages, installer will change the button text when entering
+ the page. In that case, you need to connect to \c entered() -signal of the
+ page to change the \a buttonText.
+
+ \sa {gui::setWizardPageButtonText}{gui.setWizardPageButtonText}
+*/
+void PackageManagerGui::setWizardPageButtonText(int pageId, int buttonId, const QString &buttonText)
+{
+ PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (page(pageId));
+ if (p)
+ p->setButtonText(static_cast<QWizard::WizardButton>(buttonId), buttonText);
+}
+
+/*!
Sets a validator for the custom page specified by \a name and
\a callbackName requested by \a component.
*/
@@ -1009,16 +1070,18 @@ void PackageManagerGui::showFinishedPage()
*/
void PackageManagerGui::showSettingsButton(bool show)
{
- if (d->m_showSettingsButton == show)
- return;
-
- d->m_showSettingsButton = show;
- setOption(QWizard::HaveCustomButton1, show);
- setButtonText(QWizard::CustomButton1, tr("Settings"));
- button(QWizard::CustomButton1)->setToolTip(
- PackageManagerGui::tr("Specify proxy settings and configure repositories for add-on components."));
+ m_core->setValue(QLatin1String("ShowSettingsButton"), QString::number(show));
+ d->showSettingsButton(show);
+}
- updateButtonLayout();
+/*!
+ Shows the \uicontrol Settings button if \a request is \c true. If script has
+ set the settings button visibility, this function has no effect.
+*/
+void PackageManagerGui::requestSettingsButtonByInstaller(bool request)
+{
+ if (m_core->value(QLatin1String("ShowSettingsButton")).isEmpty())
+ d->showSettingsButton(request);
}
/*!
@@ -1201,10 +1264,10 @@ void PackageManagerGui::currentPageChanged(int newId)
PackageManagerPage::PackageManagerPage(PackageManagerCore *core)
: m_complete(true)
, m_titleColor(QString())
+ , m_showOnPageList(true)
, m_needsSettingsButton(false)
, m_core(core)
, validatorComponent(nullptr)
- , m_showOnPageList(true)
{
if (!m_core->settings().titleColor().isEmpty())
m_titleColor = m_core->settings().titleColor();
@@ -1268,7 +1331,7 @@ QString PackageManagerPage::productName() const
*/
void PackageManagerPage::setColoredTitle(const QString &title)
{
- setTitle(QString::fromLatin1("<font color=\"%1\">%2</font>").arg(m_titleColor, title));
+ setTitle(QString::fromLatin1("<center><font color=\"%1\">%2</font></center>").arg(m_titleColor, title));
}
/*!
@@ -1276,7 +1339,7 @@ void PackageManagerPage::setColoredTitle(const QString &title)
*/
void PackageManagerPage::setColoredSubTitle(const QString &subTitle)
{
- setSubTitle(QString::fromLatin1("<font color=\"%1\">%2</font>").arg(m_titleColor, subTitle));
+ setSubTitle(QString::fromLatin1("<center><font color=\"%1\">%2</font></center>").arg(m_titleColor, subTitle));
}
/*!
@@ -1333,12 +1396,8 @@ void PackageManagerPage::setComplete(bool complete)
{
m_complete = complete;
if (QWizard *w = wizard()) {
- if (QAbstractButton *cancel = w->button(QWizard::CancelButton)) {
- if (cancel->hasFocus()) {
- if (QAbstractButton *next = w->button(QWizard::NextButton))
- next->setFocus();
- }
- }
+ if (QAbstractButton *nextButton = w->button(QWizard::NextButton))
+ nextButton->setFocus();
}
emit completeChanged();
}
@@ -1412,20 +1471,12 @@ int PackageManagerPage::nextId() const
if (next == PackageManagerCore::LicenseCheck) {
// calculate the page after the license page
const int nextNextId = gui()->pageIds().value(gui()->pageIds().indexOf(next) + 1, -1);
- const PackageManagerCore *const core = packageManagerCore();
+ PackageManagerCore *const core = packageManagerCore();
if (core->isUninstaller())
return nextNextId; // forcibly hide the license page if we run as uninstaller
-
- core->calculateComponentsToInstall();
- foreach (Component* component, core->orderedComponentsToInstall()) {
- if (core->isMaintainer() && component->isInstalled())
- continue; // package manager or updater, hide as long as the component is installed
-
- // The component is about to be installed and provides a license, so the page needs to
- // be shown.
- if (!component->licenses().isEmpty())
- return next;
- }
+ core->recalculateAllComponents();
+ if (core->hasLicenses())
+ return next;
return nextNextId; // no component with a license or all components with license installed
}
return next; // default, show the next page
@@ -1453,6 +1504,8 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
: PackageManagerPage(core)
, m_updatesFetched(false)
, m_allPackagesFetched(false)
+ , m_forceUpdate(false)
+ , m_offlineMaintenanceTool(false)
, m_label(nullptr)
, m_msgLabel(nullptr)
, m_errorLabel(nullptr)
@@ -1462,7 +1515,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
, m_removeAllComponents(nullptr)
{
setObjectName(QLatin1String("IntroductionPage"));
- setColoredTitle(tr("Setup - %1").arg(productName()));
+ setColoredTitle(tr("Welcome"));
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
@@ -1470,7 +1523,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_msgLabel = new QLabel(this);
m_msgLabel->setWordWrap(true);
m_msgLabel->setObjectName(QLatin1String("MessageLabel"));
- m_msgLabel->setText(tr("Welcome to the %1 Setup Wizard.").arg(productName()));
+ m_msgLabel->setText(tr("Welcome to the %1 Setup.").arg(productName()));
QWidget *widget = new QWidget(this);
QVBoxLayout *boxLayout = new QVBoxLayout(widget);
@@ -1510,6 +1563,8 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_errorLabel = new QLabel(this);
m_errorLabel->setWordWrap(true);
+ m_errorLabel->setTextFormat(Qt::RichText);
+ m_errorLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
boxLayout->addWidget(m_errorLabel);
m_errorLabel->setObjectName(QLatin1String("ErrorLabel"));
@@ -1523,9 +1578,10 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
connect(core, &PackageManagerCore::coreNetworkSettingsChanged,
this, &IntroductionPage::onCoreNetworkSettingsChanged);
- m_updateComponents->setEnabled(ProductKeyCheck::instance()->hasValidKey());
+ m_updateComponents->setEnabled(!m_offlineMaintenanceTool && ProductKeyCheck::instance()->hasValidKey());
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
m_taskButton = new QWinTaskbarButton(this);
connect(core, &PackageManagerCore::metaJobProgress,
@@ -1534,6 +1590,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_taskButton = nullptr;
}
#endif
+#endif
}
/*!
@@ -1560,9 +1617,11 @@ bool IntroductionPage::validatePage()
return true;
setComplete(false);
+ setErrorMessage(QString());
+
bool isOfflineOnlyInstaller = core->isInstaller() && core->isOfflineOnly();
// If not offline only installer, at least one valid repository needs to be available
- if (!isOfflineOnlyInstaller && !validRepositoriesAvailable()) {
+ if (!isOfflineOnlyInstaller && !core->validRepositoriesAvailable()) {
setErrorMessage(QLatin1String("<font color=\"red\">") + tr("At least one valid and enabled "
"repository required for this action to succeed.") + QLatin1String("</font>"));
return isComplete();
@@ -1577,6 +1636,7 @@ bool IntroductionPage::validatePage()
}
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0 ,0)
if (m_taskButton) {
if (!m_taskButton->window()) {
if (QWidget *widget = QApplication::activeWindow())
@@ -1588,6 +1648,7 @@ bool IntroductionPage::validatePage()
m_taskButton->progress()->setVisible(true);
}
#endif
+#endif
// fetch updater packages
if (core->isUpdater()) {
@@ -1607,30 +1668,30 @@ bool IntroductionPage::validatePage()
// fetch common packages
if (core->isInstaller() || core->isPackageManager()) {
- bool localPackagesTreeFetched = false;
if (!m_allPackagesFetched) {
// first try to fetch the server side packages tree
m_allPackagesFetched = core->fetchRemotePackagesTree();
if (!m_allPackagesFetched) {
QString error = core->error();
- if (core->isPackageManager() && core->status() != PackageManagerCore::ForceUpdate) {
- // if that fails and we're in maintenance mode, try to fetch local installed tree
- localPackagesTreeFetched = core->fetchLocalPackagesTree();
- if (localPackagesTreeFetched) {
- // if that succeeded, adjust error message
- error = QLatin1String("<font color=\"red\">") + error + tr(" Only local package "
- "management available.") + QLatin1String("</font>");
- }
- } else if (core->status() == PackageManagerCore::ForceUpdate) {
+ if (core->status() == PackageManagerCore::ForceUpdate) {
// replaces the error string from packagemanagercore
error = tr("There is an important update available. Please select '%1' first")
.arg(m_updateComponents->text().remove(QLatin1Char('&')));
+
+ m_forceUpdate = true;
+ // Don't call these directly. Need to finish the current validation first,
+ // because changing the selection updates the binary marker and resets the
+ // complete -state of the page.
+ QMetaObject::invokeMethod(m_updateComponents, "setChecked",
+ Qt::QueuedConnection, Q_ARG(bool, true));
+ QMetaObject::invokeMethod(this, "setErrorMessage",
+ Qt::QueuedConnection, Q_ARG(QString, error));
}
setErrorMessage(error);
}
}
- if (m_allPackagesFetched || localPackagesTreeFetched)
+ if (m_allPackagesFetched)
setComplete(true);
}
@@ -1643,9 +1704,11 @@ bool IntroductionPage::validatePage()
gui()->setSettingsButtonEnabled(true);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton)
m_taskButton->progress()->setVisible(!isComplete());
#endif
+#endif
return isComplete();
}
@@ -1687,15 +1750,41 @@ void IntroductionPage::showMaintenanceTools()
/*!
Sets \a enable to \c true to enable the options to install, add, and
- uninstall components on the page.
+ uninstall components on the page. For a maintenance tool without any enabled
+ repositories, the package manager and updater stay disabled regardless of
+ the value of \a enable.
*/
void IntroductionPage::setMaintenanceToolsEnabled(bool enable)
{
- m_packageManager->setEnabled(enable);
- m_updateComponents->setEnabled(enable && ProductKeyCheck::instance()->hasValidKey());
+ m_packageManager->setEnabled(enable && !m_offlineMaintenanceTool);
+ m_updateComponents->setEnabled(enable && !m_offlineMaintenanceTool
+ && ProductKeyCheck::instance()->hasValidKey());
m_removeAllComponents->setEnabled(enable);
}
+/*!
+ Enables or disables the options to add or update components based on the
+ value of \a enable. For a maintenance tool without any enabled repositories,
+ the package manager and updater stay disabled regardless of the value of \a enable.
+*/
+void IntroductionPage::setMaintainerToolsEnabled(bool enable)
+{
+ m_packageManager->setEnabled(enable && !m_offlineMaintenanceTool);
+ m_updateComponents->setEnabled(enable && !m_offlineMaintenanceTool
+ && ProductKeyCheck::instance()->hasValidKey());
+}
+
+/*!
+ Resets the internal page state, so that on clicking \uicontrol Next the metadata needs to be
+ fetched again.
+*/
+void IntroductionPage::resetFetchedState()
+{
+ m_updatesFetched = false;
+ m_allPackagesFetched = false;
+ m_forceUpdate = false;
+}
+
// -- public slots
/*!
@@ -1740,29 +1829,15 @@ void IntroductionPage::setErrorMessage(const QString &error)
m_errorLabel->setPalette(palette);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton) {
m_taskButton->progress()->stop();
m_taskButton->progress()->setValue(100);
}
#endif
+#endif
}
-/*!
- Returns \c true if at least one valid and enabled repository is available.
-*/
-bool IntroductionPage::validRepositoriesAvailable() const
-{
- const PackageManagerCore *const core = packageManagerCore();
- bool valid = false;
-
- foreach (const Repository &repo, core->settings().repositories()) {
- if (repo.isEnabled() && repo.isValid()) {
- valid = true;
- break;
- }
- }
- return valid;
-}
// -- private slots
@@ -1770,7 +1845,7 @@ void IntroductionPage::setUpdater(bool value)
{
if (value) {
entering();
- gui()->showSettingsButton(true);
+ gui()->requestSettingsButtonByInstaller(true);
packageManagerCore()->setUpdater();
emit packageManagerCoreTypeChanged();
@@ -1782,7 +1857,7 @@ void IntroductionPage::setUninstaller(bool value)
{
if (value) {
entering();
- gui()->showSettingsButton(false);
+ gui()->requestSettingsButtonByInstaller(true);
packageManagerCore()->setUninstaller();
emit packageManagerCoreTypeChanged();
@@ -1794,7 +1869,7 @@ void IntroductionPage::setPackageManager(bool value)
{
if (value) {
entering();
- gui()->showSettingsButton(true);
+ gui()->requestSettingsButtonByInstaller(true);
packageManagerCore()->setPackageManager();
emit packageManagerCoreTypeChanged();
@@ -1807,6 +1882,8 @@ void IntroductionPage::setPackageManager(bool value)
void IntroductionPage::initializePage()
{
PackageManagerCore *core = packageManagerCore();
+ const bool repositoriesAvailable = core->validRepositoriesAvailable();
+
if (core->isPackageManager()) {
m_packageManager->setChecked(true);
} else if (core->isUpdater()) {
@@ -1815,24 +1892,35 @@ void IntroductionPage::initializePage()
// If we are running maintenance tool and the default uninstaller
// marker is not overridden, set the default checked radio button
// based on if we have valid repositories available.
- if (!core->isUserSetBinaryMarker() && validRepositoriesAvailable()) {
+ if (!core->isUserSetBinaryMarker() && repositoriesAvailable) {
m_packageManager->setChecked(true);
} else {
// No repositories available, default to complete uninstallation.
m_removeAllComponents->setChecked(true);
core->setCompleteUninstallation(true);
}
+ // Disable options that are unusable without repositories
+ m_offlineMaintenanceTool = !repositoriesAvailable;
+ setMaintainerToolsEnabled(repositoriesAvailable);
}
}
/*!
Resets the internal page state, so that on clicking \uicontrol Next the metadata needs to be
- fetched again.
+ fetched again. For maintenance tool, enables or disables options requiring enabled repositories
+ based on the current repository settings.
*/
void IntroductionPage::onCoreNetworkSettingsChanged()
{
- m_updatesFetched = false;
- m_allPackagesFetched = false;
+ resetFetchedState();
+
+ PackageManagerCore *core = packageManagerCore();
+ if (core->isUninstaller() || core->isMaintainer()) {
+ m_offlineMaintenanceTool = !core->validRepositoriesAvailable();
+
+ setMaintainerToolsEnabled(!m_offlineMaintenanceTool);
+ m_removeAllComponents->setChecked(m_offlineMaintenanceTool);
+ }
}
// -- private
@@ -1855,7 +1943,10 @@ void IntroductionPage::entering()
showMaintenanceTools();
setMaintenanceToolsEnabled(true);
}
- setSettingsButtonRequested((!core->isOfflineOnly()) && (!core->isUninstaller()));
+ if (m_forceUpdate)
+ m_packageManager->setEnabled(false);
+
+ setSettingsButtonRequested((!core->isOfflineOnly()));
}
/*!
@@ -1948,6 +2039,7 @@ LicenseAgreementPage::LicenseAgreementPage(PackageManagerCore *core)
m_textBrowser->setReadOnly(true);
m_textBrowser->setOpenLinks(false);
m_textBrowser->setOpenExternalLinks(true);
+ m_textBrowser->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
m_textBrowser->setObjectName(QLatin1String("LicenseTextBrowser"));
connect(m_textBrowser, &QTextBrowser::anchorClicked, this, &LicenseAgreementPage::openLicenseUrl);
@@ -1992,7 +2084,6 @@ void LicenseAgreementPage::entering()
m_textBrowser->setHtml(QString());
m_licenseListWidget->setVisible(false);
- packageManagerCore()->calculateComponentsToInstall();
foreach (QInstaller::Component *component, packageManagerCore()->orderedComponentsToInstall())
packageManagerCore()->addLicenseItem(component->licenses());
@@ -2015,7 +2106,7 @@ void LicenseAgreementPage::entering()
*/
bool LicenseAgreementPage::isComplete() const
{
- return m_acceptCheckBox->isChecked();
+ return m_acceptCheckBox->isChecked() && ProductKeyCheck::instance()->hasAcceptedAllLicenses();
}
void LicenseAgreementPage::openLicenseUrl(const QUrl &url)
@@ -2108,7 +2199,7 @@ void ComponentSelectionPage::entering()
QT_TR_NOOP("Please select the components you want to update."),
QT_TR_NOOP("Please select the components you want to install."),
QT_TR_NOOP("Please select the components you want to uninstall."),
- QT_TR_NOOP("Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated."),
+ QT_TR_NOOP("Select the components to install. Deselect installed components to uninstall them.<br>Any components already installed will not be updated."),
QT_TR_NOOP("Mandatory components need to be updated first before you can select other components to update.")
};
@@ -2123,18 +2214,16 @@ void ComponentSelectionPage::entering()
d->updateTreeView();
// check component model state so we can enable needed component selection buttons
- if (core->isUpdater())
- d->onModelStateChanged(d->m_currentModel->checkedState());
+ d->onModelStateChanged(d->m_currentModel->checkedState());
setModified(isComplete());
- if (core->settings().repositoryCategories().count() > 0 && !core->isOfflineOnly()
- && !core->isUpdater()) {
- d->showCategoryLayout(true);
- core->settings().setAllowUnstableComponents(true);
- } else {
- d->showCategoryLayout(false);
- }
+ d->showCategoryLayout(core->showRepositoryCategories());
d->showCompressedRepositoryButton();
+ d->showCreateOfflineInstallerButton(true);
+
+ // Reset to default supplement state. The page may set it to OfflineGenerator
+ // which needs to be reset after navigating back to the page.
+ core->resetBinaryMarkerSupplement();
}
/*!
@@ -2144,6 +2233,7 @@ void ComponentSelectionPage::entering()
void ComponentSelectionPage::leaving()
{
d->hideCompressedRepositoryButton();
+ d->showCreateOfflineInstallerButton(false);
}
/*!
@@ -2162,6 +2252,29 @@ void ComponentSelectionPage::showEvent(QShowEvent *event)
}
/*!
+ Called when \c ComponentSelectionPage is validated.
+ Tries to load \c component scripts for components about to be installed.
+ Returns \c true if the script loading succeeded and the next page is shown.
+*/
+bool ComponentSelectionPage::validatePage()
+{
+ PackageManagerCore *core = packageManagerCore();
+ try {
+ core->loadComponentScripts(core->orderedComponentsToInstall(), true);
+ } catch (const Error &error) {
+ // As component script loading failed, there is error in the script and component is
+ // marked as unselected. Recalculate so that unselected component is removed from install.
+ // User is then able to select other components for install.
+ core->clearComponentsToInstallCalculated();
+ core->calculateComponentsToInstall();
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
+ tr("Error"), error.message());
+ return false;
+ }
+ return true;
+}
+
+/*!
Selects all components in the component tree.
*/
void ComponentSelectionPage::selectAll()
@@ -2204,16 +2317,6 @@ void ComponentSelectionPage::deselectComponent(const QString &id)
}
/*!
- Adds the possibility to install a compressed repository on component selection
- page. A new button which opens a file browser is added for compressed
- repository selection.
-*/
-void ComponentSelectionPage::allowCompressedRepositoryInstall()
-{
- d->allowCompressedRepositoryInstall();
-}
-
-/*!
Adds an additional virtual component with the \a name to be installed.
Returns \c true if the virtual component is found and not installed.
@@ -2226,13 +2329,18 @@ bool ComponentSelectionPage::addVirtualComponentToUninstall(const QString &name)
name, allComponents);
if (component && component->isInstalled() && component->isVirtual()) {
component->setCheckState(Qt::Unchecked);
- core->componentsToInstallNeedsRecalculation();
+ core->recalculateAllComponents();
qCDebug(QInstaller::lcDeveloperBuild) << "Virtual component " << name << " was selected for uninstall by script.";
return true;
}
return false;
}
+void ComponentSelectionPage::setAllowCreateOfflineInstaller(bool allow)
+{
+ d->setAllowCreateOfflineInstaller(allow);
+}
+
void ComponentSelectionPage::setModified(bool modified)
{
setComplete(modified);
@@ -2243,18 +2351,10 @@ void ComponentSelectionPage::setModified(bool modified)
*/
bool ComponentSelectionPage::isComplete() const
{
- if (packageManagerCore()->isInstaller() || packageManagerCore()->isUpdater())
- return d->m_currentModel->checked().count();
-
- if (d->m_currentModel->checkedState().testFlag(ComponentModel::DefaultChecked) == false)
- return true;
+ if (!d->componentsResolved())
+ return false;
- const QSet<Component *> uncheckable = d->m_currentModel->uncheckable();
- for (auto &component : uncheckable) {
- if (component->forcedInstallation() && !component->isInstalled())
- return true; // allow installation for new forced components
- }
- return false;
+ return d->m_currentModel->componentsSelected();
}
@@ -2391,7 +2491,7 @@ bool TargetDirectoryPage::validatePage()
if (!QVariant(remove).toBool())
return true;
- return this->packageManagerCore()->checkTargetDir(targetDir());
+ return this->packageManagerCore()->installationAllowedToDirectory(targetDir());
}
/*!
@@ -2580,7 +2680,7 @@ void ReadyForInstallationPage::entering()
m_taskDetailsBrowser->setVisible(false);
setButtonText(QWizard::CommitButton, tr("U&ninstall"));
setColoredTitle(tr("Ready to Uninstall"));
- m_msgLabel->setText(tr("Setup is now ready to begin removing %1 from your computer.<br>"
+ m_msgLabel->setText(tr("All required information is now available to begin removing %1 from your computer.<br>"
"<font color=\"red\">The program directory %2 will be deleted completely</font>, "
"including all content in that directory!")
.arg(productName(),
@@ -2591,26 +2691,31 @@ void ReadyForInstallationPage::entering()
} else if (packageManagerCore()->isMaintainer()) {
setButtonText(QWizard::CommitButton, tr("U&pdate"));
setColoredTitle(tr("Ready to Update Packages"));
- m_msgLabel->setText(tr("Setup is now ready to begin updating your installation."));
+ m_msgLabel->setText(tr("All required information is now available to begin updating your installation."));
+ } else if (packageManagerCore()->isOfflineGenerator()) {
+ setButtonText(QWizard::CommitButton, tr("Create Offline Installer"));
+ setColoredTitle(tr("Ready to Create Offline Installer"));
+ m_msgLabel->setText(tr("All required information is now available to create an offline installer for selected components."));
} else {
Q_ASSERT(packageManagerCore()->isInstaller());
setButtonText(QWizard::CommitButton, tr("&Install"));
setColoredTitle(tr("Ready to Install"));
- m_msgLabel->setText(tr("Setup is now ready to begin installing %1 on your computer.")
+ m_msgLabel->setText(tr("All required information is now available to begin installing %1 on your computer.")
.arg(productName()));
}
- QString htmlOutput;
- bool componentsOk = packageManagerCore()->calculateComponents(&htmlOutput);
+ bool componentsOk = packageManagerCore()->recalculateAllComponents();
+ const QString htmlOutput = packageManagerCore()->componentResolveReasons();
+
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote() << htmlToString(htmlOutput);
m_taskDetailsBrowser->setHtml(htmlOutput);
m_taskDetailsBrowser->setVisible(!componentsOk || LoggingHandler::instance().isVerbose());
setComplete(componentsOk);
- QString spaceInfo;
- if (packageManagerCore()->checkAvailableSpace(spaceInfo)) {
- m_msgLabel->setText(QString::fromLatin1("%1 %2").arg(m_msgLabel->text(), spaceInfo));
+ if (packageManagerCore()->checkAvailableSpace()) {
+ m_msgLabel->setText(QString::fromLatin1("%1 %2").arg(m_msgLabel->text(), packageManagerCore()->availableSpaceMessage()));
} else {
- m_msgLabel->setText(spaceInfo);
+ m_msgLabel->setText(packageManagerCore()->availableSpaceMessage());
setComplete(false);
}
}
@@ -2630,7 +2735,9 @@ void ReadyForInstallationPage::leaving()
void ReadyForInstallationPage::updatePageListTitle()
{
PackageManagerCore *core = packageManagerCore();
- if (core->isInstaller())
+ if (core->isOfflineGenerator())
+ setPageListTitle(tr("Ready to Create Offline Installer"));
+ else if (core->isInstaller())
setPageListTitle(tr("Ready to Install"));
else if (core->isMaintainer())
setPageListTitle(tr("Ready to Update"));
@@ -2667,7 +2774,7 @@ void ReadyForInstallationPage::updatePageListTitle()
*/
PerformInstallationPage::PerformInstallationPage(PackageManagerCore *core)
: PackageManagerPage(core)
- , m_performInstallationForm(new PerformInstallationForm(this))
+ , m_performInstallationForm(new PerformInstallationForm(core, this))
{
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("PerformInstallationPage"));
@@ -2688,6 +2795,11 @@ PerformInstallationPage::PerformInstallationPage(PackageManagerCore *core)
connect(core, &PackageManagerCore::installationFinished,
this, &PerformInstallationPage::installationFinished);
+ connect(core, &PackageManagerCore::offlineGenerationStarted,
+ this, &PerformInstallationPage::installationStarted);
+ connect(core, &PackageManagerCore::offlineGenerationFinished,
+ this, &PerformInstallationPage::installationFinished);
+
connect(core, &PackageManagerCore::uninstallationStarted,
this, &PerformInstallationPage::uninstallationStarted);
connect(core, &PackageManagerCore::uninstallationFinished,
@@ -2757,6 +2869,11 @@ void PerformInstallationPage::entering()
setColoredTitle(tr("Updating components of %1").arg(productName()));
QTimer::singleShot(30, packageManagerCore(), SLOT(runPackageUpdater()));
+ } else if (packageManagerCore()->isOfflineGenerator()) {
+ setButtonText(QWizard::CommitButton, tr("&Create Offline Installer"));
+ setColoredTitle(tr("Creating Offline Installer for %1").arg(productName()));
+
+ QTimer::singleShot(30, packageManagerCore(), SLOT(runOfflineGenerator()));
} else {
setButtonText(QWizard::CommitButton, tr("&Install"));
setColoredTitle(tr("Installing %1").arg(productName()));
@@ -2781,7 +2898,9 @@ void PerformInstallationPage::leaving()
void PerformInstallationPage::updatePageListTitle()
{
PackageManagerCore *core = packageManagerCore();
- if (core->isInstaller())
+ if (core->isOfflineGenerator())
+ setPageListTitle(tr("Creating Offline Installer"));
+ else if (core->isInstaller())
setPageListTitle(tr("Installing"));
else if (core->isMaintainer())
setPageListTitle(tr("Updating"));
@@ -2805,17 +2924,26 @@ void PerformInstallationPage::setTitleMessage(const QString &title)
*/
void PerformInstallationPage::changeCurrentImage()
{
- const QStringList productImages = packageManagerCore()->settings().productImages();
+ const QMap<QString, QVariant> productImages = packageManagerCore()->settings().productImages();
if (productImages.isEmpty())
return;
- const QString nextImage = (m_currentImage.isEmpty() || m_currentImage == productImages.last())
- ? productImages.first()
- : productImages.at(productImages.indexOf(m_currentImage) + 1);
+ QString nextImage;
+ QString nextUrl;
+ if (m_currentImage.isEmpty() || m_currentImage == productImages.lastKey()) {
+ nextImage = productImages.firstKey();
+ nextUrl = productImages.value(nextImage).toString();
+ } else {
+ QMap<QString, QVariant>::const_iterator i = productImages.constFind(m_currentImage);
+ if (++i != productImages.end()) {
+ nextImage = i.key();
+ nextUrl = i.value().toString();
+ }
+ }
// Do not update the pixmap if there was only one image available
if (nextImage != m_currentImage) {
- m_performInstallationForm->setImageFromFileName(nextImage);
+ m_performInstallationForm->setImageFromFileName(nextImage, nextUrl);
m_currentImage = nextImage;
}
}
@@ -2876,7 +3004,7 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
, m_commitButton(nullptr)
{
setObjectName(QLatin1String("FinishedPage"));
- setColoredTitle(tr("Completing the %1 Wizard").arg(productName()));
+ setColoredTitle(tr("Finished the %1 Setup").arg(productName()));
setPageListTitle(tr("Finished"));
m_msgLabel = new QLabel(this);
@@ -2901,7 +3029,7 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
*/
void FinishedPage::entering()
{
- m_msgLabel->setText(tr("Click %1 to exit the %2 Wizard.")
+ m_msgLabel->setText(tr("Click %1 to exit the %2 Setup.")
.arg(gui()->defaultButtonText(QWizard::FinishButton).remove(QLatin1Char('&')))
.arg(productName()));
@@ -2948,7 +3076,8 @@ void FinishedPage::entering()
connect(m_commitButton, &QAbstractButton::clicked, this, &FinishedPage::handleFinishClicked);
}
- if (packageManagerCore()->status() == PackageManagerCore::Success) {
+ if (packageManagerCore()->status() == PackageManagerCore::Success
+ || packageManagerCore()->status() == PackageManagerCore::EssentialUpdated) {
const QString finishedText = packageManagerCore()->value(QLatin1String("FinishedText"));
if (!finishedText.isEmpty())
m_msgLabel->setText(finishedText);
@@ -2962,7 +3091,7 @@ void FinishedPage::entering()
}
} else {
// TODO: how to handle this using the config.xml
- setColoredTitle(tr("The %1 Wizard failed.").arg(productName()));
+ setColoredTitle(tr("The %1 Setup failed.").arg(productName()));
}
m_runItCheckBox->hide();
@@ -2993,16 +3122,8 @@ void FinishedPage::leaving()
*/
void FinishedPage::handleFinishClicked()
{
- const QString program =
- packageManagerCore()->replaceVariables(packageManagerCore()->value(scRunProgram));
-
- const QStringList args = packageManagerCore()->replaceVariables(packageManagerCore()
- ->values(scRunProgramArguments));
- if (!m_runItCheckBox->isChecked() || program.isEmpty())
- return;
-
- qCDebug(QInstaller::lcInstallerInstallLog) << "starting" << program << args;
- QProcess::startDetached(program, args);
+ if (m_runItCheckBox->isChecked())
+ packageManagerCore()->runProgram();
}
/*!
@@ -3047,7 +3168,7 @@ RestartPage::RestartPage(PackageManagerCore *core)
: PackageManagerPage(core)
{
setObjectName(QLatin1String("RestartPage"));
- setColoredTitle(tr("Completing the %1 Setup Wizard").arg(productName()));
+ setColoredTitle(tr("Finished the %1 Setup").arg(productName()));
// Never show this page on the page list
setShowOnPageList(false);
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index ce8bcfd66..d83643005 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -82,8 +82,10 @@ public:
void clickButton(int wizardButton, int delayInMs = 0);
void clickButton(const QString &objectName, int delayInMs = 0) const;
bool isButtonEnabled(int wizardButton);
+ void setWizardPageButtonText(int pageId, int buttonId, const QString &buttonText);
void showSettingsButton(bool show);
+ void requestSettingsButtonByInstaller(bool request);
void setSettingsButtonEnabled(bool enable);
void updateButtonLayout();
@@ -100,10 +102,11 @@ Q_SIGNALS:
void finishButtonClicked();
void gotRestarted();
void settingsButtonClicked();
+ void aboutApplicationClicked();
public Q_SLOTS:
void cancelButtonClicked();
- void reject();
+ void reject() override;
void rejectWithoutPrompt();
void showFinishedPage();
void setModified(bool value);
@@ -129,8 +132,8 @@ private Q_SLOTS:
void currentPageChanged(int newId);
protected:
- bool event(QEvent *event);
- void showEvent(QShowEvent *event);
+ bool event(QEvent *event) override;
+ void showEvent(QShowEvent *event) override;
PackageManagerCore *packageManagerCore() const { return m_core; }
void executeControlScript(int pageId);
@@ -164,7 +167,7 @@ public:
void setShowOnPageList(bool show);
bool showOnPageList() const;
- virtual bool isComplete() const;
+ virtual bool isComplete() const override;
void setComplete(bool complete);
virtual bool isInterruptible() const { return false; }
@@ -172,7 +175,7 @@ public:
void setValidatePageComponent(QInstaller::Component *component);
- bool validatePage();
+ bool validatePage() override;
bool settingsButtonRequested() const { return m_needsSettingsButton; }
void setSettingsButtonRequested(bool request) { m_needsSettingsButton = request; }
@@ -191,7 +194,7 @@ protected:
virtual void insertWidget(QWidget *widget, const QString &siblingName, int offset = 1);
virtual QWidget *findWidget(const QString &objectName) const;
- virtual int nextId() const; // reimp
+ virtual int nextId() const override;
// Used to support some kind of initializePage() in the case the wizard has been set
// to QWizard::IndependentPages. If that option has been set, initializePage() would be only
@@ -225,14 +228,17 @@ public:
void setText(const QString &text);
- int nextId() const;
- bool validatePage();
+ int nextId() const override;
+ bool validatePage() override;
void showAll();
void hideAll();
void showMetaInfoUpdate();
void showMaintenanceTools();
void setMaintenanceToolsEnabled(bool enable);
+ void setMaintainerToolsEnabled(bool enable);
+
+ void resetFetchedState();
public Q_SLOTS:
void onCoreNetworkSettingsChanged();
@@ -250,17 +256,18 @@ private Q_SLOTS:
void setPackageManager(bool value);
private:
- void initializePage();
+ void initializePage() override;
- void entering();
- void leaving();
+ void entering() override;
+ void leaving() override;
void showWidgets(bool show);
- bool validRepositoriesAvailable() const;
private:
bool m_updatesFetched;
bool m_allPackagesFetched;
+ bool m_forceUpdate;
+ bool m_offlineMaintenanceTool;
QLabel *m_label;
QLabel *m_msgLabel;
@@ -286,8 +293,8 @@ class INSTALLER_EXPORT LicenseAgreementPage : public PackageManagerPage
public:
explicit LicenseAgreementPage(PackageManagerCore *core);
- void entering();
- bool isComplete() const;
+ void entering() override;
+ bool isComplete() const override;
private Q_SLOTS:
void openLicenseUrl(const QUrl &url);
@@ -316,20 +323,22 @@ public:
explicit ComponentSelectionPage(PackageManagerCore *core);
~ComponentSelectionPage();
- bool isComplete() const;
+ bool isComplete() const override;
Q_INVOKABLE void selectAll();
Q_INVOKABLE void deselectAll();
Q_INVOKABLE void selectDefault();
Q_INVOKABLE void selectComponent(const QString &id);
Q_INVOKABLE void deselectComponent(const QString &id);
- Q_INVOKABLE void allowCompressedRepositoryInstall();
Q_INVOKABLE bool addVirtualComponentToUninstall(const QString &name);
+ void setAllowCreateOfflineInstaller(bool allow);
+
protected:
- void entering();
- void leaving();
- void showEvent(QShowEvent *event);
+ void entering() override;
+ void leaving() override;
+ void showEvent(QShowEvent *event) override;
+ bool validatePage() override;
private Q_SLOTS:
void setModified(bool modified);
@@ -351,13 +360,13 @@ public:
QString targetDir() const;
void setTargetDir(const QString &dirName);
- void initializePage();
- bool validatePage();
- bool isComplete() const;
+ void initializePage() override;
+ bool validatePage() override;
+ bool isComplete() const override;
protected:
- void entering();
- void leaving();
+ void entering() override;
+ void leaving() override;
private Q_SLOTS:
void dirRequested();
@@ -385,7 +394,7 @@ public:
void setStartMenuDir(const QString &startMenuDir);
protected:
- void leaving();
+ void leaving() override;
private Q_SLOTS:
void currentItemChanged(QListWidgetItem* current);
@@ -407,8 +416,8 @@ public:
explicit ReadyForInstallationPage(PackageManagerCore *core);
protected:
- void entering();
- void leaving();
+ void entering() override;
+ void leaving() override;
private Q_SLOTS:
void updatePageListTitle();
@@ -431,9 +440,9 @@ public:
bool isAutoSwitching() const;
protected:
- void entering();
- void leaving();
- bool isInterruptible() const { return true; }
+ void entering() override;
+ void leaving() override;
+ bool isInterruptible() const override { return true; }
public Q_SLOTS:
void setTitleMessage(const QString& title);
@@ -473,8 +482,8 @@ public Q_SLOTS:
void cleanupChangedConnects();
protected:
- void entering();
- void leaving();
+ void entering() override;
+ void leaving() override;
private:
QLabel *m_msgLabel;
@@ -492,11 +501,11 @@ class INSTALLER_EXPORT RestartPage : public PackageManagerPage
public:
explicit RestartPage(PackageManagerCore *core);
- virtual int nextId() const;
+ virtual int nextId() const override;
protected:
- void entering();
- void leaving();
+ void entering() override;
+ void leaving() override;
Q_SIGNALS:
void restart();
diff --git a/src/libs/installer/packagemanagerproxyfactory.h b/src/libs/installer/packagemanagerproxyfactory.h
index 31f1ffeba..bbb30aed8 100644
--- a/src/libs/installer/packagemanagerproxyfactory.h
+++ b/src/libs/installer/packagemanagerproxyfactory.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -47,8 +47,8 @@ class PackageManagerProxyFactory : public KDUpdater::FileDownloaderProxyFactory
public:
explicit PackageManagerProxyFactory(const PackageManagerCore *const core);
- PackageManagerProxyFactory *clone() const;
- QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery());
+ PackageManagerProxyFactory *clone() const override;
+ QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery()) override;
void setProxyCredentials(const QNetworkProxy &proxy, const QString &user, const QString &password);
diff --git a/src/libs/installer/packagesource.cpp b/src/libs/installer/packagesource.cpp
index 46033f31b..0f87e0def 100644
--- a/src/libs/installer/packagesource.cpp
+++ b/src/libs/installer/packagesource.cpp
@@ -1,11 +1,11 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -61,7 +50,7 @@ namespace QInstaller {
*/
/*!
- \fn QInstaller::PackageSource::PackageSource(const QUrl &u, int p)
+ \fn QInstaller::PackageSource::PackageSource(const QUrl &u, int p, bool pl)
Constructs a package source info object. The object's url is set to \a u, while the priority
is set to \a p.
@@ -80,7 +69,7 @@ namespace QInstaller {
/*!
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-uint qHash(const PackageSource &key, uint seed)
+hashValue qHash(const PackageSource &key, hashValue seed)
{
return qHash(key.url, seed) ^ key.priority;
}
diff --git a/src/libs/installer/packagesource.h b/src/libs/installer/packagesource.h
index 2a3a2ea7f..f63b53cd8 100644
--- a/src/libs/installer/packagesource.h
+++ b/src/libs/installer/packagesource.h
@@ -1,11 +1,11 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -51,16 +40,18 @@ struct INSTALLER_EXPORT PackageSource
PackageSource()
: priority(-1)
{}
- PackageSource(const QUrl &u, int p)
+ PackageSource(const QUrl &u, int p, bool pl = false)
: url(u)
, priority(p)
+ , postLoadComponentScript(pl)
{}
QUrl url;
int priority;
+ bool postLoadComponentScript;
};
-INSTALLER_EXPORT uint qHash(const PackageSource &key, uint seed);
+INSTALLER_EXPORT hashValue qHash(const PackageSource &key, hashValue seed);
INSTALLER_EXPORT bool operator==(const PackageSource &lhs, const PackageSource &rhs);
} // namespace QInstaller
diff --git a/src/libs/installer/performinstallationform.cpp b/src/libs/installer/performinstallationform.cpp
index a61c0d88b..0e4c561f6 100644
--- a/src/libs/installer/performinstallationform.cpp
+++ b/src/libs/installer/performinstallationform.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -30,6 +30,10 @@
#include "progresscoordinator.h"
#include "globals.h"
+#include "aspectratiolabel.h"
+#include "packagemanagercore.h"
+#include "settings.h"
+#include "fileutils.h"
#include <QApplication>
#include <QLabel>
@@ -39,13 +43,17 @@
#include <QVBoxLayout>
#include <QImageReader>
#include <QScrollArea>
+#include <QTextEdit>
+#include <QFileInfo>
#include <QtCore/QTimer>
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QWinTaskbarButton>
# include <QWinTaskbarProgress>
#endif
+#endif
using namespace QInstaller;
@@ -74,20 +82,23 @@ using namespace QInstaller;
*/
/*!
- Constructs the perform installation UI with \a parent as parent.
+ Constructs the perform installation UI with package manager specified by \a core and
+ with \a parent as parent.
*/
-PerformInstallationForm::PerformInstallationForm(QObject *parent)
+PerformInstallationForm::PerformInstallationForm(PackageManagerCore *core, QObject *parent)
: QObject(parent)
, m_progressBar(nullptr)
, m_progressLabel(nullptr)
- , m_downloadStatus(nullptr)
+ , m_additionalProgressStatus(nullptr)
, m_productImagesScrollArea(nullptr)
, m_productImagesLabel(nullptr)
, m_detailsButton(nullptr)
, m_detailsBrowser(nullptr)
, m_updateTimer(nullptr)
+ , m_core(core)
{
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
m_taskButton = new QWinTaskbarButton(this);
m_taskButton->progress()->setVisible(true);
@@ -95,6 +106,7 @@ PerformInstallationForm::PerformInstallationForm(QObject *parent)
m_taskButton = nullptr;
}
#endif
+#endif
}
/*!
@@ -118,14 +130,14 @@ void PerformInstallationForm::setupUi(QWidget *widget)
m_progressLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
topLayout->addWidget(m_progressLabel);
- m_downloadStatus = new QLabel(widget);
- m_downloadStatus->setObjectName(QLatin1String("DownloadStatus"));
- m_downloadStatus->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
- m_downloadStatus->setWordWrap(true);
- m_downloadStatus->setTextFormat(Qt::TextFormat::RichText);
- topLayout->addWidget(m_downloadStatus);
- connect(ProgressCoordinator::instance(), &ProgressCoordinator::downloadStatusChanged, this,
- &PerformInstallationForm::onDownloadStatusChanged);
+ m_additionalProgressStatus = new QLabel(widget);
+ m_additionalProgressStatus->setObjectName(QLatin1String("DownloadStatus"));
+ m_additionalProgressStatus->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
+ m_additionalProgressStatus->setWordWrap(true);
+ m_additionalProgressStatus->setTextFormat(Qt::TextFormat::RichText);
+ topLayout->addWidget(m_additionalProgressStatus);
+ connect(ProgressCoordinator::instance(), &ProgressCoordinator::additionalProgressStatusChanged, this,
+ &PerformInstallationForm::onAdditionalProgressStatusChanged);
m_detailsButton = new QPushButton(tr("&Show Details"), widget);
m_detailsButton->setObjectName(QLatin1String("DetailsButton"));
@@ -196,12 +208,14 @@ void PerformInstallationForm::updateProgress()
m_progressBar->setValue(progressPercentage);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton) {
if (!m_taskButton->window() && QApplication::activeWindow())
m_taskButton->setWindow(QApplication::activeWindow()->windowHandle());
m_taskButton->progress()->setValue(progressPercentage);
}
#endif
+#endif
static QString lastLabelText;
if (lastLabelText == progressCoordninator->labelText())
@@ -282,26 +296,33 @@ bool PerformInstallationForm::isShowingDetails() const
Changes the label text according to the changes in the download status
specified by \a status.
*/
-void PerformInstallationForm::onDownloadStatusChanged(const QString &status)
+void PerformInstallationForm::onAdditionalProgressStatusChanged(const QString &status)
{
- m_downloadStatus->setText(status);
+ m_additionalProgressStatus->setText(status);
}
/*!
- Sets currently shown form image specified by \a fileName.
+ Sets currently shown form image specified by \a fileName. When clicking the image,
+ \a url is opened in a browser. If the \a url is a reference to a file, it will
+ be opened with a suitable application instead of a Web browser. \a url can be empty.
*/
-void PerformInstallationForm::setImageFromFileName(const QString &fileName)
+void PerformInstallationForm::setImageFromFileName(const QString &fileName, const QString &url)
{
- if (!QFile::exists(fileName)) {
- qCWarning(QInstaller::lcDeveloperBuild) << "Image file does not exist:" << fileName;
+ QString imagePath = QFileInfo(fileName).isAbsolute()
+ ? fileName
+ : m_core->settings().value(QLatin1String("Prefix")).toString() + QLatin1Char('/') + fileName;
+ QInstaller::replaceHighDpiImage(imagePath);
+
+ if (!QFile::exists(imagePath)) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << "Image file does not exist:" << fileName;
return;
}
- QImageReader reader(fileName);
+ QImageReader reader(imagePath);
QPixmap pixmap = QPixmap::fromImageReader(&reader);
if (!pixmap.isNull()) {
- m_productImagesLabel->setPixmap(pixmap);
+ m_productImagesLabel->setPixmapAndUrl(pixmap, url);
} else {
- qCWarning(QInstaller::lcDeveloperBuild) <<
- QString::fromLatin1("Failed to load image '%1' : %2.").arg(fileName, reader.errorString());
+ qCWarning(QInstaller::lcInstallerInstallLog) <<
+ QString::fromLatin1("Failed to load image '%1' : %2.").arg(imagePath, reader.errorString());
}
}
diff --git a/src/libs/installer/performinstallationform.h b/src/libs/installer/performinstallationform.h
index d67f6ac4b..d5f87eeaa 100644
--- a/src/libs/installer/performinstallationform.h
+++ b/src/libs/installer/performinstallationform.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,10 +29,7 @@
#ifndef PERFORMINSTALLATIONFORM_H
#define PERFORMINSTALLATIONFORM_H
-#include "aspectratiolabel.h"
-
#include <QObject>
-#include <QTextEdit>
QT_BEGIN_NAMESPACE
class QLabel;
@@ -42,17 +39,21 @@ class QTimer;
class QWidget;
class QWinTaskbarButton;
class QScrollArea;
+class QTextEdit;
QT_END_NAMESPACE
namespace QInstaller {
+class AspectRatioLabel;
+class PackageManagerCore;
+
class PerformInstallationForm : public QObject
{
Q_OBJECT
public:
- explicit PerformInstallationForm(QObject *parent);
+ explicit PerformInstallationForm(PackageManagerCore *core, QObject *parent);
void setupUi(QWidget *widget);
void setDetailsWidgetVisible(bool visible);
@@ -70,18 +71,19 @@ public slots:
void updateProgress();
void toggleDetails();
void clearDetailsBrowser();
- void onDownloadStatusChanged(const QString &status);
- void setImageFromFileName(const QString &fileName);
+ void onAdditionalProgressStatusChanged(const QString &status);
+ void setImageFromFileName(const QString &fileName, const QString &url);
private:
QProgressBar *m_progressBar;
QLabel *m_progressLabel;
- QLabel *m_downloadStatus;
+ QLabel *m_additionalProgressStatus;
QScrollArea *m_productImagesScrollArea;
AspectRatioLabel *m_productImagesLabel;
QPushButton *m_detailsButton;
QTextEdit *m_detailsBrowser;
QTimer *m_updateTimer;
+ PackageManagerCore *m_core;
#ifdef Q_OS_WIN
QWinTaskbarButton *m_taskButton;
diff --git a/src/libs/installer/permissionsettings.cpp b/src/libs/installer/permissionsettings.cpp
index 6d5abdfe6..d70cf5625 100644
--- a/src/libs/installer/permissionsettings.cpp
+++ b/src/libs/installer/permissionsettings.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
diff --git a/src/libs/installer/permissionsettings.h b/src/libs/installer/permissionsettings.h
index 3847c91db..c950d9c17 100644
--- a/src/libs/installer/permissionsettings.h
+++ b/src/libs/installer/permissionsettings.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,14 +39,17 @@ public:
explicit PermissionSettings(const QString &organization,
const QString &application = QString(), QObject *parent = 0)
: QSettings(organization, application, parent) {}
+
PermissionSettings(Scope scope, const QString &organization,
const QString &application = QString(), QObject *parent = 0)
: QSettings(scope, organization, application, parent) {}
+
PermissionSettings(Format format, Scope scope, const QString &organization,
- const QString &application = QString(), QObject *parent = 0)
- : QSettings(format, scope, organization, application, parent) {}
+ const QString &application = QString(), QObject *parent = 0)
+ : QSettings(format, scope, organization, application, parent) {}
PermissionSettings(const QString &fileName, Format format, QObject *parent = 0)
- : QSettings(fileName, format, parent) {}
+ : QSettings(fileName, format, parent) {}
+
~PermissionSettings();
};
diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp
index c1dfe83d6..ed128fa61 100644
--- a/src/libs/installer/productkeycheck.cpp
+++ b/src/libs/installer/productkeycheck.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,6 +29,8 @@
#include "productkeycheck.h"
#include "packagemanagercore.h"
+#include <QtUiTools/QUiLoader>
+
class ProductKeyCheckPrivate
{
};
@@ -49,6 +51,12 @@ ProductKeyCheck *ProductKeyCheck::instance()
return &instance;
}
+QUiLoader *ProductKeyCheck::uiLoader()
+{
+ static QUiLoader loader;
+ return &loader;
+}
+
void ProductKeyCheck::init(QInstaller::PackageManagerCore *core)
{
Q_UNUSED(core)
@@ -106,3 +114,22 @@ bool ProductKeyCheck::hasValidLicense() const
{
return true;
}
+
+bool ProductKeyCheck::hasAcceptedAllLicenses() const
+{
+ return true;
+}
+
+QString ProductKeyCheck::licenseAcceptanceText() const
+{
+ return QString();
+}
+QString ProductKeyCheck::securityWarning() const
+{
+ return QString();
+}
+
+QString ProductKeyCheck::additionalMetaDownloadWarning() const
+{
+ return QString();
+}
diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h
index b7e8c6d52..8e7d6724f 100644
--- a/src/libs/installer/productkeycheck.h
+++ b/src/libs/installer/productkeycheck.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,7 @@
#include "installer_global.h"
#include <QString>
+#include <QUiLoader>
namespace QInstaller {
@@ -49,6 +50,8 @@ public:
static ProductKeyCheck *instance();
void init(QInstaller::PackageManagerCore *core);
+ static QUiLoader *uiLoader();
+
// was validLicense
bool hasValidKey();
QString lastErrorString();
@@ -67,6 +70,10 @@ public:
QList<int> registeredPages() const;
bool hasValidLicense() const;
+ bool hasAcceptedAllLicenses() const;
+ QString licenseAcceptanceText() const;
+ QString securityWarning() const;
+ QString additionalMetaDownloadWarning() const;
private:
ProductKeyCheck();
diff --git a/src/libs/installer/progresscoordinator.cpp b/src/libs/installer/progresscoordinator.cpp
index 01b92bff8..6413efe28 100644
--- a/src/libs/installer/progresscoordinator.cpp
+++ b/src/libs/installer/progresscoordinator.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,7 +40,7 @@
using namespace QInstaller;
QT_BEGIN_NAMESPACE
-uint qHash(QPointer<QObject> key)
+hashValue qHash(QPointer<QObject> key)
{
return qHash(key.data());
}
@@ -76,7 +76,8 @@ ProgressCoordinator *ProgressCoordinator::instance()
void ProgressCoordinator::reset()
{
- disconnectAllSenders();
+ m_senderPartProgressSizeHash.clear();
+ m_senderPendingCalculatedPercentageHash.clear();
m_installationLabelText.clear();
m_currentCompletePercentage = 0;
m_currentBasePercentage = 0;
@@ -90,10 +91,11 @@ void ProgressCoordinator::reset()
void ProgressCoordinator::registerPartProgress(QObject *sender, const char *signal, double partProgressSize)
{
Q_ASSERT(sender);
+ Q_ASSERT(!sender->objectName().isEmpty());
Q_ASSERT(QString::fromLatin1(signal).contains(QLatin1String("(double)")));
Q_ASSERT(partProgressSize <= 1);
- m_senderPartProgressSizeHash.insert(sender, partProgressSize);
+ m_senderPartProgressSizeHash.insert(sender->objectName(), partProgressSize);
bool isConnected = connect(sender, signal, this, SLOT(partProgressChanged(double)));
Q_UNUSED(isConnected);
Q_ASSERT(isConnected);
@@ -116,16 +118,17 @@ void ProgressCoordinator::partProgressChanged(double fraction)
}
// no fraction no change
- if (fraction == 0)
+ if (fraction == 0 || !sender())
return;
+ QString senderObjectName = sender()->objectName();
// ignore senders sending 100% multiple times
- if (fraction == 1 && m_senderPendingCalculatedPercentageHash.contains(sender())
- && m_senderPendingCalculatedPercentageHash.value(sender()) == 0) {
+ if (fraction == 1 && m_senderPendingCalculatedPercentageHash.contains(senderObjectName)
+ && m_senderPendingCalculatedPercentageHash.value(senderObjectName) == 0) {
return;
}
- double partProgressSize = m_senderPartProgressSizeHash.value(sender(), 0);
+ double partProgressSize = m_senderPartProgressSizeHash.value(senderObjectName, 0);
if (partProgressSize == 0) {
qCWarning(QInstaller::lcInstallerInstallLog) << "It seems that this sender was not registered "
"in the right way:" << sender();
@@ -138,7 +141,7 @@ void ProgressCoordinator::partProgressChanged(double fraction)
// allPendingCalculatedPartPercentages has negative values
double newCurrentCompletePercentage = m_currentBasePercentage - pendingCalculatedPartPercentage
- + allPendingCalculatedPartPercentages(sender());
+ + allPendingCalculatedPartPercentages(senderObjectName);
//we can't check this here, because some round issues can make it little bit under 0 or over 100
//Q_ASSERT(newCurrentCompletePercentage >= 0);
@@ -163,9 +166,9 @@ void ProgressCoordinator::partProgressChanged(double fraction)
m_currentCompletePercentage = newCurrentCompletePercentage;
if (fraction == 1) {
m_currentBasePercentage = m_currentBasePercentage - pendingCalculatedPartPercentage;
- m_senderPendingCalculatedPercentageHash.insert(sender(), 0);
+ m_senderPendingCalculatedPercentageHash.insert(senderObjectName, 0);
} else {
- m_senderPendingCalculatedPercentageHash.insert(sender(), pendingCalculatedPartPercentage);
+ m_senderPendingCalculatedPercentageHash.insert(senderObjectName, pendingCalculatedPartPercentage);
}
} else { //if (m_undoMode)
@@ -174,7 +177,7 @@ void ProgressCoordinator::partProgressChanged(double fraction)
//double checkValue = allPendingCalculatedPartPercentages(sender());
double newCurrentCompletePercentage = m_manualAddedPercentage + m_currentBasePercentage
- + pendingCalculatedPartPercentage + allPendingCalculatedPartPercentages(sender());
+ + pendingCalculatedPartPercentage + allPendingCalculatedPartPercentages(senderObjectName);
//we can't check this here, because some round issues can make it little bit under 0 or over 100
//Q_ASSERT(newCurrentCompletePercentage >= 0);
@@ -199,9 +202,9 @@ void ProgressCoordinator::partProgressChanged(double fraction)
if (fraction == 1) {
m_currentBasePercentage = m_currentBasePercentage + pendingCalculatedPartPercentage;
- m_senderPendingCalculatedPercentageHash.insert(sender(), 0);
+ m_senderPendingCalculatedPercentageHash.insert(senderObjectName, 0);
} else {
- m_senderPendingCalculatedPercentageHash.insert(sender(), pendingCalculatedPartPercentage);
+ m_senderPendingCalculatedPercentageHash.insert(senderObjectName, pendingCalculatedPartPercentage);
}
} //if (m_undoMode)
printProgressPercentage(progressInPercentage());
@@ -219,25 +222,13 @@ int ProgressCoordinator::progressInPercentage() const
return currentValue;
}
-void ProgressCoordinator::disconnectAllSenders()
-{
- foreach (QPointer<QObject> sender, m_senderPartProgressSizeHash.keys()) {
- if (!sender.isNull()) {
- bool isDisconnected = sender->disconnect(this);
- Q_UNUSED(isDisconnected);
- Q_ASSERT(isDisconnected);
- }
- }
- m_senderPartProgressSizeHash.clear();
- m_senderPendingCalculatedPercentageHash.clear();
-}
-
void ProgressCoordinator::setUndoMode()
{
Q_ASSERT(!m_undoMode);
m_undoMode = true;
- disconnectAllSenders();
+ m_senderPartProgressSizeHash.clear();
+ m_senderPendingCalculatedPercentageHash.clear();
m_reachedPercentageBeforeUndo = progressInPercentage();
m_currentBasePercentage = m_reachedPercentageBeforeUndo;
}
@@ -294,10 +285,10 @@ void ProgressCoordinator::emitLabelAndDetailTextChanged(const QString &text)
qApp->processEvents(); //makes the result available in the ui
}
-double ProgressCoordinator::allPendingCalculatedPartPercentages(QObject *excludeKeyObject)
+double ProgressCoordinator::allPendingCalculatedPartPercentages(const QString &excludeKeyObject)
{
double result = 0;
- QHash<QPointer<QObject>, double>::iterator it = m_senderPendingCalculatedPercentageHash.begin();
+ QHash<QString, double>::iterator it = m_senderPendingCalculatedPercentageHash.begin();
while (it != m_senderPendingCalculatedPercentageHash.end()) {
if (it.key() != excludeKeyObject)
result += it.value();
@@ -306,9 +297,9 @@ double ProgressCoordinator::allPendingCalculatedPartPercentages(QObject *exclude
return result;
}
-void ProgressCoordinator::emitDownloadStatus(const QString &status)
+void ProgressCoordinator::emitAdditionalProgressStatus(const QString &status)
{
- emit downloadStatusChanged(status);
+ emit additionalProgressStatusChanged(status);
}
void ProgressCoordinator::printProgressPercentage(int progress)
diff --git a/src/libs/installer/progresscoordinator.h b/src/libs/installer/progresscoordinator.h
index 380c90df0..75d5a5d30 100644
--- a/src/libs/installer/progresscoordinator.h
+++ b/src/libs/installer/progresscoordinator.h
@@ -72,25 +72,25 @@ public slots:
void emitDetailTextChanged(const QString &text);
void emitLabelAndDetailTextChanged(const QString &text);
- void emitDownloadStatus(const QString &status);
+ void emitAdditionalProgressStatus(const QString &status);
void printProgressPercentage(int progress);
void printProgressMessage(const QString &message);
signals:
void detailTextChanged(const QString &text);
void detailTextResetNeeded();
- void downloadStatusChanged(const QString &status);
+ void additionalProgressStatusChanged(const QString &status);
protected:
explicit ProgressCoordinator(QObject *parent);
private:
- double allPendingCalculatedPartPercentages(QObject *excludeKeyObject = 0);
+ double allPendingCalculatedPartPercentages(const QString &excludeKeyObject = QString());
void disconnectAllSenders();
private:
- QHash<QPointer<QObject>, double> m_senderPendingCalculatedPercentageHash;
- QHash<QPointer<QObject>, double> m_senderPartProgressSizeHash;
+ QHash<QString, double> m_senderPendingCalculatedPercentageHash;
+ QHash<QString, double> m_senderPartProgressSizeHash;
ProgressSpinner *m_progressSpinner;
QString m_installationLabelText;
double m_currentCompletePercentage;
diff --git a/src/libs/installer/protocol.h b/src/libs/installer/protocol.h
index 65241e00b..8b2288a89 100644
--- a/src/libs/installer/protocol.h
+++ b/src/libs/installer/protocol.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -50,9 +50,9 @@ enum struct StartAs {
const char DefaultSocket[] = "ifw_srv";
const char DefaultAuthorizationKey[] = "DefaultAuthorizationKey";
+const char DefaultReply[] = "DefaultReply";
const char Create[] = "Create";
-const char Destroy[] = "Destroy";
const char Shutdown[] = "Shutdown";
const char Authorize[] = "Authorize";
const char Reply[] = "Reply";
@@ -67,6 +67,7 @@ const char QProcessReadAll[] = "QProcess::readAll";
const char QProcessReadAllStandardOutput[] = "QProcess::readAllStandardOutput";
const char QProcessReadAllStandardError[] = "QProcess::readAllStandardError";
const char QProcessStartDetached[] = "QProcess::startDetached";
+const char QProcessStartDetached2[] = "QProcess::startDetached2";
const char QProcessSetWorkingDirectory[] = "QProcess::setWorkingDirectory";
const char QProcessSetEnvironment[] = "QProcess::setEnvironment";
const char QProcessEnvironment[] = "QProcess::environment";
@@ -89,7 +90,7 @@ const char GetQProcessSignals[] = "GetQProcessSignals";
const char QProcessSignalBytesWritten[] = "QProcess::bytesWritten";
const char QProcessSignalAboutToClose[] = "QProcess::aboutToClose";
const char QProcessSignalReadChannelFinished[] = "QProcess::readChannelFinished";
-const char QProcessSignalError[] = "QProcess::error";
+const char QProcessSignalError[] = "QProcess::errorOccurred";
const char QProcessSignalReadyReadStandardOutput[] = "QProcess::readyReadStandardOutput";
const char QProcessSignalReadyReadStandardError[] = "QProcess::readyReadStandardError";
const char QProcessSignalStarted[] = "QProcess::started";
diff --git a/src/libs/installer/qinstallerglobal.cpp b/src/libs/installer/qinstallerglobal.cpp
index 177a2595d..457690892 100644
--- a/src/libs/installer/qinstallerglobal.cpp
+++ b/src/libs/installer/qinstallerglobal.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,6 +39,7 @@
\value ExtractionError
\value UserIgnoreError
\value RepositoryUpdatesReceived
+ \value CacheError
*/
/*!
@@ -66,7 +67,33 @@
*/
/*!
- \typedef QInstaller::LocalPackagesHash
+ \typedef QInstaller::LocalPackagesMap
- Synonym for QHash<QString, KDUpdater::LocalPackage>.
+ Synonym for QMap<QString, KDUpdater::LocalPackage>. The map key is component name,
+ and value contains information about the local package.
+*/
+
+/*!
+ \typedef QInstaller::AutoDependencyHash
+
+ Synonym for QHash<QString, QStringList>. The hash key is component name,
+ that other components automatically depend on. The value can contain
+ several component names, which are installed as an automatic dependency.
+ For example:
+ \badcode
+ <Name>A</Name> //Hash value
+ <AutoDependOn>B</AutoDependOn> //Hash key
+ \endcode
+*/
+
+/*!
+ \typedef QInstaller::LocalDependencyHash
+
+ Synonym for QHash<QString, QStringList>. The hash key is component name,
+ which other components depend on. The value can contain several component
+ names, which depend on the key. For example:
+ \badcode
+ <Name>A</Name> //Hash value
+ <Dependencies>B</Dependencies> //Hash key
+ \endcode
*/
diff --git a/src/libs/installer/qinstallerglobal.h b/src/libs/installer/qinstallerglobal.h
index 884044db9..a750e6583 100644
--- a/src/libs/installer/qinstallerglobal.h
+++ b/src/libs/installer/qinstallerglobal.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -46,7 +46,8 @@ enum INSTALLER_EXPORT JobError
InvalidMetaInfo,
ExtractionError,
UserIgnoreError,
- RepositoryUpdatesReceived
+ RepositoryUpdatesReceived,
+ CacheError
};
typedef KDUpdater::UpdateOperation Operation;
@@ -55,7 +56,10 @@ typedef QList<QInstaller::Operation*> OperationList;
typedef KDUpdater::Update Package;
typedef QList<QInstaller::Package*> PackagesList;
-typedef QHash<QString, KDUpdater::LocalPackage> LocalPackagesHash;
+typedef QMap<QString, KDUpdater::LocalPackage> LocalPackagesMap;
+
+typedef QHash<QString, QStringList> AutoDependencyHash;
+typedef QHash<QString, QStringList> LocalDependencyHash;
} // namespace QInstaller
diff --git a/src/libs/installer/qprocesswrapper.cpp b/src/libs/installer/qprocesswrapper.cpp
index b33e7d43c..44117eefb 100644
--- a/src/libs/installer/qprocesswrapper.cpp
+++ b/src/libs/installer/qprocesswrapper.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,7 @@
#include "utils.h"
#include <QDir>
+#include <QVariant>
namespace QInstaller {
@@ -53,7 +54,7 @@ QProcessWrapper::QProcessWrapper(QObject *parent)
connect(&process, &QIODevice::bytesWritten, this, &QProcessWrapper::bytesWritten);
connect(&process, &QIODevice::aboutToClose, this, &QProcessWrapper::aboutToClose);
connect(&process, &QIODevice::readChannelFinished, this, &QProcessWrapper::readChannelFinished);
- connect(&process, SIGNAL(error(QProcess::ProcessError)), SIGNAL(error(QProcess::ProcessError)));
+ connect(&process, SIGNAL(errorOccurred(QProcess::ProcessError)), SIGNAL(errorOccurred(QProcess::ProcessError)));
connect(&process, &QProcess::readyReadStandardOutput, this, &QProcessWrapper::readyReadStandardOutput);
connect(&process, &QProcess::readyReadStandardError, this, &QProcessWrapper::readyReadStandardError);
connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), SIGNAL(finished(int,QProcess::ExitStatus)));
@@ -87,7 +88,7 @@ void QProcessWrapper::processSignals()
} else if (name == QLatin1String(Protocol::QProcessSignalReadChannelFinished)) {
emit readChannelFinished();
} else if (name == QLatin1String(Protocol::QProcessSignalError)) {
- emit error(static_cast<QProcess::ProcessError> (receivedSignals.takeFirst().toInt()));
+ emit errorOccurred(static_cast<QProcess::ProcessError> (receivedSignals.takeFirst().toInt()));
} else if (name == QLatin1String(Protocol::QProcessSignalReadyReadStandardOutput)) {
emit readyReadStandardOutput();
} else if (name == QLatin1String(Protocol::QProcessSignalReadyReadStandardError)) {
@@ -107,6 +108,11 @@ void QProcessWrapper::processSignals()
m_lock.unlock();
}
+/*!
+ Starts the \a program with \a arguments in the working directory \a workingDirectory as a detached
+ process. The process id can be retrieved with the \a pid parameter. Compared to the QProcess
+ implementation of the same method this does not show a window for the started process on Windows.
+*/
bool QProcessWrapper::startDetached(const QString &program, const QStringList &arguments,
const QString &workingDirectory, qint64 *pid)
{
@@ -123,22 +129,70 @@ bool QProcessWrapper::startDetached(const QString &program, const QStringList &a
return QInstaller::startDetached(program, arguments, workingDirectory, pid);
}
+/*!
+ Starts the \a program with \a arguments as a detached process. Compared to the QProcess
+ implementation of the same method this does not show a window for the started process on Windows.
+*/
bool QProcessWrapper::startDetached(const QString &program, const QStringList &arguments)
{
return startDetached(program, arguments, QDir::currentPath());
}
+/*!
+ Starts the \a program as a detached process. Compared to the QProcess implementation of the same
+ method this does not show a window for the started process on Windows.
+*/
bool QProcessWrapper::startDetached(const QString &program)
{
return startDetached(program, QStringList());
}
+/*!
+ Starts the \a program as a detached process. The variants of the function suffixed with \c 2
+ use the base \c QProcess::startDetached implementation internally to start the process.
+*/
+bool QProcessWrapper::startDetached2(const QString &program)
+{
+ return startDetached2(program, QStringList());
+}
+
+/*!
+ Starts the \a program with \a arguments as a detached process. The variants of the function
+ suffixed with \c 2 use the base \c QProcess::startDetached implementation internally to
+ start the process.
+*/
+bool QProcessWrapper::startDetached2(const QString &program, const QStringList &arguments)
+{
+ return startDetached2(program, arguments, QDir::currentPath());
+}
+
+/*!
+ Starts the \a program with \a arguments in the working directory \a workingDirectory as a detached
+ process. The process id can be retrieved with the \a pid parameter. The variants
+ of the function suffixed with \c 2 use the base \c QProcess::startDetached implementation
+ internally to start the process.
+*/
+bool QProcessWrapper::startDetached2(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
+{
+ QProcessWrapper w;
+ if (w.connectToServer()) {
+ const QPair<bool, qint64> result =
+ w.callRemoteMethod<QPair<bool, qint64> >(QLatin1String(Protocol::QProcessStartDetached2),
+ program, arguments, workingDirectory);
+ if (pid != nullptr)
+ *pid = result.second;
+ w.processSignals();
+ return result.first;
+ }
+ return QProcess::startDetached(program, arguments, workingDirectory, pid);
+}
+
void QProcessWrapper::setProcessChannelMode(QProcessWrapper::ProcessChannelMode mode)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessSetProcessChannelMode),
- static_cast<QProcess::ProcessChannelMode>(mode), dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessSetProcessChannelMode),
+ static_cast<QProcess::ProcessChannelMode>(mode));
m_lock.unlock();
} else {
process.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(mode));
@@ -162,8 +216,8 @@ void QProcessWrapper::setReadChannel(QProcessWrapper::ProcessChannel chan)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessSetReadChannel),
- static_cast<QProcess::ProcessChannel>(chan), dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessSetReadChannel),
+ static_cast<QProcess::ProcessChannel>(chan));
m_lock.unlock();
} else {
process.setReadChannel(static_cast<QProcess::ProcessChannel>(chan));
@@ -209,7 +263,7 @@ void QProcessWrapper::closeWriteChannel()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessCloseWriteChannel));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessCloseWriteChannel));
m_lock.unlock();
} else {
process.closeWriteChannel();
@@ -242,7 +296,7 @@ void QProcessWrapper::kill()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessKill));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessKill));
m_lock.unlock();
} else {
process.kill();
@@ -289,7 +343,7 @@ void QProcessWrapper::start(const QString &param1, const QStringList &param2,
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessStart3Arg), param1, param2, param3);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessStart3Arg), param1, param2, param3);
m_lock.unlock();
} else {
process.start(param1, param2, param3);
@@ -300,10 +354,10 @@ void QProcessWrapper::start(const QString &param1, QIODevice::OpenMode param2)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessStart2Arg), param1, param2);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessStart2Arg), param1, param2);
m_lock.unlock();
} else {
- process.start(param1, param2);
+ process.start(param1, {}, param2);
}
}
@@ -322,7 +376,7 @@ void QProcessWrapper::terminate()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessTerminate));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessTerminate));
m_lock.unlock();
} else {
process.terminate();
@@ -389,7 +443,7 @@ void QProcessWrapper::setEnvironment(const QStringList &param1)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessSetEnvironment), param1, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessSetEnvironment), param1);
m_lock.unlock();
} else {
process.setEnvironment(param1);
@@ -401,7 +455,7 @@ void QProcessWrapper::setNativeArguments(const QString &param1)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessSetNativeArguments), param1, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessSetNativeArguments), param1);
m_lock.unlock();
} else {
process.setNativeArguments(param1);
@@ -413,7 +467,7 @@ void QProcessWrapper::setWorkingDirectory(const QString &param1)
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::QProcessSetWorkingDirectory), param1, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QProcessSetWorkingDirectory), param1);
m_lock.unlock();
} else {
process.setWorkingDirectory(param1);
diff --git a/src/libs/installer/qprocesswrapper.h b/src/libs/installer/qprocesswrapper.h
index e76217eda..b34d6f82c 100644
--- a/src/libs/installer/qprocesswrapper.h
+++ b/src/libs/installer/qprocesswrapper.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -104,6 +104,11 @@ public:
static bool startDetached(const QString &program, const QStringList &arguments,
const QString &workingDirectory, qint64 *pid = 0);
+ static bool startDetached2(const QString &program);
+ static bool startDetached2(const QString &program, const QStringList &arguments);
+ static bool startDetached2(const QString &program, const QStringList &arguments,
+ const QString &workingDirectory, qint64 *pid = 0);
+
QString errorString() const;
qint64 write(const QByteArray &byteArray);
#ifdef Q_OS_WIN
@@ -114,7 +119,7 @@ Q_SIGNALS:
void bytesWritten(qint64);
void aboutToClose();
void readChannelFinished();
- void error(QProcess::ProcessError);
+ void errorOccurred(QProcess::ProcessError);
void readyReadStandardOutput();
void readyReadStandardError();
void finished(int exitCode, QProcess::ExitStatus exitStatus);
diff --git a/src/libs/installer/qsettingswrapper.cpp b/src/libs/installer/qsettingswrapper.cpp
index f57750bc1..d322728f5 100644
--- a/src/libs/installer/qsettingswrapper.cpp
+++ b/src/libs/installer/qsettingswrapper.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -107,18 +107,18 @@ QSettingsWrapper::QSettingsWrapper(QSettingsWrapper::Scope scope, const QString
{
}
-QSettingsWrapper::QSettingsWrapper(QSettingsWrapper::Format format, QSettingsWrapper::Scope scope,
+QSettingsWrapper::QSettingsWrapper(QSettings::Format format, QSettingsWrapper::Scope scope,
const QString &organization, const QString &application, QObject *parent)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
- , d(new Private(static_cast<QSettings::Format>(format), static_cast<QSettings::Scope> (scope),
+ , d(new Private(format, static_cast<QSettings::Scope> (scope),
organization, application))
{
}
-QSettingsWrapper::QSettingsWrapper(const QString &fileName, QSettingsWrapper::Format format,
+QSettingsWrapper::QSettingsWrapper(const QString &fileName, QSettings::Format format,
QObject *parent)
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
- , d(new Private(fileName, static_cast<QSettings::Format>(format)))
+ , d(new Private(fileName, format))
{
}
@@ -141,27 +141,39 @@ QString QSettingsWrapper::applicationName() const
return d->settings.applicationName();
}
-void QSettingsWrapper::beginGroup(const QString &param1)
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+ void QSettingsWrapper::beginGroup(const QString &prefix)
+#else
+ void QSettingsWrapper::beginGroup(QAnyStringView prefix)
+#endif
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsBeginGroup), param1, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsBeginGroup), prefix);
else
- d->settings.beginGroup(param1);
+ d->settings.beginGroup(prefix);
}
-int QSettingsWrapper::beginReadArray(const QString &param1)
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+ int QSettingsWrapper::beginReadArray(const QString &prefix)
+#else
+ int QSettingsWrapper::beginReadArray(QAnyStringView prefix)
+#endif
{
if (createSocket())
- return callRemoteMethod<qint32>(QLatin1String(Protocol::QSettingsBeginReadArray), param1);
- return d->settings.beginReadArray(param1);
+ return callRemoteMethod<qint32>(QLatin1String(Protocol::QSettingsBeginReadArray), prefix);
+ return d->settings.beginReadArray(prefix);
}
-void QSettingsWrapper::beginWriteArray(const QString &param1, int param2)
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+ void QSettingsWrapper::beginWriteArray(const QString &prefix, int size)
+#else
+ void QSettingsWrapper::beginWriteArray(QAnyStringView prefix, int size)
+#endif
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsBeginWriteArray), param1, qint32(param2));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsBeginWriteArray), prefix, qint32(size));
else
- d->settings.beginWriteArray(param1, param2);
+ d->settings.beginWriteArray(prefix, size);
}
QStringList QSettingsWrapper::childGroups() const
@@ -181,21 +193,25 @@ QStringList QSettingsWrapper::childKeys() const
void QSettingsWrapper::clear()
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsClear));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsClear));
else d->settings.clear();
}
-bool QSettingsWrapper::contains(const QString &param1) const
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+ bool QSettingsWrapper::contains(const QString &key) const
+#else
+ bool QSettingsWrapper::contains(QAnyStringView key) const
+#endif
{
if (createSocket())
- return callRemoteMethod<bool>(QLatin1String(Protocol::QSettingsContains), param1);
- return d->settings.contains(param1);
+ return callRemoteMethod<bool>(QLatin1String(Protocol::QSettingsContains), key);
+ return d->settings.contains(key);
}
void QSettingsWrapper::endArray()
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsEndArray));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsEndArray));
else
d->settings.endArray();
}
@@ -203,7 +219,7 @@ void QSettingsWrapper::endArray()
void QSettingsWrapper::endGroup()
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsEndGroup));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsEndGroup));
else
d->settings.endGroup();
}
@@ -222,10 +238,10 @@ QString QSettingsWrapper::fileName() const
return d->settings.fileName();
}
-QSettingsWrapper::Format QSettingsWrapper::format() const
+QSettings::Format QSettingsWrapper::format() const
{
// No need to talk to the server, we've setup the local settings object the same way.
- return static_cast<QSettingsWrapper::Format>(d->settings.format());
+ return d->settings.format();
}
QString QSettingsWrapper::group() const
@@ -249,12 +265,16 @@ QString QSettingsWrapper::organizationName() const
return d->settings.organizationName();
}
-void QSettingsWrapper::remove(const QString &param1)
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+ void QSettingsWrapper::remove(const QString &key)
+#else
+ void QSettingsWrapper::remove(QAnyStringView key)
+#endif
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsRemove), param1, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsRemove), key);
else
- d->settings.remove(param1);
+ d->settings.remove(key);
}
QSettingsWrapper::Scope QSettingsWrapper::scope() const
@@ -266,7 +286,7 @@ QSettingsWrapper::Scope QSettingsWrapper::scope() const
void QSettingsWrapper::setArrayIndex(int param1)
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsSetArrayIndex), qint32(param1), dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsSetArrayIndex), qint32(param1));
else
d->settings.setArrayIndex(param1);
}
@@ -274,17 +294,20 @@ void QSettingsWrapper::setArrayIndex(int param1)
void QSettingsWrapper::setFallbacksEnabled(bool param1)
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsSetFallbacksEnabled), param1, dummy);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsSetFallbacksEnabled), param1);
else
d->settings.setFallbacksEnabled(param1);
}
-
-void QSettingsWrapper::setValue(const QString &param1, const QVariant &param2)
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+void QSettingsWrapper::setValue(const QString &key, const QVariant &value)
+#else
+void QSettingsWrapper::setValue(QAnyStringView key, const QVariant &value)
+#endif
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsSetValue), param1, param2);
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsSetValue), key, value);
else
- d->settings.setValue(param1, param2);
+ d->settings.setValue(key, value);
}
QSettingsWrapper::Status QSettingsWrapper::status() const
@@ -299,27 +322,36 @@ QSettingsWrapper::Status QSettingsWrapper::status() const
void QSettingsWrapper::sync()
{
if (createSocket())
- callRemoteMethod(QLatin1String(Protocol::QSettingsSync));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::QSettingsSync));
else
d->settings.sync();
}
-QVariant QSettingsWrapper::value(const QString &param1, const QVariant &param2) const
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
+QVariant QSettingsWrapper::value(const QString &key, const QVariant &value) const
+#else
+QVariant QSettingsWrapper::value(QAnyStringView key, const QVariant &value) const
+#endif
+{
+ if (createSocket())
+ return callRemoteMethod<QVariant>(QLatin1String(Protocol::QSettingsValue), key, value);
+ return d->settings.value(key, value);
+}
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
+QVariant QSettingsWrapper::value(QAnyStringView key) const
{
if (createSocket())
- return callRemoteMethod<QVariant>(QLatin1String(Protocol::QSettingsValue), param1, param2);
- return d->settings.value(param1, param2);
+ return callRemoteMethod<QVariant>(QLatin1String(Protocol::QSettingsValue), key);
+ return d->settings.value(key);
}
+#endif
// -- private
bool QSettingsWrapper::createSocket() const
{
- if ((d->m_format != QSettings::NativeFormat) && (d->m_format != QSettings::IniFormat)) {
- Q_ASSERT_X(false, Q_FUNC_INFO, "Settings wrapper only supports QSettingsWrapper::NativeFormat"
- " and QSettingsWrapper::IniFormat.");
- }
return (const_cast<QSettingsWrapper *>(this))->connectToServer(QVariantList()
<< d->m_application << d->m_organization << d->m_scope << d->m_format << d->m_filename);
}
diff --git a/src/libs/installer/qsettingswrapper.h b/src/libs/installer/qsettingswrapper.h
index c9e6d6265..f5d428b1e 100644
--- a/src/libs/installer/qsettingswrapper.h
+++ b/src/libs/installer/qsettingswrapper.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -34,6 +34,10 @@
#include <QVariant>
+#include <QSettings>
+
+QT_FORWARD_DECLARE_CLASS(QTextCodec)
+
namespace QInstaller {
class INSTALLER_EXPORT QSettingsWrapper : public RemoteObject
@@ -48,12 +52,6 @@ public:
FormatError
};
- enum Format {
- NativeFormat,
- IniFormat,
- InvalidFormat = 16
- };
-
enum Scope {
UserScope,
SystemScope
@@ -63,21 +61,30 @@ public:
const QString &application = QString(), QObject *parent = 0);
QSettingsWrapper(Scope scope, const QString &organization,
const QString &application = QString(), QObject *parent = 0);
- QSettingsWrapper(Format format, Scope scope, const QString &organization,
+ QSettingsWrapper(QSettings::Format format, Scope scope, const QString &organization,
const QString &application = QString(), QObject *parent = 0);
- QSettingsWrapper(const QString &fileName, Format format, QObject *parent = 0);
+ QSettingsWrapper(const QString &fileName, QSettings::Format format, QObject *parent = 0);
~QSettingsWrapper();
void clear();
void sync();
Status status() const;
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
void beginGroup(const QString &prefix);
+#else
+ void beginGroup(QAnyStringView prefix);
+#endif
void endGroup();
QString group() const;
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
int beginReadArray(const QString &prefix);
void beginWriteArray(const QString &prefix, int size = -1);
+#else
+ int beginReadArray(QAnyStringView prefix);
+ void beginWriteArray(QAnyStringView prefix, int size = -1);
+#endif
void endArray();
void setArrayIndex(int i);
@@ -86,17 +93,27 @@ public:
QStringList childGroups() const;
bool isWritable() const;
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
void setValue(const QString &key, const QVariant &value);
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+#else
+ void setValue(QAnyStringView key, const QVariant &value);
+ QVariant value(QAnyStringView key, const QVariant &defaultValue) const;
+ QVariant value(QAnyStringView key) const;
+#endif
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
void remove(const QString &key);
bool contains(const QString &key) const;
-
+#else
+ void remove(QAnyStringView key);
+ bool contains(QAnyStringView key) const;
+#endif
void setFallbacksEnabled(bool b);
bool fallbacksEnabled() const;
QString fileName() const;
- Format format() const;
+ QSettings::Format format() const;
Scope scope() const;
QString organizationName() const;
QString applicationName() const;
@@ -109,28 +126,27 @@ private: // we cannot support the following functionality
: RemoteObject(QLatin1String(Protocol::QSettings), parent)
{}
+#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
void setIniCodec(QTextCodec * /*codec*/);
void setIniCodec(const char * /*codecName*/);
QTextCodec *iniCodec() const { return 0; }
-
- static void setDefaultFormat(Format /*format*/);
- static Format defaultFormat() { return NativeFormat; }
- static void setSystemIniPath(const QString & /*dir*/);
- static void setUserIniPath(const QString & /*dir*/);
- static void setPath(Format /*format*/, Scope /*scope*/, const QString & /*path*/);
+#endif
+ static void setDefaultFormat(QSettings::Format /*format*/);
+ static QSettings::Format defaultFormat() { return QSettings::NativeFormat; }
+ static void setPath(QSettings::Format /*format*/, Scope /*scope*/, const QString & /*path*/);
typedef QMap<QString, QVariant> SettingsMap;
typedef bool(*ReadFunc)(QIODevice &device, SettingsMap &map);
typedef bool(*WriteFunc)(QIODevice &device, const SettingsMap &map);
- static Format registerFormat(const QString &extension, ReadFunc readFunc, WriteFunc writeFunc,
+ static QSettings::Format registerFormat(const QString &extension, ReadFunc readFunc, WriteFunc writeFunc,
Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
{
Q_UNUSED(extension)
Q_UNUSED(readFunc)
Q_UNUSED(writeFunc)
Q_UNUSED(caseSensitivity)
- return NativeFormat;
+ return QSettings::NativeFormat;
}
private:
diff --git a/src/libs/installer/qtpatch.cpp b/src/libs/installer/qtpatch.cpp
index f72e67867..a29e99f94 100644
--- a/src/libs/installer/qtpatch.cpp
+++ b/src/libs/installer/qtpatch.cpp
@@ -67,11 +67,11 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA
QFileInfo qmake(qmakePath);
if (!qmake.exists()) {
- qmakeOutput->append(QString::fromLatin1("%1 is not existing").arg(qmakePath));
+ qmakeOutput->append(QString::fromLatin1("%1 is not existing").arg(qmakePath).toUtf8());
return qmakeValueHash;
}
if (!qmake.isExecutable()) {
- qmakeOutput->append(QString::fromLatin1("%1 is not executable").arg(qmakePath));
+ qmakeOutput->append(QString::fromLatin1("%1 is not executable").arg(qmakePath).toUtf8());
return qmakeValueHash;
}
@@ -88,7 +88,7 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA
, QString::fromLatin1("Standard output: \"%1\".").arg(QLatin1String(output))
, QString::fromLatin1("Error output: \"%1\".").arg(QLatin1String(process.readAllStandardError()))
};
- qmakeOutput->append(detailedOutput.join(QLatin1Char('\n')));
+ qmakeOutput->append(detailedOutput.join(QLatin1Char('\n')).toUtf8());
return qmakeValueHash;
}
qmakeOutput->append(output);
diff --git a/src/libs/installer/registerfiletypeoperation.cpp b/src/libs/installer/registerfiletypeoperation.cpp
index c1ee7a038..852714dfb 100644
--- a/src/libs/installer/registerfiletypeoperation.cpp
+++ b/src/libs/installer/registerfiletypeoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -105,7 +105,7 @@ bool RegisterFileTypeOperation::performOperation()
allUsers = true;
QSettingsWrapper settings(QLatin1String(allUsers ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER")
- , QSettingsWrapper::NativeFormat);
+ , QSettings::NativeFormat);
const QString classesProgId = QString::fromLatin1("Software/Classes/") + m_progId;
const QString classesFileType = QString::fromLatin1("Software/Classes/.%2").arg(args.at(0));
@@ -153,7 +153,7 @@ bool RegisterFileTypeOperation::undoOperation()
{
#ifdef Q_OS_WIN
ensureOptionalArgumentsRead();
- if (parseUndoOperationArguments().count() > 0)
+ if (skipUndoOperation())
return true;
QStringList args = arguments();
@@ -166,7 +166,7 @@ bool RegisterFileTypeOperation::undoOperation()
allUsers = true;
QSettingsWrapper settings(QLatin1String(allUsers ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER")
- , QSettingsWrapper::NativeFormat);
+ , QSettings::NativeFormat);
const QString classesProgId = QString::fromLatin1("Software/Classes/") + m_progId;
const QString classesFileType = QString::fromLatin1("Software/Classes/.%2").arg(args.at(0));
diff --git a/src/libs/installer/registerfiletypeoperation.h b/src/libs/installer/registerfiletypeoperation.h
index 8850ab44b..c8fd454fe 100644
--- a/src/libs/installer/registerfiletypeoperation.h
+++ b/src/libs/installer/registerfiletypeoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,10 +40,10 @@ class INSTALLER_EXPORT RegisterFileTypeOperation : public QObject, public Operat
public:
explicit RegisterFileTypeOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
private:
void ensureOptionalArgumentsRead();
diff --git a/src/libs/installer/remoteclient_p.h b/src/libs/installer/remoteclient_p.h
index e1809e0af..3dec97c95 100644
--- a/src/libs/installer/remoteclient_p.h
+++ b/src/libs/installer/remoteclient_p.h
@@ -40,8 +40,8 @@
#include <QCoreApplication>
#include <QDeadlineTimer>
+#include <QRecursiveMutex>
#include <QTimer>
-#include <QMutex>
#include <QThread>
namespace QInstaller {
@@ -55,7 +55,6 @@ public:
RemoteClientPrivate(RemoteClient *parent)
: RemoteObject(QLatin1String("RemoteClientPrivate"))
, q_ptr(parent)
- , m_mutex(QMutex::Recursive)
, m_startServerAs(Protocol::StartAs::User)
, m_serverStarted(false)
, m_active(false)
@@ -201,7 +200,7 @@ public:
private:
RemoteClient *q_ptr;
- QMutex m_mutex;
+ QRecursiveMutex m_mutex;
QString m_socketName;
Protocol::StartAs m_startServerAs;
bool m_serverStarted;
diff --git a/src/libs/installer/remotefileengine.cpp b/src/libs/installer/remotefileengine.cpp
index 3c9ee217f..7a5e91682 100644
--- a/src/libs/installer/remotefileengine.cpp
+++ b/src/libs/installer/remotefileengine.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,7 +31,7 @@
#include "protocol.h"
#include "remoteclient.h"
-#include <QRegExp>
+#include <QRegularExpression>
namespace QInstaller {
@@ -48,17 +48,17 @@ QAbstractFileEngine* RemoteFileEngineHandler::create(const QString &fileName) co
if (!RemoteClient::instance().isActive())
return 0;
- static QRegExp re(QLatin1String("^[a-z0-9]*://.*$"));
- if (re.exactMatch(fileName)) // stuff like installer://
+ static const QRegularExpression re(QLatin1String("^[a-z0-9]*://.*$"));
+ if (re.match(fileName).hasMatch()) // stuff like installer://
return 0;
if (fileName.isEmpty() || fileName.startsWith(QLatin1String(":")))
return 0; // empty filename or Qt resource
- QScopedPointer<RemoteFileEngine> client(new RemoteFileEngine());
+ std::unique_ptr<RemoteFileEngine> client(new RemoteFileEngine());
client->setFileName(fileName);
if (client->isConnectedToServer())
- return client.take();
+ return client.release();
return 0;
}
@@ -313,6 +313,7 @@ bool RemoteFileEngine::link(const QString &newName)
/*!
\reimp
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
bool RemoteFileEngine::mkdir(const QString &dirName, bool createParentDirectories) const
{
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
@@ -320,18 +321,38 @@ bool RemoteFileEngine::mkdir(const QString &dirName, bool createParentDirectorie
dirName, createParentDirectories);
}
return m_fileEngine.mkdir(dirName, createParentDirectories);
+
+}
+#else
+bool RemoteFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
+ std::optional<QFile::Permissions> permissions) const
+{
+ if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
+ return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineMkdir),
+ dirName, createParentDirectories);
+ }
+ return m_fileEngine.mkdir(dirName, createParentDirectories, permissions);
}
+#endif
/*!
\reimp
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
bool RemoteFileEngine::open(QIODevice::OpenMode mode)
+#else
+bool RemoteFileEngine::open(QIODevice::OpenMode mode, std::optional<QFile::Permissions> permissions)
+#endif
{
if (connectToServer()) {
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineOpen),
static_cast<qint32>(mode | QIODevice::Unbuffered));
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
return m_fileEngine.open(mode | QIODevice::Unbuffered);
+#else
+ return m_fileEngine.open(mode | QIODevice::Unbuffered, permissions);
+#endif
}
/*!
@@ -418,8 +439,7 @@ bool RemoteFileEngine::seek(qint64 offset)
void RemoteFileEngine::setFileName(const QString &fileName)
{
if (connectToServer()) {
- callRemoteMethod(QString::fromLatin1(Protocol::QAbstractFileEngineSetFileName), fileName,
- dummy);
+ callRemoteMethodDefaultReply(QString::fromLatin1(Protocol::QAbstractFileEngineSetFileName), fileName);
}
m_fileEngine.setFileName(fileName);
}
diff --git a/src/libs/installer/remotefileengine.h b/src/libs/installer/remotefileengine.h
index 9544403f7..31ae67d77 100644
--- a/src/libs/installer/remotefileengine.h
+++ b/src/libs/installer/remotefileengine.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -42,7 +42,7 @@ class INSTALLER_EXPORT RemoteFileEngineHandler : public QAbstractFileEngineHandl
public:
RemoteFileEngineHandler() : QAbstractFileEngineHandler() {}
- QAbstractFileEngine* create(const QString &fileName) const Q_DECL_OVERRIDE;
+ QAbstractFileEngine* create(const QString &fileName) const override;
};
class RemoteFileEngine : public RemoteObject, public QAbstractFileEngine
@@ -53,50 +53,60 @@ public:
RemoteFileEngine();
~RemoteFileEngine();
- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
- bool close() Q_DECL_OVERRIDE;
- bool flush() Q_DECL_OVERRIDE;
- bool syncToDisk() Q_DECL_OVERRIDE;
- qint64 size() const Q_DECL_OVERRIDE;
- qint64 pos() const Q_DECL_OVERRIDE;
- bool seek(qint64 offset) Q_DECL_OVERRIDE;
- bool isSequential() const Q_DECL_OVERRIDE;
- bool remove() Q_DECL_OVERRIDE;
- bool copy(const QString &newName) Q_DECL_OVERRIDE;
- bool rename(const QString &newName) Q_DECL_OVERRIDE;
- bool renameOverwrite(const QString &newName) Q_DECL_OVERRIDE;
- bool link(const QString &newName) Q_DECL_OVERRIDE;
- bool mkdir(const QString &dirName, bool createParentDirectories) const Q_DECL_OVERRIDE;
- bool rmdir(const QString &dirName, bool recurseParentDirectories) const Q_DECL_OVERRIDE;
- bool setSize(qint64 size) Q_DECL_OVERRIDE;
- bool caseSensitive() const Q_DECL_OVERRIDE;
- bool isRelativePath() const Q_DECL_OVERRIDE;
- QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE;
- FileFlags fileFlags(FileFlags type = FileInfoAll) const Q_DECL_OVERRIDE;
- bool setPermissions(uint perms) Q_DECL_OVERRIDE;
- QString fileName(FileName file = DefaultName) const Q_DECL_OVERRIDE;
- uint ownerId(FileOwner owner) const Q_DECL_OVERRIDE;
- QString owner(FileOwner owner) const Q_DECL_OVERRIDE;
- QDateTime fileTime(FileTime time) const Q_DECL_OVERRIDE;
- void setFileName(const QString &fileName) Q_DECL_OVERRIDE;
- int handle() const Q_DECL_OVERRIDE;
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
+ bool open(QIODevice::OpenMode mode) override;
+#else
+ bool open(QIODevice::OpenMode mode,
+ std::optional<QFile::Permissions> permissions = std::nullopt) override;
+#endif
+ bool close() override;
+ bool flush() override;
+ bool syncToDisk() override;
+ qint64 size() const override;
+ qint64 pos() const override;
+ bool seek(qint64 offset) override;
+ bool isSequential() const override;
+ bool remove() override;
+ bool copy(const QString &newName) override;
+ bool rename(const QString &newName) override;
+ bool renameOverwrite(const QString &newName) override;
+ bool link(const QString &newName) override;
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
+ bool mkdir(const QString &dirName, bool createParentDirectories) const override;
+#else
+ bool mkdir(const QString &dirName, bool createParentDirectories,
+ std::optional<QFile::Permissions> permissions = std::nullopt) const override;
+#endif
+ bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
+ bool setSize(qint64 size) override;
+ bool caseSensitive() const override;
+ bool isRelativePath() const override;
+ QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
+ FileFlags fileFlags(FileFlags type = FileInfoAll) const override;
+ bool setPermissions(uint perms) override;
+ QString fileName(FileName file = DefaultName) const override;
+ uint ownerId(FileOwner owner) const override;
+ QString owner(FileOwner owner) const override;
+ QDateTime fileTime(FileTime time) const override;
+ void setFileName(const QString &fileName) override;
+ int handle() const override;
bool atEnd() const;
uchar *map(qint64, qint64, QFile::MemoryMapFlags) { return 0; }
bool unmap(uchar *) { return true; }
- Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) Q_DECL_OVERRIDE;
- Iterator *endEntryList() Q_DECL_OVERRIDE;
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
+ Iterator *endEntryList() override;
- qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
- qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
- qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE;
+ qint64 read(char *data, qint64 maxlen) override;
+ qint64 readLine(char *data, qint64 maxlen) override;
+ qint64 write(const char *data, qint64 len) override;
QFile::FileError error() const;
QString errorString() const;
bool extension(Extension extension, const ExtensionOption *option = 0,
- ExtensionReturn *output = 0) Q_DECL_OVERRIDE;
- bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE;
+ ExtensionReturn *output = 0) override;
+ bool supportsExtension(Extension extension) const override;
private:
QFSFileEngine m_fileEngine;
diff --git a/src/libs/installer/remoteobject.cpp b/src/libs/installer/remoteobject.cpp
index f6f0f2bfe..b4dd0cbb7 100644
--- a/src/libs/installer/remoteobject.cpp
+++ b/src/libs/installer/remoteobject.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -46,7 +46,6 @@ namespace QInstaller {
RemoteObject::RemoteObject(const QString &wrappedType, QObject *parent)
: QObject(parent)
- , dummy(nullptr)
, m_type(wrappedType)
, m_socket(nullptr)
{
@@ -58,8 +57,8 @@ RemoteObject::~RemoteObject()
{
if (m_socket) {
if (QThread::currentThread() == m_socket->thread()) {
- if (m_type != QLatin1String("RemoteClientPrivate")) {
- writeData(QLatin1String(Protocol::Destroy), m_type, dummy, dummy);
+ if ((m_type != QLatin1String("RemoteClientPrivate"))
+ && (m_socket->state() == QLocalSocket::ConnectedState)) {
while (m_socket->bytesToWrite()) {
// QAbstractSocket::waitForBytesWritten() may fail randomly on Windows, use
// an event loop and the bytesWritten() signal instead as the docs suggest.
@@ -67,7 +66,9 @@ RemoteObject::~RemoteObject()
connect(m_socket, &QLocalSocket::bytesWritten, &loop, &QEventLoop::quit);
loop.exec();
}
- if (!m_socket->waitForDisconnected()) {
+ m_socket->disconnectFromServer();
+ if (!(m_socket->state() == QLocalSocket::UnconnectedState
+ || m_socket->waitForDisconnected())) {
qCWarning(lcServer) << "Error while disconnecting from remote server:"
<< m_socket->error();
}
@@ -120,6 +121,11 @@ bool RemoteObject::connectToServer(const QVariantList &arguments)
sendPacket(m_socket, Protocol::Create, data);
m_socket->flush();
+ while (m_socket->bytesToWrite())
+ m_socket->waitForBytesWritten();
+
+ const QString reply = readData<QString>(QLatin1String(Protocol::Create));
+ Q_ASSERT(reply == QLatin1String(Protocol::DefaultReply));
return true;
}
@@ -133,9 +139,4 @@ bool RemoteObject::isConnectedToServer() const
return false;
}
-void RemoteObject::callRemoteMethod(const QString &name)
-{
- writeData(name, dummy, dummy, dummy);
-}
-
} // namespace QInstaller
diff --git a/src/libs/installer/remoteobject.h b/src/libs/installer/remoteobject.h
index ecd86c984..ddd512588 100644
--- a/src/libs/installer/remoteobject.h
+++ b/src/libs/installer/remoteobject.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -35,8 +35,10 @@
#include <QCoreApplication>
#include <QDataStream>
-#include <QObject>
#include <QLocalSocket>
+#include <QObject>
+#include <QVariant>
+
namespace QInstaller {
@@ -50,45 +52,65 @@ public:
virtual ~RemoteObject() = 0;
bool isConnectedToServer() const;
- void callRemoteMethod(const QString &name);
- template<typename T1, typename T2>
- void callRemoteMethod(const QString &name, const T1 &arg, const T2 &arg2)
+ template<typename... Args>
+ void callRemoteMethodDefaultReply(const QString &name, const Args&... args)
{
- writeData(name, arg, arg2, dummy);
+ const QString reply = sendReceivePacket<QString>(name, args...);
+ Q_ASSERT(reply == QLatin1String(Protocol::DefaultReply));
}
- template<typename T1, typename T2, typename T3>
- void callRemoteMethod(const QString &name, const T1 &arg, const T2 &arg2, const T3 & arg3)
+ template<typename T, typename... Args>
+ T callRemoteMethod(const QString &name, const Args&... args) const
{
- writeData(name, arg, arg2, arg3);
+ return sendReceivePacket<T>(name, args...);
}
- template<typename T>
- T callRemoteMethod(const QString &name) const
+protected:
+ bool authorize();
+ bool connectToServer(const QVariantList &arguments = QVariantList());
+
+private:
+
+ template<typename T, typename... Args>
+ T sendReceivePacket(const QString &name, const Args&... args) const
{
- return callRemoteMethod<T>(name, dummy, dummy, dummy);
+ writeData(name, args...);
+ while (m_socket->bytesToWrite())
+ m_socket->waitForBytesWritten();
+
+ return readData<T>(name);
}
- template<typename T, typename T1>
- T callRemoteMethod(const QString &name, const T1 &arg) const
+ template <class T> int writeObject(QDataStream& out, const T& t) const
{
- return callRemoteMethod<T>(name, arg, dummy, dummy);
+ static_assert(!std::is_pointer<T>::value, "Pointer passed to remote server");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ out << t;
+#else
+ if constexpr (std::is_same<T, QAnyStringView>::value)
+ out << t.toString();
+ else
+ out << t;
+#endif
+
+ return 0;
}
- template<typename T, typename T1, typename T2>
- T callRemoteMethod(const QString &name, const T1 & arg, const T2 &arg2) const
+ template<typename... Args>
+ void writeData(const QString &name, const Args&... args) const
{
- return callRemoteMethod<T>(name, arg, arg2, dummy);
+ QByteArray data;
+ QDataStream out(&data, QIODevice::WriteOnly);
+
+ (void)std::initializer_list<int>{writeObject(out, args)...};
+ sendPacket(m_socket, name.toLatin1(), data);
+ m_socket->flush();
}
- template<typename T, typename T1, typename T2, typename T3>
- T callRemoteMethod(const QString &name, const T1 &arg, const T2 &arg2, const T3 &arg3) const
+ template<typename T>
+ T readData(const QString &name) const
{
- writeData(name, arg, arg2, arg3);
- while (m_socket->bytesToWrite())
- m_socket->waitForBytesWritten();
-
QByteArray command;
QByteArray data;
while (!receivePacket(m_socket, &command, &data)) {
@@ -110,46 +132,6 @@ public:
return result;
}
-protected:
- bool authorize();
- bool connectToServer(const QVariantList &arguments = QVariantList());
-
- // Use this structure to allow derived classes to manipulate the template
- // function signature of the callRemoteMethod templates, since most of the
- // generated functions will differ in return type rather given arguments.
- struct Dummy {}; Dummy *dummy;
-
-private:
- template<typename T> bool isValueType(T) const
- {
- return true;
- }
-
- template<typename T> bool isValueType(T *dummy) const
- {
- // Force compiler error while passing anything different then Dummy* to the function.
- // It really doesn't make sense to send any pointer over to the server, so bail early.
- Q_UNUSED(static_cast<Dummy*> (dummy))
- return false;
- }
-
- template<typename T1, typename T2, typename T3>
- void writeData(const QString &name, const T1 &arg, const T2 &arg2, const T3 &arg3) const
- {
- QByteArray data;
- QDataStream out(&data, QIODevice::WriteOnly);
-
- if (isValueType(arg))
- out << arg;
- if (isValueType(arg2))
- out << arg2;
- if (isValueType(arg3))
- out << arg3;
-
- sendPacket(m_socket, name.toLatin1(), data);
- m_socket->flush();
- }
-
private:
QString m_type;
QLocalSocket *m_socket;
diff --git a/src/libs/installer/remoteserver_p.h b/src/libs/installer/remoteserver_p.h
index e39350f2f..0723c7be6 100644
--- a/src/libs/installer/remoteserver_p.h
+++ b/src/libs/installer/remoteserver_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -75,7 +75,7 @@ private slots:
}
private:
- void incomingConnection(quintptr socketDescriptor) Q_DECL_OVERRIDE {
+ void incomingConnection(quintptr socketDescriptor) override {
if (m_shutdown)
return;
diff --git a/src/libs/installer/remoteserverconnection.cpp b/src/libs/installer/remoteserverconnection.cpp
index 9e141ea48..51619983e 100644
--- a/src/libs/installer/remoteserverconnection.cpp
+++ b/src/libs/installer/remoteserverconnection.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -46,13 +46,62 @@ namespace QInstaller {
/*!
\inmodule QtInstallerFramework
- \class QInstaller::RemoteServerConnection
+ \class QInstaller::QProcessSignalReceiver
\internal
*/
/*!
\inmodule QtInstallerFramework
- \class QInstaller::QProcessSignalReceiver
+ \class QInstaller::RemoteServerReply
+ \internal
+ \brief The RemoteServerReply class is used for sending a reply to a local socket.
+
+ The class ensures exactly one reply is sent in the lifetime of an object
+ instantiated from this class. If the calling client has not explicitly sent
+ a reply, a default reply is automatically sent on destruction.
+*/
+
+/*!
+ Constructs reply object for \a socket.
+*/
+RemoteServerReply::RemoteServerReply(QLocalSocket *socket)
+ : m_socket(socket)
+ , m_sent(false)
+{}
+
+/*!
+ Destroys the object and sends the default reply, if
+ no other replies have been sent.
+*/
+RemoteServerReply::~RemoteServerReply()
+{
+ send(QString::fromLatin1(Protocol::DefaultReply));
+}
+
+/*!
+ \fn template <typename T> QInstaller::RemoteServerReply::send(const T &data)
+
+ Sends a reply packet with \a¸ data to the socket. If a reply
+ has been already sent, this function does not send another.
+*/
+template <typename T>
+void RemoteServerReply::send(const T &data)
+{
+ if (m_sent || m_socket->state() != QLocalSocket::ConnectedState)
+ return;
+
+ QByteArray result;
+ QDataStream returnStream(&result, QIODevice::WriteOnly);
+ returnStream << data;
+
+ sendPacket(m_socket, Protocol::Reply, result);
+ m_socket->flush();
+ m_sent = true;
+}
+
+/*!
+ \inmodule QtInstallerFramework
+ \class QInstaller::RemoteServerConnection
\internal
*/
@@ -60,10 +109,10 @@ RemoteServerConnection::RemoteServerConnection(qintptr socketDescriptor, const Q
QObject *parent)
: QThread(parent)
, m_socketDescriptor(socketDescriptor)
+ , m_authorizationKey(key)
, m_process(nullptr)
, m_engine(nullptr)
, m_archive(nullptr)
- , m_authorizationKey(key)
, m_processSignalReceiver(nullptr)
, m_archiveSignalReceiver(nullptr)
{
@@ -106,18 +155,18 @@ void RemoteServerConnection::run()
stream.setDevice(&buf);
StreamChecker streamChecker(&stream);
+ RemoteServerReply reply(&socket);
+
if (authorized && command == QLatin1String(Protocol::Shutdown)) {
authorized = false;
- sendData(&socket, true);
- socket.flush();
+ reply.send(true);
socket.close();
emit shutdownRequested();
return;
} else if (command == QLatin1String(Protocol::Authorize)) {
QString key;
stream >> key;
- sendData(&socket, (authorized = (key == m_authorizationKey)));
- socket.flush();
+ reply.send(authorized = (key == m_authorizationKey));
if (!authorized) {
socket.close();
return;
@@ -145,56 +194,28 @@ void RemoteServerConnection::run()
settings.reset(new PermissionSettings(fileName.toString(), QSettings::Format(format.toInt())));
}
} else if (type == QLatin1String(Protocol::QProcess)) {
- if (m_process)
- m_process->deleteLater();
- m_process = new QProcess;
- m_processSignalReceiver = new QProcessSignalReceiver(m_process);
+ m_process.reset(new QProcess);
+ m_processSignalReceiver = new QProcessSignalReceiver(m_process.get());
} else if (type == QLatin1String(Protocol::QAbstractFileEngine)) {
- if (m_engine)
- delete m_engine;
- m_engine = new QFSFileEngine;
+ m_engine.reset(new QFSFileEngine);
} else if (type == QLatin1String(Protocol::AbstractArchive)) {
#ifdef IFW_LIBARCHIVE
- if (m_archive)
- m_archive->deleteLater();
- m_archive = new LibArchiveArchive;
- m_archiveSignalReceiver = new AbstractArchiveSignalReceiver(static_cast<LibArchiveArchive *>(m_archive));
+ m_archive.reset(new LibArchiveArchive);
+ m_archiveSignalReceiver = new AbstractArchiveSignalReceiver(
+ static_cast<LibArchiveArchive *>(m_archive.get()));
#else
Q_ASSERT_X(false, Q_FUNC_INFO, "No compatible archive handler exists for protocol.");
#endif
+ } else {
+ qCDebug(QInstaller::lcServer) << "Unknown type for Create command:" << type;
}
continue;
}
- if (command == QLatin1String(Protocol::Destroy)) {
- QString type;
- stream >> type;
- if (type == QLatin1String(Protocol::QSettings)) {
- settings.reset();
- } else if (type == QLatin1String(Protocol::QProcess)) {
- m_processSignalReceiver->m_receivedSignals.clear();
- m_process->deleteLater();
- m_process = nullptr;
- } else if (type == QLatin1String(Protocol::QAbstractFileEngine)) {
- delete m_engine;
- m_engine = nullptr;
- } else if (type == QLatin1String(Protocol::AbstractArchive)) {
-#ifdef IFW_LIBARCHIVE
- m_archiveSignalReceiver->m_receivedSignals.clear();
- m_archive->deleteLater();
- m_archive = nullptr;
-#else
- Q_ASSERT_X(false, Q_FUNC_INFO, "No compatible archive handler exists for protocol.");
-#endif
- }
- return;
- }
-
if (command == QLatin1String(Protocol::GetQProcessSignals)) {
if (m_processSignalReceiver) {
QMutexLocker _(&m_processSignalReceiver->m_lock);
- sendData(&socket, m_processSignalReceiver->m_receivedSignals);
- socket.flush();
+ reply.send(m_processSignalReceiver->m_receivedSignals);
m_processSignalReceiver->m_receivedSignals.clear();
}
continue;
@@ -202,8 +223,7 @@ void RemoteServerConnection::run()
#ifdef IFW_LIBARCHIVE
if (m_archiveSignalReceiver) {
QMutexLocker _(&m_archiveSignalReceiver->m_lock);
- sendData(&socket, m_archiveSignalReceiver->m_receivedSignals);
- socket.flush();
+ reply.send(m_archiveSignalReceiver->m_receivedSignals);
m_archiveSignalReceiver->m_receivedSignals.clear();
}
continue;
@@ -213,52 +233,41 @@ void RemoteServerConnection::run()
}
if (command.startsWith(QLatin1String(Protocol::QProcess))) {
- handleQProcess(&socket, command, stream);
+ handleQProcess(&reply, command, stream);
} else if (command.startsWith(QLatin1String(Protocol::QSettings))) {
- handleQSettings(&socket, command, stream, settings.data());
+ handleQSettings(&reply, command, stream, settings.data());
} else if (command.startsWith(QLatin1String(Protocol::QAbstractFileEngine))) {
- handleQFSFileEngine(&socket, command, stream);
+ handleQFSFileEngine(&reply, command, stream);
} else if (command.startsWith(QLatin1String(Protocol::AbstractArchive))) {
- handleArchive(&socket, command, stream);
+ handleArchive(&reply, command, stream);
} else {
qCDebug(QInstaller::lcServer) << "Unknown command:" << command;
}
- socket.flush();
} else {
// authorization failed, connection not wanted
socket.close();
- qCDebug(QInstaller::lcServer) << "Unknown command:" << command;
+ qCDebug(QInstaller::lcServer) << "Authorization failed.";
return;
}
}
}
-template <typename T>
-void RemoteServerConnection::sendData(QIODevice *device, const T &data)
-{
- QByteArray result;
- QDataStream returnStream(&result, QIODevice::WriteOnly);
- returnStream << data;
-
- sendPacket(device, Protocol::Reply, result);
-}
-
-void RemoteServerConnection::handleQProcess(QIODevice *socket, const QString &command, QDataStream &data)
+void RemoteServerConnection::handleQProcess(RemoteServerReply *reply, const QString &command, QDataStream &data)
{
if (command == QLatin1String(Protocol::QProcessCloseWriteChannel)) {
m_process->closeWriteChannel();
} else if (command == QLatin1String(Protocol::QProcessExitCode)) {
- sendData(socket, m_process->exitCode());
+ reply->send(m_process->exitCode());
} else if (command == QLatin1String(Protocol::QProcessExitStatus)) {
- sendData(socket, static_cast<qint32> (m_process->exitStatus()));
+ reply->send(static_cast<qint32> (m_process->exitStatus()));
} else if (command == QLatin1String(Protocol::QProcessKill)) {
m_process->kill();
} else if (command == QLatin1String(Protocol::QProcessReadAll)) {
- sendData(socket, m_process->readAll());
+ reply->send(m_process->readAll());
} else if (command == QLatin1String(Protocol::QProcessReadAllStandardOutput)) {
- sendData(socket, m_process->readAllStandardOutput());
+ reply->send(m_process->readAllStandardOutput());
} else if (command == QLatin1String(Protocol::QProcessReadAllStandardError)) {
- sendData(socket, m_process->readAllStandardError());
+ reply->send(m_process->readAllStandardError());
} else if (command == QLatin1String(Protocol::QProcessStartDetached)) {
QString program;
QStringList arguments;
@@ -269,7 +278,18 @@ void RemoteServerConnection::handleQProcess(QIODevice *socket, const QString &co
qint64 pid = -1;
bool success = QInstaller::startDetached(program, arguments, workingDirectory, &pid);
- sendData(socket, qMakePair< bool, qint64>(success, pid));
+ reply->send(QPair<bool, qint64>(success, pid));
+ } else if (command == QLatin1String(Protocol::QProcessStartDetached2)) {
+ QString program;
+ QStringList arguments;
+ QString workingDirectory;
+ data >> program;
+ data >> arguments;
+ data >> workingDirectory;
+
+ qint64 pid = -1;
+ bool success = QProcess::startDetached(program, arguments, workingDirectory, &pid);
+ reply->send(QPair<bool, qint64>(success, pid));
} else if (command == QLatin1String(Protocol::QProcessSetWorkingDirectory)) {
QString dir;
data >> dir;
@@ -279,7 +299,7 @@ void RemoteServerConnection::handleQProcess(QIODevice *socket, const QString &co
data >> env;
m_process->setEnvironment(env);
} else if (command == QLatin1String(Protocol::QProcessEnvironment)) {
- sendData(socket, m_process->environment());
+ reply->send(m_process->environment());
} else if (command == QLatin1String(Protocol::QProcessStart3Arg)) {
QString program;
QStringList arguments;
@@ -293,25 +313,25 @@ void RemoteServerConnection::handleQProcess(QIODevice *socket, const QString &co
qint32 mode;
data >> program;
data >> mode;
- m_process->start(program, static_cast<QIODevice::OpenMode> (mode));
+ m_process->start(program, {}, static_cast<QIODevice::OpenMode> (mode));
} else if (command == QLatin1String(Protocol::QProcessState)) {
- sendData(socket, static_cast<qint32> (m_process->state()));
+ reply->send(static_cast<qint32> (m_process->state()));
} else if (command == QLatin1String(Protocol::QProcessTerminate)) {
m_process->terminate();
} else if (command == QLatin1String(Protocol::QProcessWaitForFinished)) {
qint32 msecs;
data >> msecs;
- sendData(socket, m_process->waitForFinished(msecs));
+ reply->send(m_process->waitForFinished(msecs));
} else if (command == QLatin1String(Protocol::QProcessWaitForStarted)) {
qint32 msecs;
data >> msecs;
- sendData(socket, m_process->waitForStarted(msecs));
+ reply->send(m_process->waitForStarted(msecs));
} else if (command == QLatin1String(Protocol::QProcessWorkingDirectory)) {
- sendData(socket, m_process->workingDirectory());
+ reply->send(m_process->workingDirectory());
} else if (command == QLatin1String(Protocol::QProcessErrorString)) {
- sendData(socket, m_process->errorString());
+ reply->send(m_process->errorString());
} else if (command == QLatin1String(Protocol::QProcessReadChannel)) {
- sendData(socket, static_cast<qint32> (m_process->readChannel()));
+ reply->send(static_cast<qint32> (m_process->readChannel()));
} else if (command == QLatin1String(Protocol::QProcessSetReadChannel)) {
qint32 processChannel;
data >> processChannel;
@@ -319,9 +339,9 @@ void RemoteServerConnection::handleQProcess(QIODevice *socket, const QString &co
} else if (command == QLatin1String(Protocol::QProcessWrite)) {
QByteArray byteArray;
data >> byteArray;
- sendData(socket, m_process->write(byteArray));
+ reply->send(m_process->write(byteArray));
} else if (command == QLatin1String(Protocol::QProcessProcessChannelMode)) {
- sendData(socket, static_cast<qint32> (m_process->processChannelMode()));
+ reply->send(static_cast<qint32> (m_process->processChannelMode()));
} else if (command == QLatin1String(Protocol::QProcessSetProcessChannelMode)) {
qint32 processChannel;
data >> processChannel;
@@ -339,14 +359,14 @@ void RemoteServerConnection::handleQProcess(QIODevice *socket, const QString &co
}
}
-void RemoteServerConnection::handleQSettings(QIODevice *socket, const QString &command,
+void RemoteServerConnection::handleQSettings(RemoteServerReply *reply, const QString &command,
QDataStream &data, PermissionSettings *settings)
{
if (!settings)
return;
if (command == QLatin1String(Protocol::QSettingsAllKeys)) {
- sendData(socket, settings->allKeys());
+ reply->send(settings->allKeys());
} else if (command == QLatin1String(Protocol::QSettingsBeginGroup)) {
QString prefix;
data >> prefix;
@@ -360,29 +380,29 @@ void RemoteServerConnection::handleQSettings(QIODevice *socket, const QString &c
} else if (command == QLatin1String(Protocol::QSettingsBeginReadArray)) {
QString prefix;
data >> prefix;
- sendData(socket, settings->beginReadArray(prefix));
+ reply->send(settings->beginReadArray(prefix));
} else if (command == QLatin1String(Protocol::QSettingsChildGroups)) {
- sendData(socket, settings->childGroups());
+ reply->send(settings->childGroups());
} else if (command == QLatin1String(Protocol::QSettingsChildKeys)) {
- sendData(socket, settings->childKeys());
+ reply->send(settings->childKeys());
} else if (command == QLatin1String(Protocol::QSettingsClear)) {
settings->clear();
} else if (command == QLatin1String(Protocol::QSettingsContains)) {
QString key;
data >> key;
- sendData(socket, settings->contains(key));
+ reply->send(settings->contains(key));
} else if (command == QLatin1String(Protocol::QSettingsEndArray)) {
settings->endArray();
} else if (command == QLatin1String(Protocol::QSettingsEndGroup)) {
settings->endGroup();
} else if (command == QLatin1String(Protocol::QSettingsFallbacksEnabled)) {
- sendData(socket, settings->fallbacksEnabled());
+ reply->send(settings->fallbacksEnabled());
} else if (command == QLatin1String(Protocol::QSettingsFileName)) {
- sendData(socket, settings->fileName());
+ reply->send(settings->fileName());
} else if (command == QLatin1String(Protocol::QSettingsGroup)) {
- sendData(socket, settings->group());
+ reply->send(settings->group());
} else if (command == QLatin1String(Protocol::QSettingsIsWritable)) {
- sendData(socket, settings->isWritable());
+ reply->send(settings->isWritable());
} else if (command == QLatin1String(Protocol::QSettingsRemove)) {
QString key;
data >> key;
@@ -396,7 +416,7 @@ void RemoteServerConnection::handleQSettings(QIODevice *socket, const QString &c
data >> b;
settings->setFallbacksEnabled(b);
} else if (command == QLatin1String(Protocol::QSettingsStatus)) {
- sendData(socket, settings->status());
+ reply->send(settings->status());
} else if (command == QLatin1String(Protocol::QSettingsSync)) {
settings->sync();
} else if (command == QLatin1String(Protocol::QSettingsSetValue)) {
@@ -409,26 +429,27 @@ void RemoteServerConnection::handleQSettings(QIODevice *socket, const QString &c
QString key;
QVariant defaultValue;
data >> key;
- data >> defaultValue;
- sendData(socket, settings->value(key, defaultValue));
+ if (!data.atEnd())
+ data >> defaultValue;
+ reply->send(settings->value(key, defaultValue));
} else if (command == QLatin1String(Protocol::QSettingsOrganizationName)) {
- sendData(socket, settings->organizationName());
+ reply->send(settings->organizationName());
} else if (command == QLatin1String(Protocol::QSettingsApplicationName)) {
- sendData(socket, settings->applicationName());
+ reply->send(settings->applicationName());
} else if (!command.isEmpty()) {
qCDebug(QInstaller::lcServer) << "Unknown QSettings command:" << command;
}
}
-void RemoteServerConnection::handleQFSFileEngine(QIODevice *socket, const QString &command,
+void RemoteServerConnection::handleQFSFileEngine(RemoteServerReply *reply, const QString &command,
QDataStream &data)
{
if (command == QLatin1String(Protocol::QAbstractFileEngineAtEnd)) {
- sendData(socket, m_engine->atEnd());
+ reply->send(m_engine->atEnd());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineCaseSensitive)) {
- sendData(socket, m_engine->caseSensitive());
+ reply->send(m_engine->caseSensitive());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineClose)) {
- sendData(socket, m_engine->close());
+ reply->send(m_engine->close());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineCopy)) {
QString newName;
data >>newName;
@@ -436,90 +457,99 @@ void RemoteServerConnection::handleQFSFileEngine(QIODevice *socket, const QStrin
// QFileSystemEngine::copyFile() is currently unimplemented on Linux,
// copy using QFile instead of directly with QFSFileEngine.
QFile file(m_engine->fileName(QAbstractFileEngine::AbsoluteName));
- sendData(socket, file.copy(newName));
+ reply->send(file.copy(newName));
#else
- sendData(socket, m_engine->copy(newName));
+ reply->send(m_engine->copy(newName));
#endif
} else if (command == QLatin1String(Protocol::QAbstractFileEngineEntryList)) {
qint32 filters;
QStringList filterNames;
data >>filters;
data >>filterNames;
- sendData(socket, m_engine->entryList(static_cast<QDir::Filters> (filters), filterNames));
+ reply->send(m_engine->entryList(static_cast<QDir::Filters> (filters), filterNames));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineError)) {
- sendData(socket, static_cast<qint32> (m_engine->error()));
+ reply->send(static_cast<qint32> (m_engine->error()));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineErrorString)) {
- sendData(socket, m_engine->errorString());
+ reply->send(m_engine->errorString());
}
else if (command == QLatin1String(Protocol::QAbstractFileEngineFileFlags)) {
qint32 flags;
data >>flags;
flags = m_engine->fileFlags(static_cast<QAbstractFileEngine::FileFlags>(flags));
- sendData(socket, static_cast<qint32>(flags));
+ reply->send(static_cast<qint32>(flags));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineFileName)) {
qint32 file;
data >>file;
- sendData(socket, m_engine->fileName(static_cast<QAbstractFileEngine::FileName> (file)));
+ reply->send(m_engine->fileName(static_cast<QAbstractFileEngine::FileName> (file)));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineFlush)) {
- sendData(socket, m_engine->flush());
+ reply->send(m_engine->flush());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineHandle)) {
- sendData(socket, m_engine->handle());
+ reply->send(m_engine->handle());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineIsRelativePath)) {
- sendData(socket, m_engine->isRelativePath());
+ reply->send(m_engine->isRelativePath());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineIsSequential)) {
- sendData(socket, m_engine->isSequential());
+ reply->send(m_engine->isSequential());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineLink)) {
QString newName;
data >>newName;
- sendData(socket, m_engine->link(newName));
+ reply->send(m_engine->link(newName));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineMkdir)) {
QString dirName;
bool createParentDirectories;
data >>dirName;
data >>createParentDirectories;
- sendData(socket, m_engine->mkdir(dirName, createParentDirectories));
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
+ reply->send(m_engine->mkdir(dirName, createParentDirectories));
+#else
+ reply->send(m_engine->mkdir(dirName, createParentDirectories, std::nullopt));
+#endif
+
} else if (command == QLatin1String(Protocol::QAbstractFileEngineOpen)) {
qint32 openMode;
data >>openMode;
- sendData(socket, m_engine->open(static_cast<QIODevice::OpenMode> (openMode)));
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
+ reply->send(m_engine->open(static_cast<QIODevice::OpenMode> (openMode)));
+#else
+ reply->send(m_engine->open(static_cast<QIODevice::OpenMode> (openMode), std::nullopt));
+#endif
} else if (command == QLatin1String(Protocol::QAbstractFileEngineOwner)) {
qint32 owner;
data >>owner;
- sendData(socket, m_engine->owner(static_cast<QAbstractFileEngine::FileOwner> (owner)));
+ reply->send(m_engine->owner(static_cast<QAbstractFileEngine::FileOwner> (owner)));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineOwnerId)) {
qint32 owner;
data >>owner;
- sendData(socket, m_engine->ownerId(static_cast<QAbstractFileEngine::FileOwner> (owner)));
+ reply->send(m_engine->ownerId(static_cast<QAbstractFileEngine::FileOwner> (owner)));
} else if (command == QLatin1String(Protocol::QAbstractFileEnginePos)) {
- sendData(socket, m_engine->pos());
+ reply->send(m_engine->pos());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRead)) {
qint64 maxlen;
data >> maxlen;
QByteArray byteArray(maxlen, '\0');
const qint64 r = m_engine->read(byteArray.data(), maxlen);
- sendData(socket, qMakePair<qint64, QByteArray>(r, byteArray));
+ reply->send(QPair<qint64, QByteArray>(r, byteArray));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineReadLine)) {
qint64 maxlen;
data >> maxlen;
QByteArray byteArray(maxlen, '\0');
const qint64 r = m_engine->readLine(byteArray.data(), maxlen);
- sendData(socket, qMakePair<qint64, QByteArray>(r, byteArray));
+ reply->send(QPair<qint64, QByteArray>(r, byteArray));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRemove)) {
- sendData(socket, m_engine->remove());
+ reply->send(m_engine->remove());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRename)) {
QString newName;
data >>newName;
- sendData(socket, m_engine->rename(newName));
+ reply->send(m_engine->rename(newName));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRmdir)) {
QString dirName;
bool recurseParentDirectories;
data >>dirName;
data >>recurseParentDirectories;
- sendData(socket, m_engine->rmdir(dirName, recurseParentDirectories));
+ reply->send(m_engine->rmdir(dirName, recurseParentDirectories));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSeek)) {
quint64 offset;
data >>offset;
- sendData(socket, m_engine->seek(offset));
+ reply->send(m_engine->seek(offset));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSetFileName)) {
QString fileName;
data >>fileName;
@@ -527,43 +557,43 @@ void RemoteServerConnection::handleQFSFileEngine(QIODevice *socket, const QStrin
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSetPermissions)) {
uint perms;
data >>perms;
- sendData(socket, m_engine->setPermissions(perms));
+ reply->send(m_engine->setPermissions(perms));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSetSize)) {
qint64 size;
data >>size;
- sendData(socket, m_engine->setSize(size));
+ reply->send(m_engine->setSize(size));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSize)) {
- sendData(socket, m_engine->size());
+ reply->send(m_engine->size());
} else if ((command == QLatin1String(Protocol::QAbstractFileEngineSupportsExtension))
|| (command == QLatin1String(Protocol::QAbstractFileEngineExtension))) {
// Implemented client side.
} else if (command == QLatin1String(Protocol::QAbstractFileEngineWrite)) {
QByteArray content;
data >> content;
- sendData(socket, m_engine->write(content.data(), content.size()));
+ reply->send(m_engine->write(content.data(), content.size()));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineSyncToDisk)) {
- sendData(socket, m_engine->syncToDisk());
+ reply->send(m_engine->syncToDisk());
} else if (command == QLatin1String(Protocol::QAbstractFileEngineRenameOverwrite)) {
QString newFilename;
data >> newFilename;
- sendData(socket, m_engine->renameOverwrite(newFilename));
+ reply->send(m_engine->renameOverwrite(newFilename));
} else if (command == QLatin1String(Protocol::QAbstractFileEngineFileTime)) {
qint32 filetime;
data >> filetime;
- sendData(socket, m_engine->fileTime(static_cast<QAbstractFileEngine::FileTime> (filetime)));
+ reply->send(m_engine->fileTime(static_cast<QAbstractFileEngine::FileTime> (filetime)));
} else if (!command.isEmpty()) {
qCDebug(QInstaller::lcServer) << "Unknown QAbstractFileEngine command:" << command;
}
}
-void RemoteServerConnection::handleArchive(QIODevice *socket, const QString &command, QDataStream &data)
+void RemoteServerConnection::handleArchive(RemoteServerReply *reply, const QString &command, QDataStream &data)
{
#ifdef IFW_LIBARCHIVE
- LibArchiveArchive *archive = static_cast<LibArchiveArchive *>(m_archive);
+ LibArchiveArchive *archive = static_cast<LibArchiveArchive *>(m_archive.get());
if (command == QLatin1String(Protocol::AbstractArchiveOpen)) {
qint32 openMode;
data >> openMode;
- sendData(socket, archive->open(static_cast<QIODevice::OpenMode>(openMode)));
+ reply->send(archive->open(static_cast<QIODevice::OpenMode>(openMode)));
} else if (command == QLatin1String(Protocol::AbstractArchiveClose)) {
archive->close();
} else if (command == QLatin1String(Protocol::AbstractArchiveSetFilename)) {
@@ -571,7 +601,7 @@ void RemoteServerConnection::handleArchive(QIODevice *socket, const QString &com
data >> fileName;
archive->setFilename(fileName);
} else if (command == QLatin1String(Protocol::AbstractArchiveErrorString)) {
- sendData(socket, archive->errorString());
+ reply->send(archive->errorString());
} else if (command == QLatin1String(Protocol::AbstractArchiveExtract)) {
QString dirPath;
quint64 total;
@@ -581,11 +611,11 @@ void RemoteServerConnection::handleArchive(QIODevice *socket, const QString &com
} else if (command == QLatin1String(Protocol::AbstractArchiveCreate)) {
QStringList entries;
data >> entries;
- sendData(socket, archive->create(entries));
+ reply->send(archive->create(entries));
} else if (command == QLatin1String(Protocol::AbstractArchiveList)) {
- sendData(socket, archive->list());
+ reply->send(archive->list());
} else if (command == QLatin1String(Protocol::AbstractArchiveIsSupported)) {
- sendData(socket, archive->isSupported());
+ reply->send(archive->isSupported());
} else if (command == QLatin1String(Protocol::AbstractArchiveSetCompressionLevel)) {
qint32 level;
data >> level;
@@ -601,7 +631,7 @@ void RemoteServerConnection::handleArchive(QIODevice *socket, const QString &com
data >> pos;
archive->workerSetFilePosition(pos);
} else if (command == QLatin1String(Protocol::AbstractArchiveWorkerStatus)) {
- sendData(socket, static_cast<qint32>(archive->workerStatus()));
+ reply->send(static_cast<qint32>(archive->workerStatus()));
} else if (command == QLatin1String(Protocol::AbstractArchiveCancel)) {
archive->workerCancel();
} else if (!command.isEmpty()) {
diff --git a/src/libs/installer/remoteserverconnection.h b/src/libs/installer/remoteserverconnection.h
index ccb8e153d..53f6a412b 100644
--- a/src/libs/installer/remoteserverconnection.h
+++ b/src/libs/installer/remoteserverconnection.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -33,12 +33,12 @@
#include <QPointer>
#include <QThread>
+#include <QProcess>
#include <QtCore/private/qfsfileengine_p.h>
QT_BEGIN_NAMESPACE
-class QProcess;
-class QIODevice;
+class QLocalSocket;
QT_END_NAMESPACE
namespace QInstaller {
@@ -48,6 +48,20 @@ class PermissionSettings;
class QProcessSignalReceiver;
class AbstractArchiveSignalReceiver;
+class RemoteServerReply
+{
+public:
+ explicit RemoteServerReply(QLocalSocket *socket);
+ ~RemoteServerReply();
+
+ template <typename T>
+ void send(const T &data);
+
+private:
+ QLocalSocket *m_socket;
+ bool m_sent;
+};
+
class RemoteServerConnection : public QThread
{
Q_OBJECT
@@ -57,27 +71,26 @@ public:
RemoteServerConnection(qintptr socketDescriptor, const QString &authorizationKey,
QObject *parent);
- void run() Q_DECL_OVERRIDE;
+ void run() override;
signals:
void shutdownRequested();
private:
- template <typename T>
- void sendData(QIODevice *device, const T &arg);
- void handleQProcess(QIODevice *device, const QString &command, QDataStream &data);
- void handleQSettings(QIODevice *device, const QString &command, QDataStream &data,
+ void handleQProcess(RemoteServerReply *reply, const QString &command, QDataStream &data);
+ void handleQSettings(RemoteServerReply *reply, const QString &command, QDataStream &data,
PermissionSettings *settings);
- void handleQFSFileEngine(QIODevice *device, const QString &command, QDataStream &data);
- void handleArchive(QIODevice *device, const QString &command, QDataStream &data);
+ void handleQFSFileEngine(RemoteServerReply *reply, const QString &command, QDataStream &data);
+ void handleArchive(RemoteServerReply *reply, const QString &command, QDataStream &data);
private:
qintptr m_socketDescriptor;
-
- QProcess *m_process;
- QFSFileEngine *m_engine;
- AbstractArchive *m_archive;
QString m_authorizationKey;
+
+ QScopedPointer<QProcess> m_process;
+ QScopedPointer<QFSFileEngine> m_engine;
+ QScopedPointer<AbstractArchive> m_archive;
+
QProcessSignalReceiver *m_processSignalReceiver;
AbstractArchiveSignalReceiver *m_archiveSignalReceiver;
};
diff --git a/src/libs/installer/remoteserverconnection_p.h b/src/libs/installer/remoteserverconnection_p.h
index 977a64711..09e6de7d7 100644
--- a/src/libs/installer/remoteserverconnection_p.h
+++ b/src/libs/installer/remoteserverconnection_p.h
@@ -52,7 +52,7 @@ private:
connect(process, &QIODevice::bytesWritten, this, &QProcessSignalReceiver::onBytesWritten);
connect(process, &QIODevice::aboutToClose, this, &QProcessSignalReceiver::onAboutToClose);
connect(process, &QIODevice::readChannelFinished, this, &QProcessSignalReceiver::onReadChannelFinished);
- connect(process, SIGNAL(error(QProcess::ProcessError)),
+ connect(process, SIGNAL(errorOccurred(QProcess::ProcessError)),
SLOT(onError(QProcess::ProcessError)));
connect(process, &QProcess::readyReadStandardOutput,
this, &QProcessSignalReceiver::onReadyReadStandardOutput);
diff --git a/src/libs/installer/replaceoperation.h b/src/libs/installer/replaceoperation.h
index 0d2783ab6..09cca99c2 100644
--- a/src/libs/installer/replaceoperation.h
+++ b/src/libs/installer/replaceoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT ReplaceOperation : public Operation
public:
explicit ReplaceOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
} // namespace QInstaller
diff --git a/src/libs/installer/repository.cpp b/src/libs/installer/repository.cpp
index 50f3eceb6..f7035e732 100644
--- a/src/libs/installer/repository.cpp
+++ b/src/libs/installer/repository.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -35,7 +35,7 @@
#include <QDir>
/*!
- \fn inline uint QInstaller::qHash(const Repository &repository)
+ \fn inline hashValue QInstaller::qHash(const Repository &repository)
Returns a hash of the \a repository.
*/
@@ -49,8 +49,8 @@ Repository::Repository()
: m_default(false)
, m_enabled(false)
, m_compressed(false)
+ , m_postLoadComponentScript(false)
{
- registerMetaType();
}
/*!
@@ -63,10 +63,11 @@ Repository::Repository(const Repository &other)
, m_username(other.m_username)
, m_password(other.m_password)
, m_displayname(other.m_displayname)
- , m_compressed(other.m_compressed)
, m_categoryname(other.m_categoryname)
+ , m_compressed(other.m_compressed)
+ , m_xmlChecksum(other.m_xmlChecksum)
+ , m_postLoadComponentScript(other.m_postLoadComponentScript)
{
- registerMetaType();
}
/*!
@@ -78,8 +79,8 @@ Repository::Repository(const QUrl &url, bool isDefault, bool compressed)
, m_default(isDefault)
, m_enabled(true)
, m_compressed(compressed)
+ , m_postLoadComponentScript(false)
{
- registerMetaType();
}
/*!
@@ -224,6 +225,28 @@ void Repository::setCategoryName(const QString &categoryname)
}
/*!
+ Returns the expected checksum of the repository, which is the checksum
+ calculated from the \c Updates.xml document at the root of the repository.
+
+ This value is used as a hint when looking for already fetched repositories
+ from the local cache. If the installer has cached a repository with a matching
+ checksum, it can skip downloading the \c Updates.xml file for that repository again.
+*/
+QByteArray Repository::xmlChecksum() const
+{
+ return m_xmlChecksum;
+}
+
+/*!
+ Sets the expected checksum of the repository to \c checksum. The checksum
+ is calculated from the \c Updates.xml document at the root of the repository.
+*/
+void Repository::setXmlChecksum(const QByteArray &checksum)
+{
+ m_xmlChecksum = checksum;
+}
+
+/*!
Returns true if repository is compressed
*/
bool Repository::isCompressed() const
@@ -232,13 +255,31 @@ bool Repository::isCompressed() const
}
/*!
+ \internal
+*/
+bool Repository::postLoadComponentScript() const
+{
+ return m_postLoadComponentScript;
+}
+
+/*!
+ \internal
+*/
+void Repository::setPostLoadComponentScript(const bool postLoad)
+{
+ m_postLoadComponentScript = postLoad;
+}
+
+/*!
Compares the values of this repository to \a other and returns true if they are equal (same server,
default state, enabled state as well as username and password). \sa operator!=()
*/
bool Repository::operator==(const Repository &other) const
{
return m_url == other.m_url && m_default == other.m_default && m_enabled == other.m_enabled
- && m_username == other.m_username && m_password == other.m_password && m_displayname == other.m_displayname;
+ && m_username == other.m_username && m_password == other.m_password
+ && m_displayname == other.m_displayname && m_xmlChecksum == other.m_xmlChecksum
+ && m_postLoadComponentScript == other.m_postLoadComponentScript;
}
/*!
@@ -266,6 +307,8 @@ const Repository &Repository::operator=(const Repository &other)
m_displayname = other.m_displayname;
m_compressed = other.m_compressed;
m_categoryname = other.m_categoryname;
+ m_xmlChecksum = other.m_xmlChecksum;
+ m_postLoadComponentScript = other.m_postLoadComponentScript;
return *this;
}
@@ -273,7 +316,9 @@ const Repository &Repository::operator=(const Repository &other)
void Repository::registerMetaType()
{
qRegisterMetaType<Repository>("Repository");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
qRegisterMetaTypeStreamOperators<Repository>("Repository");
+#endif
}
/*!
@@ -283,7 +328,7 @@ QDataStream &operator>>(QDataStream &istream, Repository &repository)
{
QByteArray url, username, password, displayname, compressed;
istream >> url >> repository.m_default >> repository.m_enabled >> username >> password
- >> displayname >> repository.m_categoryname;
+ >> displayname >> repository.m_categoryname >> repository.m_xmlChecksum >> repository.m_postLoadComponentScript;
repository.setUrl(QUrl::fromEncoded(QByteArray::fromBase64(url)));
repository.setUsername(QString::fromUtf8(QByteArray::fromBase64(username)));
repository.setPassword(QString::fromUtf8(QByteArray::fromBase64(password)));
@@ -298,7 +343,8 @@ QDataStream &operator<<(QDataStream &ostream, const Repository &repository)
{
return ostream << repository.m_url.toEncoded().toBase64() << repository.m_default << repository.m_enabled
<< repository.m_username.toUtf8().toBase64() << repository.m_password.toUtf8().toBase64()
- << repository.m_displayname.toUtf8().toBase64() << repository.m_categoryname.toUtf8().toBase64();
+ << repository.m_displayname.toUtf8().toBase64() << repository.m_categoryname.toUtf8().toBase64()
+ << repository.m_xmlChecksum.toBase64() << repository.m_postLoadComponentScript;
}
}
diff --git a/src/libs/installer/repository.h b/src/libs/installer/repository.h
index 3f28e4d99..0a589a43e 100644
--- a/src/libs/installer/repository.h
+++ b/src/libs/installer/repository.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -67,11 +67,17 @@ public:
QString categoryname() const;
void setCategoryName(const QString &categoryname);
+ QByteArray xmlChecksum() const;
+ void setXmlChecksum(const QByteArray &checksum);
+
bool isCompressed() const;
+ bool postLoadComponentScript() const;
+ void setPostLoadComponentScript(const bool postLoad);
+
bool operator==(const Repository &other) const;
bool operator!=(const Repository &other) const;
- uint qHash(const Repository &repository);
+ hashValue qHash(const Repository &repository);
const Repository &operator=(const Repository &other);
friend INSTALLER_EXPORT QDataStream &operator>>(QDataStream &istream, Repository &repository);
@@ -86,9 +92,11 @@ private:
QString m_displayname;
QString m_categoryname;
bool m_compressed;
+ QByteArray m_xmlChecksum;
+ bool m_postLoadComponentScript;
};
-inline uint qHash(const Repository &repository)
+inline hashValue qHash(const Repository &repository)
{
return qHash(repository.url());
}
diff --git a/src/libs/installer/repositorycategory.cpp b/src/libs/installer/repositorycategory.cpp
index 0b875b27a..c9bee6e3a 100644
--- a/src/libs/installer/repositorycategory.cpp
+++ b/src/libs/installer/repositorycategory.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -35,7 +35,7 @@
#include <QStringList>
/*!
- \fn inline uint QInstaller::qHash(const RepositoryCategory &repository)
+ \fn inline hashValue QInstaller::qHash(const RepositoryCategory &repository)
Returns a hash of the repository category \a repository.
*/
@@ -65,8 +65,8 @@ RepositoryCategory::RepositoryCategory()
Constructs a new category by using all fields of the given category \a other.
*/
RepositoryCategory::RepositoryCategory(const RepositoryCategory &other)
- : m_displayname(other.m_displayname), m_data(other.m_data), m_enabled(other.m_enabled),
- m_tooltip(other.m_tooltip)
+ : m_data(other.m_data), m_displayname(other.m_displayname), m_tooltip(other.m_tooltip),
+ m_enabled(other.m_enabled)
{
registerMetaType();
}
@@ -75,7 +75,9 @@ RepositoryCategory::RepositoryCategory(const RepositoryCategory &other)
void RepositoryCategory::registerMetaType()
{
qRegisterMetaType<RepositoryCategory>("RepositoryCategory");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
qRegisterMetaTypeStreamOperators<RepositoryCategory>("RepositoryCategory");
+#endif
}
/*!
@@ -128,7 +130,7 @@ void RepositoryCategory::setRepositories(const QSet<Repository> repositories, co
m_data.remove(scRepositories);
foreach (const Repository &repository, repositories)
- m_data.insertMulti(scRepositories, QVariant().fromValue(repository));
+ m_data.insert(scRepositories, QVariant().fromValue(repository));
}
/*!
@@ -136,7 +138,7 @@ void RepositoryCategory::setRepositories(const QSet<Repository> repositories, co
*/
void RepositoryCategory::addRepository(const Repository &repository)
{
- m_data.insertMulti(scRepositories, QVariant().fromValue(repository));
+ m_data.insert(scRepositories, QVariant().fromValue(repository));
}
/*!
diff --git a/src/libs/installer/repositorycategory.h b/src/libs/installer/repositorycategory.h
index 51dc3ddfb..993ae78aa 100644
--- a/src/libs/installer/repositorycategory.h
+++ b/src/libs/installer/repositorycategory.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -31,6 +31,7 @@
#include "installer_global.h"
#include "repository.h"
+#include "qinstallerglobal.h"
#include <QtCore/QMetaType>
#include <QtCore/QUrl>
@@ -63,19 +64,19 @@ public:
bool operator==(const RepositoryCategory &other) const;
bool operator!=(const RepositoryCategory &other) const;
- uint qHash(const RepositoryCategory &repository);
+ hashValue qHash(const RepositoryCategory &repository);
friend INSTALLER_EXPORT QDataStream &operator>>(QDataStream &istream, RepositoryCategory &repository);
friend INSTALLER_EXPORT QDataStream &operator<<(QDataStream &ostream, const RepositoryCategory &repository);
private:
- QVariantHash m_data;
+ QMultiHash<QString, QVariant> m_data;
QString m_displayname;
QString m_tooltip;
bool m_enabled;
};
-inline uint qHash(const RepositoryCategory &repository)
+inline hashValue qHash(const RepositoryCategory &repository)
{
return qHash(repository.displayname());
}
diff --git a/src/libs/installer/resources/installer.qrc b/src/libs/installer/resources/installer.qrc
index 48a7c65bd..a3855b5c4 100644
--- a/src/libs/installer/resources/installer.qrc
+++ b/src/libs/installer/resources/installer.qrc
@@ -7,5 +7,6 @@
<file>uninstall.png</file>
<file>keepinstalled.png</file>
<file>keepuninstalled.png</file>
+ <file>qt/etc/qt.conf</file>
</qresource>
</RCC>
diff --git a/src/libs/installer/resources/qt/etc/qt.conf b/src/libs/installer/resources/qt/etc/qt.conf
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/libs/installer/resources/qt/etc/qt.conf
diff --git a/src/libs/installer/runextensions.h b/src/libs/installer/runextensions.h
index fd76db060..9c7147141 100644
--- a/src/libs/installer/runextensions.h
+++ b/src/libs/installer/runextensions.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -37,384 +37,70 @@ QT_BEGIN_NAMESPACE
namespace QtConcurrent {
-template <typename T, typename FunctionPointer>
-class StoredInterfaceFunctionCall0 : public QRunnable
+template <typename T, typename FunctionPointer, typename... Args>
+class StoredInterfaceFunctionCall : public QRunnable
{
public:
- StoredInterfaceFunctionCall0(void (fn)(QFutureInterface<T> &))
- : fn(fn) { }
+ StoredInterfaceFunctionCall(void (fn)(QFutureInterface<T> &, Args...), const Args&&... args)
+ : m_fn(fn), m_args(std::make_tuple(std::forward<Args>(args)...)) { }
QFuture<T> start()
{
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
+ m_futureInterface.reportStarted();
+ QFuture<T> future = m_futureInterface.future();
QThreadPool::globalInstance()->start(this);
return future;
}
- void run()
+ void run() override
{
- fn(futureInterface);
- futureInterface.reportFinished();
+ fn(m_futureInterface, std::forward<Args>(m_args)...);
+ m_futureInterface.reportFinished();
}
private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
-
+ QFutureInterface<T> m_futureInterface;
+ FunctionPointer m_fn;
+ std::tuple<Args...> m_args;
};
-template <typename T, typename FunctionPointer, typename Class>
-class StoredInterfaceMemberFunctionCall0 : public QRunnable
+template <typename T, typename FunctionPointer, typename Class, typename... Args>
+class StoredInterfaceMemberFunctionCall : public QRunnable
{
public:
- StoredInterfaceMemberFunctionCall0(void (Class::*fn)(QFutureInterface<T> &), Class *object)
- : fn(fn), object(object) { }
+ StoredInterfaceMemberFunctionCall(void (Class::*fn)(QFutureInterface<T> &, Args...), Class *object, const Args&&... args)
+ : m_fn(fn), m_object(object), m_args(std::make_tuple(std::forward<Args>(args)...)) { }
QFuture<T> start()
{
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
+ m_futureInterface.reportStarted();
+ QFuture<T> future = m_futureInterface.future();
QThreadPool::globalInstance()->start(this);
return future;
}
- void run()
+ void run() override
{
- (object->*fn)(futureInterface);
- futureInterface.reportFinished();
+ (m_object->*m_fn)(m_futureInterface, std::forward<Args>(m_args)...);
+ m_futureInterface.reportFinished();
}
private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Class *object;
-
+ QFutureInterface<T> m_futureInterface;
+ FunctionPointer m_fn;
+ Class *m_object;
+ std::tuple<Args...> m_args;
};
-template <typename T, typename FunctionPointer, typename Arg1>
-class StoredInterfaceFunctionCall1 : public QRunnable
+template <typename T, typename... Args>
+QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &, Args...), Args... args)
{
-public:
- StoredInterfaceFunctionCall1(void (fn)(QFutureInterface<T> &, Arg1), const Arg1 &arg1)
- : fn(fn), arg1(arg1) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- fn(futureInterface, arg1);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Arg1 arg1;
-};
-template <typename T, typename FunctionPointer, typename Class, typename Arg1>
-class StoredInterfaceMemberFunctionCall1 : public QRunnable
-{
-public:
- StoredInterfaceMemberFunctionCall1(void (Class::*fn)(QFutureInterface<T> &, Arg1), Class *object, const Arg1 &arg1)
- : fn(fn), object(object), arg1(arg1) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- (object->*fn)(futureInterface, arg1);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Class *object;
- Arg1 arg1;
-};
-
-template <typename T, typename FunctionPointer, typename Arg1, typename Arg2>
-class StoredInterfaceFunctionCall2 : public QRunnable
-{
-public:
- StoredInterfaceFunctionCall2(void (fn)(QFutureInterface<T> &, Arg1, Arg2), const Arg1 &arg1, const Arg2 &arg2)
- : fn(fn), arg1(arg1), arg2(arg2) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- fn(futureInterface, arg1, arg2);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Arg1 arg1; Arg2 arg2;
-};
-template <typename T, typename FunctionPointer, typename Class, typename Arg1, typename Arg2>
-class StoredInterfaceMemberFunctionCall2 : public QRunnable
-{
-public:
- StoredInterfaceMemberFunctionCall2(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2), Class *object, const Arg1 &arg1, const Arg2 &arg2)
- : fn(fn), object(object), arg1(arg1), arg2(arg2) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- (object->*fn)(futureInterface, arg1, arg2);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Class *object;
- Arg1 arg1; Arg2 arg2;
-};
-
-template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3>
-class StoredInterfaceFunctionCall3 : public QRunnable
-{
-public:
- StoredInterfaceFunctionCall3(void (fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
- : fn(fn), arg1(arg1), arg2(arg2), arg3(arg3) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- fn(futureInterface, arg1, arg2, arg3);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Arg1 arg1; Arg2 arg2; Arg3 arg3;
-};
-template <typename T, typename FunctionPointer, typename Class, typename Arg1, typename Arg2, typename Arg3>
-class StoredInterfaceMemberFunctionCall3 : public QRunnable
-{
-public:
- StoredInterfaceMemberFunctionCall3(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3), Class *object, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
- : fn(fn), object(object), arg1(arg1), arg2(arg2), arg3(arg3) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- (object->*fn)(futureInterface, arg1, arg2, arg3);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Class *object;
- Arg1 arg1; Arg2 arg2; Arg3 arg3;
-};
-
-template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-class StoredInterfaceFunctionCall4 : public QRunnable
-{
-public:
- StoredInterfaceFunctionCall4(void (fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
- : fn(fn), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- fn(futureInterface, arg1, arg2, arg3, arg4);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
-};
-template <typename T, typename FunctionPointer, typename Class, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-class StoredInterfaceMemberFunctionCall4 : public QRunnable
-{
-public:
- StoredInterfaceMemberFunctionCall4(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4), Class *object, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
- : fn(fn), object(object), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- (object->*fn)(futureInterface, arg1, arg2, arg3, arg4);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Class *object;
- Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4;
-};
-
-template <typename T, typename FunctionPointer, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
-class StoredInterfaceFunctionCall5 : public QRunnable
-{
-public:
- StoredInterfaceFunctionCall5(void (fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4, Arg5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
- : fn(fn), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- fn(futureInterface, arg1, arg2, arg3, arg4, arg5);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
-};
-template <typename T, typename FunctionPointer, typename Class, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
-class StoredInterfaceMemberFunctionCall5 : public QRunnable
-{
-public:
- StoredInterfaceMemberFunctionCall5(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4, Arg5), Class *object, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
- : fn(fn), object(object), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5) { }
-
- QFuture<T> start()
- {
- futureInterface.reportStarted();
- QFuture<T> future = futureInterface.future();
- QThreadPool::globalInstance()->start(this);
- return future;
- }
-
- void run()
- {
- (object->*fn)(futureInterface, arg1, arg2, arg3, arg4, arg5);
- futureInterface.reportFinished();
- }
-private:
- QFutureInterface<T> futureInterface;
- FunctionPointer fn;
- Class *object;
- Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5;
-};
-
-template <typename T>
-QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &))
-{
- return (new StoredInterfaceFunctionCall0<T, void (*)(QFutureInterface<T> &)>(functionPointer))->start();
-}
-template <typename T, typename Arg1>
-QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &, Arg1), const Arg1 &arg1)
-{
- return (new StoredInterfaceFunctionCall1<T, void (*)(QFutureInterface<T> &, Arg1), Arg1>(functionPointer, arg1))->start();
-}
-template <typename T, typename Arg1, typename Arg2>
-QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &, Arg1, Arg2), const Arg1 &arg1, const Arg2 &arg2)
-{
- return (new StoredInterfaceFunctionCall2<T, void (*)(QFutureInterface<T> &, Arg1, Arg2), Arg1, Arg2>(functionPointer, arg1, arg2))->start();
-}
-template <typename T, typename Arg1, typename Arg2, typename Arg3>
-QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &, Arg1, Arg2, Arg3), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
-{
- return (new StoredInterfaceFunctionCall3<T, void (*)(QFutureInterface<T> &, Arg1, Arg2, Arg3), Arg1, Arg2, Arg3>(functionPointer, arg1, arg2, arg3))->start();
-}
-template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
-{
- return (new StoredInterfaceFunctionCall4<T, void (*)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4), Arg1, Arg2, Arg3, Arg4>(functionPointer, arg1, arg2, arg3, arg4))->start();
-}
-template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
-QFuture<T> run(void (*functionPointer)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4, Arg5), const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
-{
- return (new StoredInterfaceFunctionCall5<T, void (*)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4, Arg5), Arg1, Arg2, Arg3, Arg4, Arg5>(functionPointer, arg1, arg2, arg3, arg4, arg5))->start();
-}
-
-template <typename Class, typename T>
-QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &), Class *object)
-{
- return (new StoredInterfaceMemberFunctionCall0<T, void (Class::*)(QFutureInterface<T> &), Class>(fn, object))->start();
-}
-
-template <typename Class, typename T, typename Arg1>
-QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &, Arg1), Class *object, Arg1 arg1)
-{
- return (new StoredInterfaceMemberFunctionCall1<T, void (Class::*)(QFutureInterface<T> &, Arg1), Class, Arg1>(fn, object, arg1))->start();
-}
-
-template <typename Class, typename T, typename Arg1, typename Arg2>
-QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2), Class *object, const Arg1 &arg1, const Arg2 &arg2)
-{
- return (new StoredInterfaceMemberFunctionCall2<T, void (Class::*)(QFutureInterface<T> &, Arg1, Arg2), Class, Arg1, Arg2>(fn, object, arg1, arg2))->start();
+ return (new StoredInterfaceFunctionCall<T, void (*)(QFutureInterface<T> &, Args...), Args...>(functionPointer, args...))->start();
}
-template <typename Class, typename T, typename Arg1, typename Arg2, typename Arg3>
-QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3), Class *object, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3)
+template <typename Class, typename T, typename... Args>
+QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &, Args...), Class *object, Args... args)
{
- return (new StoredInterfaceMemberFunctionCall3<T, void (Class::*)(QFutureInterface<T> &, Arg1, Arg2, Arg3), Class, Arg1, Arg2, Arg3>(fn, object, arg1, arg2, arg3))->start();
+ return (new StoredInterfaceMemberFunctionCall<T, void (Class::*)(QFutureInterface<T> &, Args...), Class, Args...>(fn, object, args...))->start();
}
-template <typename Class, typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4), Class *object, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4)
-{
- return (new StoredInterfaceMemberFunctionCall4<T, void (Class::*)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4), Class, Arg1, Arg2, Arg3, Arg4>(fn, object, arg1, arg2, arg3, arg4))->start();
-}
-
-template <typename Class, typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
-QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4, Arg5), Class *object, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5)
-{
- return (new StoredInterfaceMemberFunctionCall5<T, void (Class::*)(QFutureInterface<T> &, Arg1, Arg2, Arg3, Arg4, Arg5), Class, Arg1, Arg2, Arg3, Arg4, Arg5>(fn, object, arg1, arg2, arg3, arg4, arg5))->start();
-}
} // namespace QtConcurrent
QT_END_NAMESPACE
diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp
index c8fc65d34..7e3e69eb2 100644
--- a/src/libs/installer/scriptengine.cpp
+++ b/src/libs/installer/scriptengine.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,9 @@
#include "scriptengine_p.h"
#include "systeminfo.h"
#include "loggingutils.h"
+#include "packagemanagergui.h"
+#include "component.h"
+#include "settings.h"
#include <QMetaEnum>
#include <QQmlEngine>
@@ -53,18 +56,6 @@ namespace QInstaller {
/*!
\inmodule QtInstallerFramework
- \class QInstaller::ConsoleProxy
- \internal
-*/
-
-/*!
- \inmodule QtInstallerFramework
- \class QInstaller::InstallerProxy
- \internal
-*/
-
-/*!
- \inmodule QtInstallerFramework
\class QInstaller::QDesktopServicesProxy
\internal
*/
@@ -75,28 +66,6 @@ namespace QInstaller {
\internal
*/
-QJSValue InstallerProxy::components(const QString &regexp) const
-{
- if (m_core) {
- const QList<Component*> all = m_core->components(PackageManagerCore::ComponentType::All, regexp);
- QJSValue scriptComponentsObject = m_engine->newArray(all.count());
- for (int i = 0; i < all.count(); ++i) {
- Component *const component = all.at(i);
- QQmlEngine::setObjectOwnership(component, QQmlEngine::CppOwnership);
- scriptComponentsObject.setProperty(i, m_engine->newQObject(component));
- }
- return scriptComponentsObject;
- }
- return m_engine->newArray();
-}
-
-QJSValue InstallerProxy::componentByName(const QString &componentName)
-{
- if (m_core)
- return m_engine->newQObject(m_core->componentByName(componentName));
- return QJSValue();
-}
-
QJSValue QDesktopServicesProxy::findFiles(const QString &path, const QString &pattern)
{
QStringList result;
@@ -220,6 +189,12 @@ bool GuiProxy::isButtonEnabled(int wizardButton)
return m_gui->isButtonEnabled(wizardButton);
}
+void GuiProxy::setWizardPageButtonText(int pageId, int buttonId, const QString &buttonText)
+{
+ if (m_gui)
+ m_gui->setWizardPageButtonText(pageId, buttonId, buttonText);
+}
+
void GuiProxy::showSettingsButton(bool show)
{
if (m_gui)
@@ -375,24 +350,23 @@ QString QFileDialogProxy::getExistingFileOrDirectory(const QString &caption,
/*!
Constructs a script engine with \a core as parent.
*/
-ScriptEngine::ScriptEngine(PackageManagerCore *core) :
- QObject(core),
- m_guiProxy(new GuiProxy(this, this))
+ScriptEngine::ScriptEngine(PackageManagerCore *core) : QObject(core)
+ , m_guiProxy(new GuiProxy(this, this))
+ , m_core(core)
{
- m_engine.installExtensions(QJSEngine::TranslationExtension);
+ m_engine.installExtensions(QJSEngine::TranslationExtension | QJSEngine::ConsoleExtension);
QJSValue global = m_engine.globalObject();
- global.setProperty(QLatin1String("console"), m_engine.newQObject(new ConsoleProxy));
+
global.setProperty(QLatin1String("QFileDialog"), m_engine.newQObject(new QFileDialogProxy(core)));
- const QJSValue proxy = m_engine.newQObject(new InstallerProxy(this, core));
- global.setProperty(QLatin1String("InstallerProxy"), proxy);
- global.setProperty(QLatin1String("print"), m_engine.newQObject(new ConsoleProxy)
- .property(QLatin1String("log")));
global.setProperty(QLatin1String("systemInfo"), m_engine.newQObject(new SystemInfo));
global.setProperty(QLatin1String("QInstaller"), generateQInstallerObject());
global.setProperty(QLatin1String("buttons"), generateWizardButtonsObject());
global.setProperty(QLatin1String("QMessageBox"), generateMessageBoxObject());
global.setProperty(QLatin1String("QDesktopServices"), generateDesktopServicesObject());
+#ifdef Q_OS_WIN
+ global.setProperty(QLatin1String("QSettings"), generateSettingsObject());
+#endif
if (core) {
setGuiQObject(core->guiObject());
@@ -403,19 +377,14 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) :
global.setProperty(QLatin1String("installer"), m_engine.newQObject(new QObject));
}
global.setProperty(QLatin1String("gui"), m_engine.newQObject(m_guiProxy));
-
- global.property(QLatin1String("installer")).setProperty(QLatin1String("components"),
- proxy.property(QLatin1String("components")));
- global.property(QLatin1String("installer")).setProperty(QLatin1String("componentByName"),
- proxy.property(QLatin1String("componentByName")));
}
/*!
Creates a JavaScript object that wraps the given QObject \a object.
- Signals and slots, properties and children of \a object are
- available as properties of the created QJSValue. In addition some helper methods and properties
- are added:
+ Signals and slots, properties and children of \a object are available as properties
+ of the created QJSValue. If \a qtScriptCompat is set to \c true (default), some helper
+ methods and properties from the legacy \c QtScript module are added:
\list
\li findChild(), findChildren() recursively search for child objects with the given
@@ -424,7 +393,7 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core) :
names.
\endlist
*/
-QJSValue ScriptEngine::newQObject(QObject *object)
+QJSValue ScriptEngine::newQObject(QObject *object, bool qtScriptCompat)
{
QJSValue jsValue = m_engine.newQObject(object);
if (!jsValue.isQObject())
@@ -432,6 +401,9 @@ QJSValue ScriptEngine::newQObject(QObject *object)
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
+ if (!qtScriptCompat) // skip adding the extra properties
+ return jsValue;
+
// add findChild(), findChildren() methods known from QtScript
QJSValue findChild = m_engine.evaluate(
QLatin1String("(function() { return gui.findChild(this, arguments[0]); })"));
@@ -566,14 +538,17 @@ QJSValue ScriptEngine::callScriptMethod(const QJSValue &scriptContext, const QSt
if (!method.isCallable())
return QJSValue(QJSValue::UndefinedValue);
if (method.isError()) {
- throw Error(method.toString().isEmpty() ? QString::fromLatin1("Unknown error.")
- : method.toString());
+ QString errorString = method.toString().isEmpty() ? QString::fromLatin1("Unknown error.")
+ : method.toString();
+
+ throw Error(QString::fromLatin1("%1 \n%2 \"%3\"").arg(errorString, tr(scClearCacheHint), m_core->settings().localCachePath()));
}
const QJSValue result = method.call(arguments);
if (result.isError()) {
- throw Error(result.toString().isEmpty() ? QString::fromLatin1("Unknown error.")
- : result.toString());
+ QString errorString = result.toString().isEmpty() ? QString::fromLatin1("Unknown error.")
+ : result.toString();
+ throw Error(QString::fromLatin1("%1 \n%2 \"%3\"").arg(errorString, tr(scClearCacheHint), m_core->settings().localCachePath()));
}
stack.removeLast();
@@ -649,20 +624,38 @@ QJSValue ScriptEngine::generateDesktopServicesObject()
SETPROPERTY(desktopServices, PicturesLocation, QStandardPaths)
SETPROPERTY(desktopServices, TempLocation, QStandardPaths)
SETPROPERTY(desktopServices, HomeLocation, QStandardPaths)
- SETPROPERTY(desktopServices, DataLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, AppLocalDataLocation, QStandardPaths)
SETPROPERTY(desktopServices, CacheLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, GenericCacheLocation, QStandardPaths)
SETPROPERTY(desktopServices, GenericDataLocation, QStandardPaths)
SETPROPERTY(desktopServices, RuntimeLocation, QStandardPaths)
SETPROPERTY(desktopServices, ConfigLocation, QStandardPaths)
SETPROPERTY(desktopServices, DownloadLocation, QStandardPaths)
SETPROPERTY(desktopServices, GenericCacheLocation, QStandardPaths)
SETPROPERTY(desktopServices, GenericConfigLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, AppDataLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, AppConfigLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, PublicShareLocation, QStandardPaths)
+ SETPROPERTY(desktopServices, TemplatesLocation, QStandardPaths)
QJSValue object = m_engine.newQObject(new QDesktopServicesProxy(this));
object.setPrototype(desktopServices); // attach the properties
return object;
}
+#ifdef Q_OS_WIN
+QJSValue ScriptEngine::generateSettingsObject()
+{
+ QJSValue settingsObject = m_engine.newArray();
+ SETPROPERTY(settingsObject, NativeFormat, QSettings)
+ SETPROPERTY(settingsObject, IniFormat, QSettings)
+ SETPROPERTY(settingsObject, Registry32Format, QSettings)
+ SETPROPERTY(settingsObject, Registry64Format, QSettings)
+ SETPROPERTY(settingsObject, InvalidFormat, QSettings)
+ return settingsObject;
+}
+#endif
+
QJSValue ScriptEngine::generateQInstallerObject()
{
// register ::WizardPage enum in the script connection
diff --git a/src/libs/installer/scriptengine.h b/src/libs/installer/scriptengine.h
index a0c64c0e4..0b43465cb 100644
--- a/src/libs/installer/scriptengine.h
+++ b/src/libs/installer/scriptengine.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -48,7 +48,7 @@ public:
explicit ScriptEngine(PackageManagerCore *core = 0);
QJSValue globalObject() const { return m_engine.globalObject(); }
- QJSValue newQObject(QObject *object);
+ QJSValue newQObject(QObject *object, bool qtScriptCompat = true);
QJSValue newArray(uint length = 0);
QJSValue evaluate(const QString &program, const QString &fileName = QString(),
int lineNumber = 1);
@@ -69,11 +69,15 @@ private:
QJSValue generateQInstallerObject();
QJSValue generateWizardButtonsObject();
QJSValue generateDesktopServicesObject();
+#ifdef Q_OS_WIN
+ QJSValue generateSettingsObject();
+#endif
private:
QJSEngine m_engine;
QHash<QString, QStringList> m_callstack;
GuiProxy *m_guiProxy;
+ PackageManagerCore *m_core;
};
}
diff --git a/src/libs/installer/scriptengine_p.h b/src/libs/installer/scriptengine_p.h
index e5c39663c..101d4f303 100644
--- a/src/libs/installer/scriptengine_p.h
+++ b/src/libs/installer/scriptengine_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,47 +29,19 @@
#ifndef SCRIPTENGINE_P_H
#define SCRIPTENGINE_P_H
-#include "component.h"
-#include "packagemanagercore.h"
-#include "packagemanagergui.h"
#include "globals.h"
#include <QDebug>
#include <QDesktopServices>
#include <QFileDialog>
#include <QStandardPaths>
+#include <QJSValue>
namespace QInstaller {
-class ConsoleProxy : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(ConsoleProxy)
-
-public:
- ConsoleProxy() {}
-
-public slots :
- void log(const QString &log) { qCDebug(QInstaller::lcInstallerInstallLog).noquote() << log; }
-};
-
-class InstallerProxy : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(InstallerProxy)
-
-public:
- InstallerProxy(ScriptEngine *engine, PackageManagerCore *core)
- : m_engine(engine), m_core(core) {}
-
-public slots:
- QJSValue components(const QString &regexp = QString()) const;
- QJSValue componentByName(const QString &componentName);
-
-private:
- ScriptEngine *m_engine;
- PackageManagerCore *m_core;
-};
+class PackageManagerCore;
+class PackageManagerGui;
+class ScriptEngine;
class QFileDialogProxy : public QObject
{
@@ -144,6 +116,7 @@ public:
Q_INVOKABLE void clickButton(int wizardButton, int delayInMs = 0);
Q_INVOKABLE void clickButton(const QString &objectName, int delayInMs = 0) const;
Q_INVOKABLE bool isButtonEnabled(int wizardButton);
+ Q_INVOKABLE void setWizardPageButtonText(int pageId, int buttonId, const QString &buttonText);
Q_INVOKABLE void showSettingsButton(bool show);
Q_INVOKABLE void setSettingsButtonEnabled(bool enable);
@@ -176,8 +149,6 @@ private:
} // namespace QInstaller
-Q_DECLARE_METATYPE(QInstaller::ConsoleProxy*)
-Q_DECLARE_METATYPE(QInstaller::InstallerProxy*)
Q_DECLARE_METATYPE(QInstaller::QFileDialogProxy*)
Q_DECLARE_METATYPE(QInstaller::QDesktopServicesProxy*)
diff --git a/src/libs/installer/selfrestartoperation.h b/src/libs/installer/selfrestartoperation.h
index 7adccd183..0554df2af 100644
--- a/src/libs/installer/selfrestartoperation.h
+++ b/src/libs/installer/selfrestartoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT SelfRestartOperation : public Operation
public:
explicit SelfRestartOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
}
diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp
index 537f6060b..e18f63689 100644
--- a/src/libs/installer/settings.cpp
+++ b/src/libs/installer/settings.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -34,8 +34,11 @@
#include "globals.h"
#include "fileutils.h"
+#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QStringList>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QUuid>
#include <QtGui/QFontMetrics>
#include <QtWidgets/QApplication>
@@ -66,6 +69,7 @@ static const QLatin1String scMaintenanceToolName("MaintenanceToolName");
static const QLatin1String scUserRepositories("UserRepositories");
static const QLatin1String scTmpRepositories("TemporaryRepositories");
static const QLatin1String scMaintenanceToolIniFile("MaintenanceToolIniFile");
+static const QLatin1String scMaintenanceToolAlias("MaintenanceToolAlias");
static const QLatin1String scDependsOnLocalInstallerBinary("DependsOnLocalInstallerBinary");
static const QLatin1String scTranslations("Translations");
static const QLatin1String scCreateLocalRepository("CreateLocalRepository");
@@ -75,6 +79,8 @@ static const QLatin1String scFtpProxy("FtpProxy");
static const QLatin1String scHttpProxy("HttpProxy");
static const QLatin1String scProxyType("ProxyType");
+static const QLatin1String scLocalCachePath("LocalCachePath");
+
const char scControlScript[] = "ControlScript";
template <typename T>
@@ -132,7 +138,7 @@ static QStringList readArgumentAttributes(QXmlStreamReader &reader, Settings::Pa
if (reader.isWhitespace())
continue;
arguments.append(reader.text().toString().split(QRegularExpression(QLatin1String("\\s+")),
- QString::SkipEmptyParts));
+ Qt::SkipEmptyParts));
}
break;
case QXmlStreamReader::EndElement: {
@@ -145,6 +151,26 @@ static QStringList readArgumentAttributes(QXmlStreamReader &reader, Settings::Pa
return arguments;
}
+static QMap<QString, QVariant> readProductImages(QXmlStreamReader &reader)
+{
+ QMap<QString, QVariant> productImages;
+ while (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("ProductImage")) {
+ QString key = QString();
+ QString value = QString();
+ while (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("Image")) {
+ key = reader.readElementText();
+ } else if (reader.name() == QLatin1String("Url")) {
+ value = reader.readElementText();
+ }
+ }
+ productImages.insert(key, value);
+ }
+ }
+ return productImages;
+}
+
static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefault, Settings::ParseMode parseMode,
QString *displayName = nullptr, bool *preselected = nullptr,
QString *tooltip = nullptr)
@@ -229,7 +255,7 @@ public:
: m_replacementRepos(false)
{}
- QVariantHash m_data;
+ QMultiHash<QString, QVariant> m_data;
bool m_replacementRepos;
QString absolutePathFromKey(const QString &key, const QString &suffix = QString()) const
@@ -292,12 +318,13 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
elementList << scName << scVersion << scTitle << scPublisher << scProductUrl
<< scTargetDir << scAdminTargetDir
<< scInstallerApplicationIcon << scInstallerWindowIcon
- << scLogo << scWatermark << scBanner << scBackground << scPageListPixmap
- << scStartMenuDir << scMaintenanceToolName << scMaintenanceToolIniFile << scRemoveTargetDir
+ << scLogo << scWatermark << scBanner << scBackground << scPageListPixmap << scAliasDefinitionsFile
+ << scStartMenuDir << scMaintenanceToolName << scMaintenanceToolIniFile << scMaintenanceToolAlias
+ << scRemoveTargetDir << scLocalCacheDir << scPersistentLocalCache
<< scRunProgram << scRunProgramArguments << scRunProgramDescription
<< scDependsOnLocalInstallerBinary
- << scAllowSpaceInPath << scAllowNonAsciiCharacters << scDisableAuthorizationFallback
- << scDisableCommandLineInterface
+ << scAllowSpaceInPath << scAllowNonAsciiCharacters << scAllowRepositoriesForOfflineInstaller
+ << scDisableAuthorizationFallback << scDisableCommandLineInterface
<< scWizardStyle << scStyleSheet << scTitleColor
<< scWizardDefaultWidth << scWizardDefaultHeight << scWizardMinimumWidth << scWizardMinimumHeight
<< scWizardShowPageList << scProductImages
@@ -307,7 +334,7 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
<< scSaveDefaultRepositories << scRepositoryCategories;
Settings s;
- s.d->m_data.insert(scPrefix, prefix);
+ s.d->m_data.replace(scPrefix, prefix);
while (reader.readNextStartElement()) {
const QString name = reader.name().toString();
if (!elementList.contains(name))
@@ -326,7 +353,7 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
} else if (name == scRunProgramArguments) {
s.setRunProgramArguments(readArgumentAttributes(reader, parseMode, QLatin1String("Argument")));
} else if (name == scProductImages) {
- s.setProductImages(readArgumentAttributes(reader, parseMode, QLatin1String("Image")));
+ s.setProductImages(readProductImages(reader));
} else if (name == scRemoteRepositories) {
s.addDefaultRepositories(readRepositories(reader, true, parseMode));
} else if (name == scRepositoryCategories) {
@@ -336,7 +363,7 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
s.setRepositoryCategoryDisplayName(repositoryCategoryName);
}
} else {
- s.d->m_data.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements));
+ s.d->m_data.replace(name, reader.readElementText(QXmlStreamReader::SkipChildElements));
}
}
if (reader.error() != QXmlStreamReader::NoError) {
@@ -351,39 +378,40 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
// Add some possible missing values
if (!s.d->m_data.contains(scInstallerApplicationIcon))
- s.d->m_data.insert(scInstallerApplicationIcon, QLatin1String(":/installer"));
+ s.d->m_data.replace(scInstallerApplicationIcon, QLatin1String(":/installer"));
if (!s.d->m_data.contains(scInstallerWindowIcon)) {
- s.d->m_data.insert(scInstallerWindowIcon,
+ s.d->m_data.replace(scInstallerWindowIcon,
QString(QLatin1String(":/installer") + s.systemIconSuffix()));
}
if (!s.d->m_data.contains(scRemoveTargetDir))
- s.d->m_data.insert(scRemoveTargetDir, scTrue);
+ s.d->m_data.replace(scRemoveTargetDir, scTrue);
if (s.d->m_data.value(scMaintenanceToolName).toString().isEmpty()) {
- s.d->m_data.insert(scMaintenanceToolName,
+ s.d->m_data.replace(scMaintenanceToolName,
// TODO: Remove deprecated 'UninstallerName'.
s.d->m_data.value(QLatin1String("UninstallerName"), QLatin1String("maintenancetool"))
.toString());
}
+
if (s.d->m_data.value(scTargetConfigurationFile).toString().isEmpty())
- s.d->m_data.insert(scTargetConfigurationFile, QLatin1String("components.xml"));
+ s.d->m_data.replace(scTargetConfigurationFile, QLatin1String("components.xml"));
if (s.d->m_data.value(scMaintenanceToolIniFile).toString().isEmpty()) {
- s.d->m_data.insert(scMaintenanceToolIniFile,
+ s.d->m_data.replace(scMaintenanceToolIniFile,
// TODO: Remove deprecated 'UninstallerIniFile'.
s.d->m_data.value(QLatin1String("UninstallerIniFile"), QString(s.maintenanceToolName()
+ QLatin1String(".ini"))).toString());
}
if (!s.d->m_data.contains(scDependsOnLocalInstallerBinary))
- s.d->m_data.insert(scDependsOnLocalInstallerBinary, false);
+ s.d->m_data.replace(scDependsOnLocalInstallerBinary, false);
if (!s.d->m_data.contains(scRepositorySettingsPageVisible))
- s.d->m_data.insert(scRepositorySettingsPageVisible, true);
+ s.d->m_data.replace(scRepositorySettingsPageVisible, true);
if (!s.d->m_data.contains(scCreateLocalRepository))
- s.d->m_data.insert(scCreateLocalRepository, false);
+ s.d->m_data.replace(scCreateLocalRepository, false);
if (!s.d->m_data.contains(scInstallActionColumnVisible))
- s.d->m_data.insert(scInstallActionColumnVisible, false);
+ s.d->m_data.replace(scInstallActionColumnVisible, false);
if (!s.d->m_data.contains(scAllowUnstableComponents))
- s.d->m_data.insert(scAllowUnstableComponents, false);
+ s.d->m_data.replace(scAllowUnstableComponents, false);
if (!s.d->m_data.contains(scSaveDefaultRepositories))
- s.d->m_data.insert(scSaveDefaultRepositories, true);
+ s.d->m_data.replace(scSaveDefaultRepositories, true);
return s;
}
@@ -457,11 +485,11 @@ static int lengthToInt(const QVariant &variant)
QString length = variant.toString().trimmed();
if (length.endsWith(QLatin1String("em"), Qt::CaseInsensitive)) {
length.chop(2);
- return qRound(length.toDouble() * QApplication::fontMetrics().height());
+ return qRound(length.toDouble() * QFontMetricsF(QApplication::font()).height());
}
if (length.endsWith(QLatin1String("ex"), Qt::CaseInsensitive)) {
length.chop(2);
- return qRound(length.toDouble() * QApplication::fontMetrics().xHeight());
+ return qRound(length.toDouble() * QFontMetricsF(QApplication::font()).xHeight());
}
if (length.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
length.chop(2);
@@ -497,25 +525,23 @@ bool Settings::wizardShowPageList() const
return d->m_data.value(scWizardShowPageList, true).toBool();
}
-QStringList Settings::productImages() const
+QMap<QString, QVariant> Settings::productImages() const
{
const QVariant variant = d->m_data.value(scProductImages);
- QStringList imagePaths;
- if (variant.canConvert<QStringList>()) {
- foreach (auto image, variant.value<QStringList>()) {
- QString imagePath = QFileInfo(image).isAbsolute()
- ? image
- : d->m_data.value(scPrefix).toString() + QLatin1Char('/') + image;
- QInstaller::replaceHighDpiImage(imagePath);
- imagePaths.append(imagePath);
- }
- }
+ QMap<QString, QVariant> imagePaths;
+ if (variant.canConvert<QVariantMap>())
+ imagePaths = variant.toMap();
return imagePaths;
}
-void Settings::setProductImages(const QStringList &images)
+void Settings::setProductImages(const QMap<QString, QVariant> &images)
+{
+ d->m_data.insert(scProductImages, QVariant::fromValue(images));
+}
+
+QString Settings::aliasDefinitionsFile() const
{
- d->m_data.insert(scProductImages, images);
+ return d->absolutePathFromKey(scAliasDefinitionsFile);
}
QString Settings::installerApplicationIcon() const
@@ -554,6 +580,11 @@ QString Settings::maintenanceToolIniFile() const
return d->m_data.value(scMaintenanceToolIniFile).toString();
}
+QString Settings::maintenanceToolAlias() const
+{
+ return d->m_data.value(scMaintenanceToolAlias).toString();
+}
+
QString Settings::runProgram() const
{
return d->m_data.value(scRunProgram).toString();
@@ -569,7 +600,7 @@ QStringList Settings::runProgramArguments() const
void Settings::setRunProgramArguments(const QStringList &arguments)
{
- d->m_data.insert(scRunProgramArguments, arguments);
+ d->m_data.replace(scRunProgramArguments, arguments);
}
@@ -618,6 +649,11 @@ bool Settings::allowNonAsciiCharacters() const
return d->m_data.value(scAllowNonAsciiCharacters, false).toBool();
}
+bool Settings::allowRepositoriesForOfflineInstaller() const
+{
+ return d->m_data.value(scAllowRepositoriesForOfflineInstaller, true).toBool();
+}
+
bool Settings::disableAuthorizationFallback() const
{
return d->m_data.value(scDisableAuthorizationFallback, false).toBool();
@@ -676,7 +712,7 @@ void Settings::setDefaultRepositories(const QSet<Repository> &repositories)
void Settings::addDefaultRepositories(const QSet<Repository> &repositories)
{
foreach (const Repository &repository, repositories)
- d->m_data.insertMulti(scRepositories, QVariant().fromValue(repository));
+ d->m_data.insert(scRepositories, QVariant().fromValue(repository));
}
void Settings::setRepositoryCategories(const QSet<RepositoryCategory> &repositories)
@@ -688,7 +724,7 @@ void Settings::setRepositoryCategories(const QSet<RepositoryCategory> &repositor
void Settings::addRepositoryCategories(const QSet<RepositoryCategory> &repositories)
{
foreach (const RepositoryCategory &repository, repositories)
- d->m_data.insertMulti(scRepositoryCategories, QVariant().fromValue(repository));
+ d->m_data.insert(scRepositoryCategories, QVariant().fromValue(repository));
}
Settings::Update Settings::updateRepositoryCategories(const RepoHash &updates)
@@ -713,13 +749,13 @@ Settings::Update Settings::updateRepositoryCategories(const RepoHash &updates)
}
}
if (update) {
- categories = categoriesList.toSet();
+ categories = QSet<RepositoryCategory>(categoriesList.begin(), categoriesList.end());
setRepositoryCategories(categories);
}
return update ? Settings::UpdatesApplied : Settings::NoUpdatesApplied;
}
-static bool apply(const RepoHash &updates, QHash<QUrl, Repository> *reposToUpdate)
+static bool apply(const RepoHash &updates, QMultiHash<QUrl, Repository> *reposToUpdate)
{
bool update = false;
QList<QPair<Repository, Repository> > values = updates.values(QLatin1String("replace"));
@@ -757,15 +793,17 @@ Settings::Update Settings::updateDefaultRepositories(const RepoHash &updates)
if (updates.isEmpty())
return Settings::NoUpdatesApplied;
- QHash <QUrl, Repository> defaultRepos;
+ QMultiHash <QUrl, Repository> defaultRepos;
foreach (const QVariant &variant, d->m_data.values(scRepositories)) {
const Repository repository = variant.value<Repository>();
defaultRepos.insert(repository.url(), repository);
}
const bool updated = apply(updates, &defaultRepos);
- if (updated)
- setDefaultRepositories(defaultRepos.values().toSet());
+ if (updated) {
+ const QList<Repository> repositoriesList = defaultRepos.values();
+ setDefaultRepositories(QSet<Repository>(repositoriesList.begin(), repositoriesList.end()));
+ }
return updated ? Settings::UpdatesApplied : Settings::NoUpdatesApplied;
}
@@ -784,7 +822,7 @@ void Settings::addTemporaryRepositories(const QSet<Repository> &repositories, bo
{
d->m_replacementRepos = replace;
foreach (const Repository &repository, repositories)
- d->m_data.insertMulti(scTmpRepositories, QVariant().fromValue(repository));
+ d->m_data.insert(scTmpRepositories, QVariant().fromValue(repository));
}
QSet<Repository> Settings::userRepositories() const
@@ -801,7 +839,7 @@ void Settings::setUserRepositories(const QSet<Repository> &repositories)
void Settings::addUserRepositories(const QSet<Repository> &repositories)
{
foreach (const Repository &repository, repositories)
- d->m_data.insertMulti(scUserRepositories, QVariant().fromValue(repository));
+ d->m_data.insert(scUserRepositories, QVariant().fromValue(repository));
}
Settings::Update Settings::updateUserRepositories(const RepoHash &updates)
@@ -809,15 +847,17 @@ Settings::Update Settings::updateUserRepositories(const RepoHash &updates)
if (updates.isEmpty())
return Settings::NoUpdatesApplied;
- QHash <QUrl, Repository> reposToUpdate;
+ QMultiHash <QUrl, Repository> reposToUpdate;
foreach (const QVariant &variant, d->m_data.values(scUserRepositories)) {
const Repository repository = variant.value<Repository>();
reposToUpdate.insert(repository.url(), repository);
}
const bool updated = apply(updates, &reposToUpdate);
- if (updated)
- setUserRepositories(reposToUpdate.values().toSet());
+ if (updated) {
+ const QList<Repository> repositoriesList = reposToUpdate.values();
+ setUserRepositories(QSet<Repository>(repositoriesList.begin(), repositoriesList.end()));
+ }
return updated ? Settings::UpdatesApplied : Settings::NoUpdatesApplied;
}
@@ -844,7 +884,41 @@ bool Settings::repositorySettingsPageVisible() const
void Settings::setRepositorySettingsPageVisible(bool visible)
{
- d->m_data.insert(scRepositorySettingsPageVisible, visible);
+ d->m_data.replace(scRepositorySettingsPageVisible, visible);
+}
+
+bool Settings::persistentLocalCache() const
+{
+ return d->m_data.value(scPersistentLocalCache, true).toBool();
+}
+
+void Settings::setPersistentLocalCache(bool enable)
+{
+ d->m_data.replace(scPersistentLocalCache, enable);
+}
+
+QString Settings::localCacheDir() const
+{
+ const QString fallback = QLatin1String("qt-installer-framework") + QDir::separator()
+ + QUuid::createUuidV3(QUuid(), applicationName()).toString(QUuid::WithoutBraces);
+ return d->m_data.value(scLocalCacheDir, fallback).toString();
+}
+
+void Settings::setLocalCacheDir(const QString &dir)
+{
+ d->m_data.replace(scLocalCacheDir, dir);
+}
+
+QString Settings::localCachePath() const
+{
+ const QString fallback = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)
+ + QDir::separator() + localCacheDir();
+ return d->m_data.value(scLocalCachePath, fallback).toString();
+}
+
+void Settings::setLocalCachePath(const QString &path)
+{
+ d->m_data.replace(scLocalCachePath, path);
}
Settings::ProxyType Settings::proxyType() const
@@ -854,7 +928,7 @@ Settings::ProxyType Settings::proxyType() const
void Settings::setProxyType(Settings::ProxyType type)
{
- d->m_data.insert(scProxyType, type);
+ d->m_data.replace(scProxyType, type);
}
QNetworkProxy Settings::ftpProxy() const
@@ -867,7 +941,7 @@ QNetworkProxy Settings::ftpProxy() const
void Settings::setFtpProxy(const QNetworkProxy &proxy)
{
- d->m_data.insert(scFtpProxy, QVariant::fromValue(proxy));
+ d->m_data.replace(scFtpProxy, QVariant::fromValue(proxy));
}
QNetworkProxy Settings::httpProxy() const
@@ -880,7 +954,7 @@ QNetworkProxy Settings::httpProxy() const
void Settings::setHttpProxy(const QNetworkProxy &proxy)
{
- d->m_data.insert(scHttpProxy, QVariant::fromValue(proxy));
+ d->m_data.replace(scHttpProxy, QVariant::fromValue(proxy));
}
QStringList Settings::translations() const
@@ -893,7 +967,7 @@ QStringList Settings::translations() const
void Settings::setTranslations(const QStringList &translations)
{
- d->m_data.insert(scTranslations, translations);
+ d->m_data.replace(scTranslations, translations);
}
QString Settings::controlScript() const
@@ -913,7 +987,7 @@ bool Settings::allowUnstableComponents() const
void Settings::setAllowUnstableComponents(bool allow)
{
- d->m_data.insert(scAllowUnstableComponents, allow);
+ d->m_data.replace(scAllowUnstableComponents, allow);
}
bool Settings::saveDefaultRepositories() const
@@ -923,16 +997,16 @@ bool Settings::saveDefaultRepositories() const
void Settings::setSaveDefaultRepositories(bool save)
{
- d->m_data.insert(scSaveDefaultRepositories, save);
+ d->m_data.replace(scSaveDefaultRepositories, save);
}
QString Settings::repositoryCategoryDisplayName() const
{
QString displayName = d->m_data.value(QLatin1String(scRepositoryCategoryDisplayName)).toString();
- return displayName.isEmpty() ? tr("Select Categories") : displayName;
+ return displayName.isEmpty() ? tr("Categories") : displayName;
}
void Settings::setRepositoryCategoryDisplayName(const QString& name)
{
- d->m_data.insert(scRepositoryCategoryDisplayName, name);
+ d->m_data.replace(scRepositoryCategoryDisplayName, name);
}
diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h
index 68a1592ff..85b59869c 100644
--- a/src/libs/installer/settings.h
+++ b/src/libs/installer/settings.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -42,7 +42,7 @@
namespace QInstaller {
class Repository;
-typedef QHash<QString, QPair<Repository, Repository> > RepoHash;
+typedef QMultiHash<QString, QPair<Repository, Repository> > RepoHash;
class INSTALLER_EXPORT Settings
{
@@ -92,8 +92,10 @@ public:
int wizardMinimumWidth() const;
int wizardMinimumHeight() const;
bool wizardShowPageList() const;
- QStringList productImages() const;
- void setProductImages(const QStringList &images);
+ QMap<QString, QVariant> productImages() const;
+ void setProductImages(const QMap<QString, QVariant> &images);
+
+ QString aliasDefinitionsFile() const;
QString applicationName() const;
QString version() const;
@@ -110,6 +112,7 @@ public:
QString removeTargetDir() const;
QString maintenanceToolName() const;
QString maintenanceToolIniFile() const;
+ QString maintenanceToolAlias() const;
QString configurationFileName() const;
@@ -142,6 +145,8 @@ public:
bool allowSpaceInPath() const;
bool allowNonAsciiCharacters() const;
+ bool allowRepositoriesForOfflineInstaller() const;
+
bool disableAuthorizationFallback() const;
bool disableCommandLineInterface() const;
@@ -152,6 +157,15 @@ public:
bool repositorySettingsPageVisible() const;
void setRepositorySettingsPageVisible(bool visible);
+ bool persistentLocalCache() const;
+ void setPersistentLocalCache(bool enable);
+
+ QString localCacheDir() const;
+ void setLocalCacheDir(const QString &dir);
+
+ QString localCachePath() const;
+ void setLocalCachePath(const QString &path);
+
Settings::ProxyType proxyType() const;
void setProxyType(Settings::ProxyType type);
diff --git a/src/libs/installer/settingsoperation.cpp b/src/libs/installer/settingsoperation.cpp
index c5fe8384c..a74161178 100644
--- a/src/libs/installer/settingsoperation.cpp
+++ b/src/libs/installer/settingsoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -46,6 +46,7 @@ SettingsOperation::SettingsOperation(PackageManagerCore *core)
: UpdateOperation(core)
{
setName(QLatin1String("Settings"));
+ setRequiresUnreplacedVariables(true);
}
void SettingsOperation::backup()
@@ -104,10 +105,17 @@ bool SettingsOperation::performOperation()
if (!checkArguments())
return false;
- const QString path = argumentKeyValue(QLatin1String("path"));
+ QString path = argumentKeyValue(QLatin1String("path"));
const QString method = argumentKeyValue(QLatin1String("method"));
const QString key = argumentKeyValue(QLatin1String("key"));
- const QString aValue = argumentKeyValue(QLatin1String("value"));
+ QString aValue = argumentKeyValue(QLatin1String("value"));
+
+ if (requiresUnreplacedVariables()) {
+ if (PackageManagerCore *const core = packageManager()) {
+ path = core->replaceVariables(path);
+ aValue = core->replaceVariables(aValue);
+ }
+ }
// use MkdirOperation to get the path so it can remove it with MkdirOperation::undoOperation later
KDUpdater::MkdirOperation mkDirOperation;
@@ -120,7 +128,7 @@ bool SettingsOperation::performOperation()
}
setValue(QLatin1String("createddir"), mkDirOperation.value(QLatin1String("createddir")));
- QSettingsWrapper settings(path, QSettingsWrapper::IniFormat);
+ QSettingsWrapper settings(path, QSettings::IniFormat);
if (method == QLatin1String("set"))
settings.setValue(key, aValue);
else if (method == QLatin1String("remove"))
@@ -152,17 +160,28 @@ bool SettingsOperation::undoOperation()
{
if (!checkArguments())
return false;
- const QString path = argumentKeyValue(QLatin1String("path"));
+ QString path = argumentKeyValue(QLatin1String("path"));
const QString method = argumentKeyValue(QLatin1String("method"));
const QString key = argumentKeyValue(QLatin1String("key"));
- const QString aValue = argumentKeyValue(QLatin1String("value"));
+ QString aValue = argumentKeyValue(QLatin1String("value"));
if (method.startsWith(QLatin1String("remove")))
return true;
+ if (requiresUnreplacedVariables()) {
+ if (PackageManagerCore *const core = packageManager()) {
+ path = core->replaceVariables(path);
+ aValue = core->replaceVariables(aValue);
+ // Check is different settings file is wanted to be used.
+ // Old settings file name should be set to variable <variable_name>_OLD,
+ // and new path is then read from <variable_name> variable.
+ variableReplacement(&path);
+ }
+ }
+
bool cleanUp = false;
{ // kill the scope to kill settings object, else remove file will not work
- QSettingsWrapper settings(path, QSettingsWrapper::IniFormat);
+ QSettingsWrapper settings(path, QSettings::IniFormat);
if (method == QLatin1String("set")) {
settings.remove(key);
} else if (method == QLatin1String("add_array_value")) {
diff --git a/src/libs/installer/settingsoperation.h b/src/libs/installer/settingsoperation.h
index 0b94ea015..97655a85c 100644
--- a/src/libs/installer/settingsoperation.h
+++ b/src/libs/installer/settingsoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,10 +39,10 @@ class INSTALLER_EXPORT SettingsOperation : public Operation
public:
explicit SettingsOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
private:
bool checkArguments();
diff --git a/src/libs/installer/simplemovefileoperation.cpp b/src/libs/installer/simplemovefileoperation.cpp
index 5f3000be0..5bbbdabb4 100644
--- a/src/libs/installer/simplemovefileoperation.cpp
+++ b/src/libs/installer/simplemovefileoperation.cpp
@@ -93,7 +93,7 @@ bool SimpleMoveFileOperation::performOperation()
bool SimpleMoveFileOperation::undoOperation()
{
- if (parseUndoOperationArguments().count() > 0)
+ if (skipUndoOperation())
return true;
const QString source = arguments().at(0);
const QString target = arguments().at(1);
diff --git a/src/libs/installer/simplemovefileoperation.h b/src/libs/installer/simplemovefileoperation.h
index 26cb5c462..850468b2f 100644
--- a/src/libs/installer/simplemovefileoperation.h
+++ b/src/libs/installer/simplemovefileoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -42,10 +42,10 @@ class INSTALLER_EXPORT SimpleMoveFileOperation : public QObject, public Operatio
public:
explicit SimpleMoveFileOperation(PackageManagerCore *core);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
Q_SIGNALS:
void outputTextChanged(const QString &progress);
diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp
index 508ce7a6e..e5df8e35f 100644
--- a/src/libs/installer/sysinfo_win.cpp
+++ b/src/libs/installer/sysinfo_win.cpp
@@ -64,7 +64,7 @@ VolumeInfo updateVolumeSizeInformation(const VolumeInfo &info)
return update;
}
-/*!
+/*
Returns a list of volume info objects that are mounted as network drive shares.
*/
QList<VolumeInfo> networkVolumeInfosFromMountPoints()
@@ -95,7 +95,7 @@ QList<VolumeInfo> networkVolumeInfosFromMountPoints()
return volumes;
}
-/*!
+/*
Returns a list of volume info objects based on the given \a volumeGUID. The function also solves mounted
volume folder paths. It does not return any network drive shares.
*/
@@ -109,7 +109,7 @@ QList<VolumeInfo> localVolumeInfosFromMountPoints(PTCHAR volumeGUID)
TCHAR volumeNames[MAX_PATH + 1] = { 0 };
if (GetVolumePathNamesForVolumeName(volumeGUID, volumeNames, MAX_PATH, &bufferSize)) {
QStringList mountedPaths = QString::fromWCharArray(volumeNames, bufferSize).split(QLatin1Char(char(0)),
- QString::SkipEmptyParts);
+ Qt::SkipEmptyParts);
foreach (const QString &mountedPath, mountedPaths) {
VolumeInfo info;
info.setMountPath(mountedPath);
@@ -150,10 +150,10 @@ QList<VolumeInfo> mountedVolumes()
bool pathIsOnLocalDevice(const QString &path)
{
- if (!QFileInfo(path).exists())
+ if (!QFileInfo::exists(path))
return false;
- if (path.startsWith(QLatin1String("\\\\")))
+ if (path.startsWith(QLatin1String("//")))
return false;
QDir dir(path);
diff --git a/src/libs/installer/systeminfo.cpp b/src/libs/installer/systeminfo.cpp
index 6a1976c4a..aed02c569 100644
--- a/src/libs/installer/systeminfo.cpp
+++ b/src/libs/installer/systeminfo.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -55,6 +55,7 @@ SystemInfo::SystemInfo(QObject *parent) : QObject(parent)
\list
\li "i386"
\li "x86_64"
+ \li "arm64"
\endlist
\note This function depends on what the OS will report and may not detect the actual CPU
@@ -62,7 +63,7 @@ SystemInfo::SystemInfo(QObject *parent) : QObject(parent)
OS running on a 64-bit CPU is usually unable to determine whether the CPU is actually capable
of running 64-bit programs.
- \sa QSysInfo::currentCpuArchitecture()
+ \sa QSysInfo::currentCpuArchitecture() buildCpuArchitecture()
*/
QString SystemInfo::currentCpuArchitecture() const
{
@@ -70,6 +71,29 @@ QString SystemInfo::currentCpuArchitecture() const
}
/*!
+ \property SystemInfo::buildCpuArchitecture
+
+ The architecture of the CPU that the application was compiled for, in text format.
+
+ Possible values include:
+ \list
+ \li "i386"
+ \li "x86_64"
+ \li "arm64"
+ \endlist
+
+ \note Note that this may not match the actual CPU that the application is running on if
+ there's an emulation layer or if the CPU supports multiple architectures (like x86-64
+ processors supporting i386 applications). To detect that, use \c installer.currentCpuArchitecture()
+
+ \sa QSysInfo::buildCpuArchitecture() currentCpuArchitecture()
+*/
+QString SystemInfo::buildCpuArchitecture() const
+{
+ return QSysInfo::buildCpuArchitecture();
+}
+
+/*!
\property SystemInfo::kernelType
The type of the operating system kernel the installer was compiled for. It is also the
@@ -124,7 +148,7 @@ QString SystemInfo::kernelVersion() const
\list
\li "windows"
\li "opensuse" (for the Linux openSUSE distribution)
- \li "osx"
+ \li "macos"
\endlist
\sa QSysInfo::productType()
diff --git a/src/libs/installer/systeminfo.h b/src/libs/installer/systeminfo.h
index c5451605e..a1393397a 100644
--- a/src/libs/installer/systeminfo.h
+++ b/src/libs/installer/systeminfo.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,6 +39,7 @@ class SystemInfo : public QObject
Q_DISABLE_COPY(SystemInfo)
Q_PROPERTY(QString currentCpuArchitecture READ currentCpuArchitecture CONSTANT)
+ Q_PROPERTY(QString buildCpuArchitecture READ buildCpuArchitecture CONSTANT)
Q_PROPERTY(QString kernelType READ kernelType CONSTANT)
Q_PROPERTY(QString kernelVersion READ kernelVersion CONSTANT)
Q_PROPERTY(QString productType READ productType CONSTANT)
@@ -49,7 +50,7 @@ public:
explicit SystemInfo(QObject *parent = 0);
QString currentCpuArchitecture() const;
-
+ QString buildCpuArchitecture() const;
QString kernelType() const;
QString kernelVersion() const;
QString productType() const;
diff --git a/src/libs/installer/testrepository.h b/src/libs/installer/testrepository.h
index 80d964692..a214188a9 100644
--- a/src/libs/installer/testrepository.h
+++ b/src/libs/installer/testrepository.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -52,8 +52,8 @@ public:
void setRepository(const Repository &repository);
private slots:
- void doStart();
- void doCancel();
+ void doStart() override;
+ void doCancel() override;
void onTimeout();
void downloadCompleted();
diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp
index 668ace699..de753f71a 100644
--- a/src/libs/installer/uninstallercalculator.cpp
+++ b/src/libs/installer/uninstallercalculator.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,8 +32,6 @@
#include "packagemanagercore.h"
#include "globals.h"
-#include <QDebug>
-
namespace QInstaller {
/*!
@@ -42,120 +40,161 @@ namespace QInstaller {
\internal
*/
-UninstallerCalculator::UninstallerCalculator(const QList<Component *> &installedComponents)
- : m_installedComponents(installedComponents)
+UninstallerCalculator::UninstallerCalculator(PackageManagerCore *core
+ , const AutoDependencyHash &autoDependencyComponentHash
+ , const LocalDependencyHash &localDependencyComponentHash
+ , const QStringList &localVirtualComponents)
+ : CalculatorBase(core)
+ , m_autoDependencyComponentHash(autoDependencyComponentHash)
+ , m_localDependencyComponentHash(localDependencyComponentHash)
+ , m_localVirtualComponents(localVirtualComponents)
{
}
-QSet<Component *> UninstallerCalculator::componentsToUninstall() const
+UninstallerCalculator::~UninstallerCalculator()
{
- return m_componentsToUninstall;
}
-void UninstallerCalculator::appendComponentToUninstall(Component *component)
+bool UninstallerCalculator::solveComponent(Component *component, const QString &version)
{
+ Q_UNUSED(version)
+
if (!component)
- return;
+ return true;
if (!component->isInstalled())
- return;
+ return true;
- PackageManagerCore *core = component->packageManagerCore();
- // remove all already resolved dependees
- QSet<Component *> dependees = core->dependees(component).toSet()
- .subtract(m_componentsToUninstall);
+ if (m_localDependencyComponentHash.contains(component->name())) {
+ const QStringList &dependencies = PackageManagerCore::parseNames(m_localDependencyComponentHash.value(component->name()));
+ for (const QString &dependencyComponent : dependencies) {
+ Component *depComponent = m_core->componentByName(dependencyComponent);
+ if (!depComponent || !depComponent->isInstalled())
+ continue;
+
+ if (m_resolvedComponents.contains(depComponent)
+ || m_core->orderedComponentsToInstall().contains(depComponent)) {
+ // Component is already selected for uninstall or update
+ continue;
+ }
+
+ if (depComponent->isEssential() || depComponent->forcedInstallation()) {
+ const QString errorMessage = QCoreApplication::translate("InstallerCalculator",
+ "Impossible dependency resolution detected. Forced install component \"%1\" would be uninstalled "
+ "because its dependency \"%2\" is marked for uninstallation with reason: \"%3\".")
+ .arg(depComponent->name(), component->name(), resolutionText(component));
+
+ qCWarning(QInstaller::lcInstallerInstallLog).noquote() << errorMessage;
+ m_errorString.append(errorMessage);
+ return false;
+ }
+ // Resolve also all cascading dependencies
+ if (!solveComponent(depComponent))
+ return false;
- foreach (Component *dependee, dependees)
- appendComponentToUninstall(dependee);
+ insertResolution(depComponent, Resolution::Dependent, component->name());
+ }
+ }
- m_componentsToUninstall.insert(component);
+ m_resolvedComponents.append(component);
+ return true;
}
-void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components)
+bool UninstallerCalculator::solve(const QList<Component*> &components)
{
- foreach (Component *component, components)
- appendComponentToUninstall(component);
+ foreach (Component *component, components) {
+ if (!solveComponent(component))
+ return false;
+ }
QList<Component*> autoDependOnList;
// All regular dependees are resolved. Now we are looking for auto depend on components.
- foreach (Component *component, m_installedComponents) {
+ for (Component *component : components) {
// If a components is installed and not yet scheduled for un-installation, check for auto depend.
- if (component->isInstalled() && !m_componentsToUninstall.contains(component)) {
- QStringList autoDependencies = PackageManagerCore::parseNames(component->autoDependencies());
- if (autoDependencies.isEmpty())
- continue;
-
- // This code needs to be enabled once the scripts use isInstalled, installationRequested and
- // uninstallationRequested...
- if (autoDependencies.first().compare(scScript, Qt::CaseInsensitive) == 0) {
- //QScriptValue valueFromScript;
- //try {
- // valueFromScript = callScriptMethod(QLatin1String("isAutoDependOn"));
- //} catch (const Error &error) {
- // // keep the component, should do no harm
- // continue;
- //}
-
- //if (valueFromScript.isValid() && !valueFromScript.toBool())
- // autoDependOnList.append(component);
- continue;
- }
-
- foreach (Component *c, m_installedComponents) {
- const QString replaces = c->value(scReplaces);
- const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
- QString::SkipEmptyParts) << c->name();
- foreach (const QString &possibleName, possibleNames) {
-
- Component *cc = PackageManagerCore::componentByName(possibleName, m_installedComponents);
- if (cc && (cc->installAction() != ComponentModelHelper::AutodependUninstallation)) {
- autoDependencies.removeAll(possibleName);
-
- }
- }
- }
-
- // A component requested auto uninstallation, keep it to resolve their dependencies as well.
- if (!autoDependencies.isEmpty()) {
- autoDependOnList.append(component);
- component->setInstallAction(ComponentModelHelper::AutodependUninstallation);
+ if (!m_autoDependencyComponentHash.contains(component->name()))
+ continue;
+ const QStringList autoDependencies = PackageManagerCore::parseNames(m_autoDependencyComponentHash.value(component->name()));
+ for (const QString &autoDependencyComponent : autoDependencies) {
+ Component *autoDepComponent = m_core->componentByName(autoDependencyComponent);
+ if (autoDepComponent && autoDepComponent->isInstalled()) {
+ // A component requested auto uninstallation, keep it to resolve their dependencies as well.
+ if (!m_resolvedComponents.contains(autoDepComponent)) {
+ insertResolution(autoDepComponent, Resolution::Automatic, component->name());
+ autoDepComponent->setInstallAction(ComponentModelHelper::AutodependUninstallation);
+ autoDependOnList.append(autoDepComponent);
+ }
}
}
}
if (!autoDependOnList.isEmpty())
- appendComponentsToUninstall(autoDependOnList);
+ solve(autoDependOnList);
else
- continueAppendComponentsToUninstall();
+ appendVirtualComponentsToUninstall();
+
+ return true;
}
-void UninstallerCalculator::continueAppendComponentsToUninstall()
+QString UninstallerCalculator::resolutionText(Component *component) const
+{
+ Resolution reason = resolutionType(component);
+ switch (reason) {
+ case Resolution::Selected:
+ return QCoreApplication::translate("UninstallerCalculator",
+ "Deselected Components:");
+ case Resolution::Replaced:
+ return QCoreApplication::translate("UninstallerCalculator", "Components replaced "
+ "by \"%1\":").arg(referencedComponent(component));
+ case Resolution::VirtualDependent:
+ return QCoreApplication::translate("UninstallerCalculator",
+ "Removing virtual components without existing dependencies:");
+ case Resolution::Dependent:
+ return QCoreApplication::translate("UninstallerCalculator", "Components "
+ "dependency \"%1\" removed:").arg(referencedComponent(component));
+ case Resolution::Automatic:
+ return QCoreApplication::translate("UninstallerCalculator", "Components "
+ "autodependency \"%1\" removed:").arg(referencedComponent(component));
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid uninstall resolution detected!");
+ }
+ return QString();
+}
+
+void UninstallerCalculator::appendVirtualComponentsToUninstall()
{
QList<Component*> unneededVirtualList;
// Check for virtual components without dependees
- foreach (Component *component, m_installedComponents) {
- if (component->isInstalled() && component->isVirtual() && !m_componentsToUninstall.contains(component)) {
- // Components with auto dependencies were handled in the previous step
- if (!component->autoDependencies().isEmpty())
- continue;
- if (component->forcedInstallation())
- continue;
-
- bool required = false;
- PackageManagerCore *core = component->packageManagerCore();
- foreach (Component *dependee, core->dependees(component)) {
- if (dependee->isInstalled() && !m_componentsToUninstall.contains(dependee)) {
- required = true;
- break;
- }
- }
- if (!required)
- unneededVirtualList.append(component);
+ for (const QString &componentName : qAsConst(m_localVirtualComponents)) {
+ Component *virtualComponent = m_core->componentByName(componentName, m_core->components(PackageManagerCore::ComponentType::All));
+ if (!virtualComponent)
+ continue;
+
+ if (virtualComponent->isInstalled() && !m_resolvedComponents.contains(virtualComponent)) {
+ // Components with auto dependencies were handled in the previous step
+ if (!virtualComponent->autoDependencies().isEmpty() || virtualComponent->forcedInstallation())
+ continue;
+
+ if (!isRequiredVirtualPackage(virtualComponent)) {
+ unneededVirtualList.append(virtualComponent);
+ insertResolution(virtualComponent, Resolution::VirtualDependent);
+ }
}
}
if (!unneededVirtualList.isEmpty())
- appendComponentsToUninstall(unneededVirtualList);
+ solve(unneededVirtualList);
+}
+
+bool UninstallerCalculator::isRequiredVirtualPackage(Component *component)
+{
+ const QStringList localInstallDependents = m_core->localDependenciesToComponent(component);
+ for (const QString &dependent : localInstallDependents) {
+ Component *comp = m_core->componentByName(dependent);
+ if (!m_resolvedComponents.contains(comp)) {
+ return true;
+ }
+ }
+ return m_core->isDependencyForRequestedComponent(component);
}
} // namespace QInstaller
diff --git a/src/libs/installer/uninstallercalculator.h b/src/libs/installer/uninstallercalculator.h
index a684c92cc..24979a9bb 100644
--- a/src/libs/installer/uninstallercalculator.h
+++ b/src/libs/installer/uninstallercalculator.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,6 +29,8 @@
#define UNINSTALLERCALCULATOR_H
#include "installer_global.h"
+#include "qinstallerglobal.h"
+#include "calculatorbase.h"
#include <QHash>
#include <QList>
@@ -38,26 +40,32 @@
namespace QInstaller {
class Component;
+class PackageManagerCore;
-class INSTALLER_EXPORT UninstallerCalculator
+class INSTALLER_EXPORT UninstallerCalculator : public CalculatorBase
{
public:
- UninstallerCalculator(const QList<Component *> &installedComponents);
+ UninstallerCalculator(PackageManagerCore *core,
+ const AutoDependencyHash &autoDependencyComponentHash,
+ const LocalDependencyHash &localDependencyComponentHash,
+ const QStringList &localVirtualComponents);
+ ~UninstallerCalculator();
- QSet<Component*> componentsToUninstall() const;
-
- void appendComponentsToUninstall(const QList<Component*> &components);
+ bool solve(const QList<Component*> &components) override;
+ QString resolutionText(Component *component) const override;
private:
+ bool solveComponent(Component *component, const QString &version = QString()) override;
- void appendComponentToUninstall(Component *component);
- void continueAppendComponentsToUninstall();
+ bool isRequiredVirtualPackage(Component *component);
+ void appendVirtualComponentsToUninstall();
- QList<Component *> m_installedComponents;
- QSet<Component *> m_componentsToUninstall;
+private:
+ AutoDependencyHash m_autoDependencyComponentHash;
+ LocalDependencyHash m_localDependencyComponentHash;
+ QStringList m_localVirtualComponents;
};
-}
-
+} // namespace QInstaller
#endif // UNINSTALLERCALCULATOR_H
diff --git a/src/libs/installer/unziptask.h b/src/libs/installer/unziptask.h
index e382b9f47..877b9b970 100644
--- a/src/libs/installer/unziptask.h
+++ b/src/libs/installer/unziptask.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,7 +40,7 @@ public:
UnzipTask() {}
UnzipTask(const QString &source, const QString &target);
- void doTask(QFutureInterface<QString> &fi);
+ void doTask(QFutureInterface<QString> &fi) override;
private:
void setBytesToExtract(qint64 bytes);
diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp
index 7506a13fe..9b64ade37 100644
--- a/src/libs/installer/utils.cpp
+++ b/src/libs/installer/utils.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,6 +29,7 @@
#include "utils.h"
#include "fileutils.h"
+#include "qsettingswrapper.h"
#include <QCoreApplication>
#include <QDateTime>
@@ -56,7 +57,7 @@
*/
void QInstaller::uiDetachedWait(int ms)
{
- QTime timer;
+ QElapsedTimer timer;
timer.start();
do {
QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
@@ -138,7 +139,7 @@ QStringList QInstaller::localeCandidates(const QString &locale_)
at least one mutually exclusive pair of options set. Otherwise returns an empty
\c QStringList. The options considered mutual are provided with \a options.
*/
-QStringList QInstaller::checkMutualOptions(CommandLineParser &parser, const QStringList &options)
+QStringList QInstaller::checkMutualOptions(const CommandLineParser &parser, const QStringList &options)
{
QStringList mutual;
foreach (const QString &option, options) {
@@ -170,7 +171,7 @@ QByteArray QInstaller::calculateHash(QIODevice *device, QCryptographicHash::Algo
const qint64 numRead = device->read(buffer.data(), buffer.size());
if (numRead <= 0)
return hash.result();
- hash.addData(buffer.constData(), numRead);
+ hash.addData(buffer.left(numRead));
}
return QByteArray(); // never reached
}
@@ -323,6 +324,21 @@ QStringList QInstaller::parseCommandLineArgs(int argc, char **argv)
}
#endif
+/*!
+ On Windows checks if the user account has the privilege required to create a symbolic links.
+ Returns \c true if the privilege is held, \c false otherwise.
+
+ On Unix platforms always returns \c true.
+*/
+bool QInstaller::canCreateSymbolicLinks()
+{
+#ifdef Q_OS_WIN
+ return ((setPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME, true)
+ && checkPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME)) || developerModeEnabled());
+#endif
+ return true;
+}
+
#ifdef Q_OS_WIN
// taken from qprocess_win.cpp
static QString qt_create_commandline(const QString &program, const QStringList &arguments)
@@ -401,4 +417,84 @@ QString QInstaller::windowsErrorString(int errorCode)
return ret;
}
+/*!
+ \internal
+
+ Sets the enabled state of \a privilege to \a enable for this process.
+ The privilege must be held by the current login user. Returns \c true
+ on success, \c false on failure.
+*/
+bool QInstaller::setPrivilege(const wchar_t *privilege, bool enable)
+{
+ LUID luid;
+ TOKEN_PRIVILEGES privileges;
+ HANDLE token;
+ HANDLE process = GetCurrentProcess();
+
+ if (!OpenProcessToken(process, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &token))
+ return false;
+
+ if (!LookupPrivilegeValue(nullptr, privilege, &luid))
+ return false;
+
+ privileges.PrivilegeCount = 1;
+ privileges.Privileges[0].Luid = luid;
+ if (enable)
+ privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ else
+ privileges.Privileges[0].Attributes = 0;
+
+ if (!AdjustTokenPrivileges(token, FALSE, &privileges,
+ sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) {
+ return false;
+ }
+ if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+ return false;
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Returns \c true if the specified \a privilege is enabled for the client
+ process, \c false otherwise.
+*/
+bool QInstaller::checkPrivilege(const wchar_t *privilege)
+{
+ LUID luid;
+ PRIVILEGE_SET privileges;
+ HANDLE token;
+ HANDLE process = GetCurrentProcess();
+
+ if (!OpenProcessToken(process, TOKEN_QUERY, &token))
+ return false;
+
+ if (!LookupPrivilegeValue(nullptr, privilege, &luid))
+ return false;
+
+ privileges.PrivilegeCount = 1;
+ privileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
+ privileges.Privilege[0].Luid = luid;
+ privileges.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ BOOL result;
+ PrivilegeCheck(token, &privileges, &result);
+
+ return result;
+}
+
+/*!
+ \internal
+
+ Returns \c true if the 'Developer mode' is enabled on system.
+*/
+bool QInstaller::developerModeEnabled()
+{
+ QSettingsWrapper appModelUnlock(QLatin1String("HKLM\\SOFTWARE\\Microsoft\\Windows\\"
+ "CurrentVersion\\AppModelUnlock"), QSettings::NativeFormat);
+
+ return appModelUnlock.value(QLatin1String("AllowDevelopmentWithoutDevLicense"), false).toBool();
+}
+
#endif
diff --git a/src/libs/installer/utils.h b/src/libs/installer/utils.h
index a22acd879..068490cc2 100644
--- a/src/libs/installer/utils.h
+++ b/src/libs/installer/utils.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -57,14 +57,19 @@ namespace QInstaller {
QString INSTALLER_EXPORT replaceWindowsEnvironmentVariables(const QString &str);
QStringList INSTALLER_EXPORT parseCommandLineArgs(int argc, char **argv);
+ bool INSTALLER_EXPORT canCreateSymbolicLinks();
+
#ifdef Q_OS_WIN
QString windowsErrorString(int errorCode);
QString createCommandline(const QString &program, const QStringList &arguments);
+ bool setPrivilege(const wchar_t *privilege, bool enable);
+ bool checkPrivilege(const wchar_t *privilege);
+ bool developerModeEnabled();
#endif
QStringList INSTALLER_EXPORT localeCandidates(const QString &locale);
- QStringList INSTALLER_EXPORT checkMutualOptions(CommandLineParser &parser, const QStringList &options);
+ QStringList INSTALLER_EXPORT checkMutualOptions(const CommandLineParser &parser, const QStringList &options);
INSTALLER_EXPORT std::ostream& operator<<(std::ostream &os, const QString &string);
}
diff --git a/src/libs/kdtools/filedownloader.cpp b/src/libs/kdtools/filedownloader.cpp
index 2510dc4c8..4d4002b7a 100644
--- a/src/libs/kdtools/filedownloader.cpp
+++ b/src/libs/kdtools/filedownloader.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -657,14 +658,6 @@ void KDUpdater::FileDownloader::addCheckSumData(const QByteArray &data)
}
/*!
- Adds the \a length of characters of \a data to the cryptographic hash of the downloaded file.
-*/
-void KDUpdater::FileDownloader::addCheckSumData(const char *data, int length)
-{
- d->m_hash.addData(data, length);
-}
-
-/*!
Resets SHA-1 checksum data of the downloaded file.
*/
void KDUpdater::FileDownloader::resetCheckSumData()
@@ -920,7 +913,7 @@ void KDUpdater::LocalFileDownloader::timerEvent(QTimerEvent *event)
toWrite -= numWritten;
}
addSample(numRead);
- addCheckSumData(buffer.data(), numRead);
+ addCheckSumData(buffer.left(numRead));
if (numRead > 0) {
setProgress(d->source->pos(), d->source->size());
emit downloadProgress(calcProgress(d->source->pos(), d->source->size()));
@@ -1112,7 +1105,7 @@ void KDUpdater::ResourceFileDownloader::timerEvent(QTimerEvent *event)
const qint64 numRead = d->destFile.read(buffer.data(), buffer.size());
addSample(numRead);
- addCheckSumData(buffer.data(), numRead);
+ addCheckSumData(buffer.left(numRead));
if (numRead > 0) {
setProgress(d->destFile.pos(), d->destFile.size());
@@ -1191,9 +1184,8 @@ struct KDUpdater::HttpDownloader::Private
disconnect(http, &QNetworkReply::finished, q, &HttpDownloader::httpReqFinished);
disconnect(http, &QNetworkReply::downloadProgress,
q, &HttpDownloader::httpReadProgress);
- void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error;
- disconnect(http, errorSignal, q, &HttpDownloader::httpError);
+ disconnect(http, &QNetworkReply::errorOccurred, q, &HttpDownloader::httpError);
http->deleteLater();
}
http = 0;
@@ -1219,8 +1211,14 @@ KDUpdater::HttpDownloader::HttpDownloader(QObject *parent)
#endif
connect(&d->manager, &QNetworkAccessManager::authenticationRequired,
this, &HttpDownloader::onAuthenticationRequired);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
connect(&d->manager, &QNetworkAccessManager::networkAccessibleChanged,
this, &HttpDownloader::onNetworkAccessibleChanged);
+#else
+ auto netInfo = QNetworkInformation::instance();
+ connect(netInfo, &QNetworkInformation::reachabilityChanged,
+ this, &HttpDownloader::onReachabilityChanged);
+#endif
}
@@ -1313,7 +1311,7 @@ void KDUpdater::HttpDownloader::httpReadyRead()
written += numWritten;
}
addSample(written);
- addCheckSumData(buffer.data(), read);
+ addCheckSumData(buffer.left(read));
updateBytesDownloadedBeforeResume(written);
}
}
@@ -1475,29 +1473,47 @@ void KDUpdater::HttpDownloader::startDownload(const QUrl &url)
d->m_authenticationCount = 0;
d->manager.setProxyFactory(proxyFactory());
clearBytesDownloadedBeforeResume();
- d->http = d->manager.get(QNetworkRequest(url));
+
+ QNetworkRequest request(url);
+ request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
+ request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
+
+ d->http = d->manager.get(request);
connect(d->http, &QIODevice::readyRead, this, &HttpDownloader::httpReadyRead);
connect(d->http, &QNetworkReply::downloadProgress,
this, &HttpDownloader::httpReadProgress);
connect(d->http, &QNetworkReply::finished, this, &HttpDownloader::httpReqFinished);
- void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error;
- connect(d->http, errorSignal, this, &HttpDownloader::httpError);
+ connect(d->http, &QNetworkReply::errorOccurred, this, &HttpDownloader::httpError);
+ bool fileOpened = false;
if (d->destFileName.isEmpty()) {
QTemporaryFile *file = new QTemporaryFile(this);
- file->open();
+ fileOpened = file->open();
d->destination = file;
} else {
d->destination = new QFile(d->destFileName, this);
- d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate);
+ fileOpened = d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate);
}
-
- if (!d->destination->isOpen()) {
- const QString error = d->destination->errorString();
- const QString fileName = d->destination->fileName();
- d->shutDown();
- setDownloadAborted(tr("Cannot download %1. Cannot create file \"%2\": %3").arg(
- url.toString(), fileName, error));
+ if (!fileOpened) {
+ qCWarning(QInstaller::lcInstallerInstallLog).nospace() << "Failed to open file " << d->destFileName
+ << ": "<<d->destination->errorString() << ". Trying again.";
+ QFileInfo fileInfo;
+ fileInfo.setFile(d->destination->fileName());
+ if (!QDir().mkpath(fileInfo.absolutePath())) {
+ setDownloadAborted(tr("Cannot download %1. Cannot create directory for \"%2\"").arg(
+ url.toString(), fileInfo.filePath()));
+ } else {
+ fileOpened = d->destination->open(QIODevice::ReadWrite | QIODevice::Truncate);
+ if (fileOpened)
+ return;
+ if (d->destination->exists())
+ qCWarning(QInstaller::lcInstallerInstallLog) << "File exists but installer is unable to open it.";
+ else
+ qCWarning(QInstaller::lcInstallerInstallLog) << "File does not exist.";
+ setDownloadAborted(tr("Cannot download %1. Cannot create file \"%2\": %3").arg(
+ url.toString(), d->destination->fileName(), d->destination->errorString()));
+ d->shutDown();
+ }
}
}
@@ -1517,8 +1533,7 @@ void KDUpdater::HttpDownloader::resumeDownload()
connect(d->http, &QNetworkReply::downloadProgress,
this, &HttpDownloader::httpReadProgress);
connect(d->http, &QNetworkReply::finished, this, &HttpDownloader::httpReqFinished);
- void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error;
- connect(d->http, errorSignal, this, &HttpDownloader::httpError);
+ connect(d->http, &QNetworkReply::errorOccurred, this, &HttpDownloader::httpError);
runDownloadSpeedTimer();
runDownloadDeadlineTimer();
}
@@ -1560,6 +1575,7 @@ void KDUpdater::HttpDownloader::onAuthenticationRequired(QNetworkReply *reply, Q
}
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void KDUpdater::HttpDownloader::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible)
{
if (accessible == QNetworkAccessManager::NotAccessible) {
@@ -1574,6 +1590,22 @@ void KDUpdater::HttpDownloader::onNetworkAccessibleChanged(QNetworkAccessManager
}
}
}
+#else
+void KDUpdater::HttpDownloader::onReachabilityChanged(QNetworkInformation::Reachability newReachability)
+{
+ if (newReachability == QNetworkInformation::Reachability::Online) {
+ if (isDownloadPaused()) {
+ setDownloadPaused(false);
+ resumeDownload();
+ }
+ } else {
+ d->shutDown(false);
+ setDownloadPaused(true);
+ setDownloadResumed(false);
+ stopDownloadDeadlineTimer();
+ }
+}
+#endif
#ifndef QT_NO_SSL
@@ -1611,7 +1643,7 @@ void KDUpdater::HttpDownloader::onSslErrors(QNetworkReply* reply, const QList<QS
"the error may be temporary and you can try again.")));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
- msgBox.setButtonText(QMessageBox::Yes, tr("Try again"));
+ msgBox.addButton(tr("Try again"), QMessageBox::YesRole);
msgBox.setDefaultButton(QMessageBox::Cancel);
if (msgBox.exec() == QMessageBox::Cancel) {
diff --git a/src/libs/kdtools/filedownloader.h b/src/libs/kdtools/filedownloader.h
index f02a4cc85..e71f7d62f 100644
--- a/src/libs/kdtools/filedownloader.h
+++ b/src/libs/kdtools/filedownloader.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -58,6 +59,8 @@ public:
QByteArray assumedSha1Sum() const;
void setAssumedSha1Sum(const QByteArray &sha1);
+ void setCheckSha1Sum(const bool checkSha1Sum);
+ bool checkSha1Sum() const;
QString scheme() const;
void setScheme(const QString &scheme);
@@ -140,7 +143,6 @@ protected:
void emitEstimatedDownloadTime();
void addCheckSumData(const QByteArray &data);
- void addCheckSumData(const char *data, int length);
void resetCheckSumData();
private Q_SLOTS:
diff --git a/src/libs/kdtools/filedownloader_p.h b/src/libs/kdtools/filedownloader_p.h
index 41a430554..23eff08d7 100644
--- a/src/libs/kdtools/filedownloader_p.h
+++ b/src/libs/kdtools/filedownloader_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -34,6 +35,10 @@
#include <QtNetwork/QNetworkReply>
#include <QNetworkAccessManager>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QNetworkInformation>
+#endif
+
// these classes are not a part of the public API
namespace KDUpdater {
@@ -46,22 +51,22 @@ public:
explicit LocalFileDownloader(QObject *parent = 0);
~LocalFileDownloader();
- bool canDownload() const;
- bool isDownloaded() const;
- QString downloadedFileName() const;
- void setDownloadedFileName(const QString &name);
- LocalFileDownloader *clone(QObject *parent = 0) const;
+ bool canDownload() const override;
+ bool isDownloaded() const override;
+ QString downloadedFileName() const override;
+ void setDownloadedFileName(const QString &name) override;
+ LocalFileDownloader *clone(QObject *parent = 0) const override;
public Q_SLOTS:
- void cancelDownload();
+ void cancelDownload() override;
protected:
- void timerEvent(QTimerEvent *te);
- void onError();
- void onSuccess();
+ void timerEvent(QTimerEvent *te) override;
+ void onError() override;
+ void onSuccess() override;
private Q_SLOTS:
- void doDownload();
+ void doDownload() override;
private:
struct Private;
@@ -76,22 +81,22 @@ public:
explicit ResourceFileDownloader(QObject *parent = 0);
~ResourceFileDownloader();
- bool canDownload() const;
- bool isDownloaded() const;
- QString downloadedFileName() const;
- void setDownloadedFileName(const QString &name);
- ResourceFileDownloader *clone(QObject *parent = 0) const;
+ bool canDownload() const override;
+ bool isDownloaded() const override;
+ QString downloadedFileName() const override;
+ void setDownloadedFileName(const QString &name) override;
+ ResourceFileDownloader *clone(QObject *parent = 0) const override;
public Q_SLOTS:
- void cancelDownload();
+ void cancelDownload() override;
protected:
- void timerEvent(QTimerEvent *te);
- void onError();
- void onSuccess();
+ void timerEvent(QTimerEvent *te) override;
+ void onError() override;
+ void onSuccess() override;
private Q_SLOTS:
- void doDownload();
+ void doDownload() override;
private:
struct Private;
@@ -106,22 +111,22 @@ public:
explicit HttpDownloader(QObject *parent = 0);
~HttpDownloader();
- bool canDownload() const;
- bool isDownloaded() const;
- QString downloadedFileName() const;
- void setDownloadedFileName(const QString &name);
- HttpDownloader *clone(QObject *parent = 0) const;
+ bool canDownload() const override;
+ bool isDownloaded() const override;
+ QString downloadedFileName() const override;
+ void setDownloadedFileName(const QString &name) override;
+ HttpDownloader *clone(QObject *parent = 0) const override;
public Q_SLOTS:
- void cancelDownload();
+ void cancelDownload() override;
protected:
- void onError();
- void onSuccess();
- void timerEvent(QTimerEvent *event);
+ void onError() override;
+ void onSuccess() override;
+ void timerEvent(QTimerEvent *event) override;
private Q_SLOTS:
- void doDownload();
+ void doDownload() override;
void httpReadyRead();
void httpReadProgress(qint64 done, qint64 total);
@@ -129,7 +134,11 @@ private Q_SLOTS:
void httpDone(bool error);
void httpReqFinished();
void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
+#else
+ void onReachabilityChanged(QNetworkInformation::Reachability newReachability);
+#endif
#ifndef QT_NO_SSL
void onSslErrors(QNetworkReply* reply, const QList<QSslError> &errors);
#endif
diff --git a/src/libs/kdtools/genericfactory.cpp b/src/libs/kdtools/genericfactory.cpp
index e45fb89ff..4d4fcac98 100644
--- a/src/libs/kdtools/genericfactory.cpp
+++ b/src/libs/kdtools/genericfactory.cpp
@@ -1,11 +1,11 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -128,6 +117,7 @@
/*!
\fn template <typename BASE, typename IDENTIFIER, typename... ARGUMENTS> BASE *GenericFactory<BASE, IDENTIFIER, ARGUMENTS...>::create(const IDENTIFIER &id, ARGUMENTS... args) const
- Creates and returns the type identified by \a id, but automatically upcasted to BASE. Ownership
- of the type is transferred to the caller.
+ Creates and returns the type identified by \a id with variable number of
+ arguments \a args passed to the object's constructor, but automatically
+ upcasted to BASE. Ownership of the type is transferred to the caller.
*/
diff --git a/src/libs/kdtools/genericfactory.h b/src/libs/kdtools/genericfactory.h
index 467f797d6..885271150 100644
--- a/src/libs/kdtools/genericfactory.h
+++ b/src/libs/kdtools/genericfactory.h
@@ -1,11 +1,11 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -14,24 +14,13 @@
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/libs/kdtools/kdsysinfo_win.cpp b/src/libs/kdtools/kdsysinfo_win.cpp
index 0aa7e7aa3..d423ef01e 100644
--- a/src/libs/kdtools/kdsysinfo_win.cpp
+++ b/src/libs/kdtools/kdsysinfo_win.cpp
@@ -66,9 +66,15 @@ QList<ProcessInfo> runningProcesses()
QStringList deviceList;
const DWORD bufferSize = 1024;
char buffer[bufferSize + 1] = { 0 };
- if (QSysInfo::windowsVersion() <= QSysInfo::WV_5_2) {
+
+ // Qt6 does not support Win before 10
+ bool winVerLessEqual5_2 = false;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ winVerLessEqual5_2 = QSysInfo::windowsVersion() <= QSysInfo::WV_5_2;
+#endif
+ if (winVerLessEqual5_2) {
const DWORD size = GetLogicalDriveStringsA(bufferSize, buffer);
- deviceList = QString::fromLatin1(buffer, size).split(QLatin1Char(char(0)), QString::SkipEmptyParts);
+ deviceList = QString::fromLatin1(buffer, size).split(QLatin1Char(char(0)), Qt::SkipEmptyParts);
}
QLibrary kernel32(QLatin1String("Kernel32.dll"));
@@ -85,7 +91,7 @@ QList<ProcessInfo> runningProcesses()
processStruct.dwSize = sizeof(PROCESSENTRY32);
bool foundProcess = Process32First(snapshot, &processStruct);
while (foundProcess) {
- HANDLE procHandle = OpenProcess(QSysInfo::windowsVersion() > QSysInfo::WV_5_2
+ HANDLE procHandle = OpenProcess(!winVerLessEqual5_2
? KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, false, processStruct
.th32ProcessID);
@@ -93,7 +99,7 @@ QList<ProcessInfo> runningProcesses()
QString executablePath;
DWORD bufferSize = 1024;
- if (QSysInfo::windowsVersion() > QSysInfo::WV_5_2) {
+ if (!winVerLessEqual5_2) {
succ = pQueryFullProcessImageNamePtr(procHandle, 0, buffer, &bufferSize);
executablePath = QString::fromLatin1(buffer);
} else if (pGetProcessImageFileNamePtr) {
diff --git a/src/libs/kdtools/localpackagehub.cpp b/src/libs/kdtools/localpackagehub.cpp
index 2ee880e04..c7b627c51 100644
--- a/src/libs/kdtools/localpackagehub.cpp
+++ b/src/libs/kdtools/localpackagehub.cpp
@@ -1,8 +1,8 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
@@ -124,6 +124,13 @@ bool LocalPackageHub::isValid() const
}
/*!
+ Returns a map of all local installed packages. Map key is the package name.
+*/
+QMap<QString, LocalPackage> LocalPackageHub::localPackages() const
+{
+ return d->m_packageInfoMap;
+}
+/*!
Returns a list of all local installed packages.
*/
QStringList LocalPackageHub::packageNames() const
@@ -306,6 +313,7 @@ void LocalPackageHub::refresh()
\a title,
\a treeName,
\a description,
+ \a sortingPriority,
\a dependencies,
\a autoDependencies,
\a forcedInstallation,
@@ -313,13 +321,15 @@ void LocalPackageHub::refresh()
\a uncompressedSize,
\a inheritVersionFrom,
\a checkable,
- and \a expandedByDefault for the package.
+ \a expandedByDefault,
+ and \a contentSha1 for the package.
*/
void LocalPackageHub::addPackage(const QString &name,
const QString &version,
const QString &title,
- const QString &treeName,
+ const QPair<QString, bool> &treeName,
const QString &description,
+ const int sortingPriority,
const QStringList &dependencies,
const QStringList &autoDependencies,
bool forcedInstallation,
@@ -344,6 +354,7 @@ void LocalPackageHub::addPackage(const QString &name,
info.title = title;
info.treeName = treeName;
info.description = description;
+ info.sortingPriority = sortingPriority;
info.dependencies = dependencies;
info.autoDependencies = autoDependencies;
info.forcedInstallation = forcedInstallation;
@@ -403,7 +414,9 @@ void LocalPackageHub::writeToDisk()
addTextChildHelper(&package, QLatin1String("Name"), info.name);
addTextChildHelper(&package, QLatin1String("Title"), info.title);
addTextChildHelper(&package, QLatin1String("Description"), info.description);
- addTextChildHelper(&package, scTreeName, info.treeName);
+ addTextChildHelper(&package, QLatin1String("SortingPriority"), QString::number(info.sortingPriority));
+ addTextChildHelper(&package, scTreeName, info.treeName.first, QLatin1String("moveChildren"),
+ QVariant(info.treeName.second).toString());
if (info.inheritVersionFrom.isEmpty())
addTextChildHelper(&package, QLatin1String("Version"), info.version);
else
@@ -476,9 +489,12 @@ void LocalPackageHub::PackagesInfoData::addPackageFrom(const QDomElement &packag
info.title = childNodeE.text();
else if (childNodeE.tagName() == QLatin1String("Description"))
info.description = childNodeE.text();
- else if (childNodeE.tagName() == scTreeName)
- info.treeName = childNodeE.text();
- else if (childNodeE.tagName() == QLatin1String("Version")) {
+ else if (childNodeE.tagName() == QLatin1String("SortingPriority"))
+ info.sortingPriority = childNodeE.text().toInt();
+ else if (childNodeE.tagName() == scTreeName) {
+ info.treeName.first = childNodeE.text();
+ info.treeName.second = QVariant(childNodeE.attribute(QLatin1String("moveChildren"))).toBool();
+ } else if (childNodeE.tagName() == QLatin1String("Version")) {
info.version = childNodeE.text();
info.inheritVersionFrom = childNodeE.attribute(QLatin1String("inheritVersionFrom"));
}
@@ -488,10 +504,10 @@ void LocalPackageHub::PackagesInfoData::addPackageFrom(const QDomElement &packag
info.uncompressedSize = childNodeE.text().toULongLong();
else if (childNodeE.tagName() == QLatin1String("Dependencies")) {
info.dependencies = childNodeE.text().split(QInstaller::commaRegExp(),
- QString::SkipEmptyParts);
+ Qt::SkipEmptyParts);
} else if (childNodeE.tagName() == QLatin1String("AutoDependOn")) {
info.autoDependencies = childNodeE.text().split(QInstaller::commaRegExp(),
- QString::SkipEmptyParts);
+ Qt::SkipEmptyParts);
} else if (childNodeE.tagName() == QLatin1String("ForcedInstallation"))
info.forcedInstallation = childNodeE.text().toLower() == QLatin1String( "true" ) ? true : false;
else if (childNodeE.tagName() == QLatin1String("LastUpdateDate"))
diff --git a/src/libs/kdtools/localpackagehub.h b/src/libs/kdtools/localpackagehub.h
index 648d6cf6e..5d69faf7d 100644
--- a/src/libs/kdtools/localpackagehub.h
+++ b/src/libs/kdtools/localpackagehub.h
@@ -1,8 +1,8 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
@@ -43,7 +43,8 @@ struct KDTOOLS_EXPORT LocalPackage
QString name;
QString title;
QString description;
- QString treeName;
+ int sortingPriority;
+ QPair<QString, bool> treeName;
QString version;
QString inheritVersionFrom;
QStringList dependencies;
@@ -77,6 +78,8 @@ public:
};
bool isValid() const;
+
+ QMap<QString, LocalPackage> localPackages() const;
QStringList packageNames() const;
Error error() const;
@@ -100,8 +103,9 @@ public:
void addPackage(const QString &pkgName,
const QString &version, // mandatory
const QString &title,
- const QString &treeName,
+ const QPair<QString, bool> &treeName,
const QString &description,
+ const int sortingPriority,
const QStringList &dependencies,
const QStringList &autoDependencies,
bool forcedInstallation,
diff --git a/src/libs/kdtools/lockfile_win.cpp b/src/libs/kdtools/lockfile_win.cpp
index 20961cc4e..7fc808d39 100644
--- a/src/libs/kdtools/lockfile_win.cpp
+++ b/src/libs/kdtools/lockfile_win.cpp
@@ -45,7 +45,7 @@ bool LockFile::Private::lock()
errorString.clear();
handle = CreateFile(filename.toStdWString().data(), GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ, NULL, QFileInfo(filename).exists() ? OPEN_EXISTING : CREATE_NEW,
+ FILE_SHARE_READ, NULL, QFileInfo::exists(filename) ? OPEN_EXISTING : CREATE_NEW,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL);
if (handle == INVALID_HANDLE_VALUE) {
diff --git a/src/libs/kdtools/sysinfo.cpp b/src/libs/kdtools/sysinfo.cpp
index df9a374f2..9512e59e3 100644
--- a/src/libs/kdtools/sysinfo.cpp
+++ b/src/libs/kdtools/sysinfo.cpp
@@ -71,7 +71,7 @@ VolumeInfo VolumeInfo::fromPath(const QString &path)
}
// the target directory does not exist yet, we need to cd up till we find the first existing dir
- QStringList parts = targetPath.absolutePath().split(QDir::separator(),QString::SkipEmptyParts);
+ QStringList parts = targetPath.absolutePath().split(QDir::separator(), Qt::SkipEmptyParts);
while (targetPath.absolutePath() != QDir::rootPath()) {
if (targetPath.exists())
break;
diff --git a/src/libs/kdtools/sysinfo_x11.cpp b/src/libs/kdtools/sysinfo_x11.cpp
index bc55939a6..24ef099ca 100644
--- a/src/libs/kdtools/sysinfo_x11.cpp
+++ b/src/libs/kdtools/sysinfo_x11.cpp
@@ -40,7 +40,7 @@
#include <QtCore/QTextStream>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
namespace KDUpdater {
@@ -60,7 +60,7 @@ quint64 installedMemory()
else if (s.isEmpty())
return quint64();
- const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const QStringList parts = s.split(QLatin1Char(' '), Qt::SkipEmptyParts);
return quint64(parts.at(1).toInt() * 1024LL);
}
#else
@@ -99,7 +99,7 @@ QList<VolumeInfo> mountedVolumes()
if (!s.startsWith(QLatin1Char('/')) && !s.startsWith(QLatin1String("tmpfs ") + QDir::tempPath()))
continue;
- const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const QStringList parts = s.split(QLatin1Char(' '), Qt::SkipEmptyParts);
VolumeInfo v;
v.setMountPath(parts.at(1));
@@ -124,9 +124,9 @@ QList<ProcessInfo> runningProcesses()
QList<ProcessInfo> processes;
QDir procDir(QLatin1String("/proc"));
const QFileInfoList procCont = procDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable);
- QRegExp validator(QLatin1String("[0-9]+"));
- Q_FOREACH (const QFileInfo &info, procCont) {
- if (validator.exactMatch(info.fileName())) {
+ static const QRegularExpression validator(QLatin1String("^[0-9]+$"));
+ for (const QFileInfo &info : procCont) {
+ if (validator.match(info.fileName()).hasMatch()) {
const QString linkPath = QDir(info.absoluteFilePath()).absoluteFilePath(QLatin1String("exe"));
const QFileInfo linkInfo(linkPath);
if (linkInfo.exists()) {
diff --git a/src/libs/kdtools/updatefinder.cpp b/src/libs/kdtools/updatefinder.cpp
index 5bf33d4a4..dbe7825df 100644
--- a/src/libs/kdtools/updatefinder.cpp
+++ b/src/libs/kdtools/updatefinder.cpp
@@ -1,8 +1,8 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
@@ -39,7 +39,8 @@
#include <QCoreApplication>
#include <QFileInfo>
-#include <QRegExp>
+#include <QRegularExpression>
+#include <QFutureWatcher>
using namespace KDUpdater;
using namespace QInstaller;
@@ -55,72 +56,107 @@ using namespace QInstaller;
objects.
*/
-//
-// Private
-//
-class UpdateFinder::Private
+
+static int computeProgressPercentage(int min, int max, int percent)
{
-public:
- enum struct Resolution {
- AddPackage,
- KeepExisting,
- RemoveExisting
- };
-
- explicit Private(UpdateFinder *qq)
- : q(qq)
- , cancel(false)
- , downloadCompleteCount(0)
- , m_downloadsToComplete(0)
- {}
-
- ~Private()
- {
- clear();
- }
+ return min + qint64(max-min) * percent / 100;
+}
- struct Data {
- Data()
- : downloader(0) {}
- explicit Data(const PackageSource &i, FileDownloader *d = 0)
- : info(i), downloader(d) {}
+static int computePercent(int done, int total)
+{
+ return total ? done * Q_INT64_C(100) / total : 0 ;
+}
- PackageSource info;
- FileDownloader *downloader;
- };
- UpdateFinder *q;
- QHash<QString, Update *> updates;
+/*!
+ Constructs an update finder.
+*/
+UpdateFinder::UpdateFinder()
+ : Task(QLatin1String("UpdateFinder"), Stoppable)
+ , m_cancel(false)
+ , m_downloadCompleteCount(0)
+ , m_downloadsToComplete(0)
+ , m_updatesXmlTasks(0)
+ , m_updatesXmlTasksToComplete(0)
+{
+}
- // Temporary structure that notes down information about updates.
- bool cancel;
- int downloadCompleteCount;
- int m_downloadsToComplete;
- QHash<UpdatesInfo *, Data> m_updatesInfoList;
+/*!
+ Destructor
+*/
+UpdateFinder::~UpdateFinder()
+{
+ clear();
+}
- void clear();
- void computeUpdates();
- void cancelComputeUpdates();
- bool downloadUpdateXMLFiles();
- bool computeApplicableUpdates();
+/*!
+ Returns a list of KDUpdater::Update objects.
+*/
+QList<Update *> UpdateFinder::updates() const
+{
+ return m_updates.values();
+}
- QList<UpdateInfo> applicableUpdates(UpdatesInfo *updatesInfo);
- void createUpdateObjects(const PackageSource &source, const QList<UpdateInfo> &updateInfoList);
- Resolution checkPriorityAndVersion(const PackageSource &source, const QVariantHash &data) const;
- void slotDownloadDone();
+/*!
+ Sets the information about installed local packages \a hub.
+*/
+void UpdateFinder::setLocalPackageHub(std::weak_ptr<LocalPackageHub> hub)
+{
+ m_localPackageHub = std::move(hub);
+}
- QSet<PackageSource> packageSources;
- std::weak_ptr<LocalPackageHub> m_localPackageHub;
-};
+/*!
+ Sets the package \a sources information when searching for applicable packages.
+*/
+void UpdateFinder::setPackageSources(const QSet<PackageSource> &sources)
+{
+ m_packageSources = sources;
+}
+/*!
+ \internal
-static int computeProgressPercentage(int min, int max, int percent)
+ Implemented from KDUpdater::Task::doRun().
+*/
+void UpdateFinder::doRun()
{
- return min + qint64(max-min) * percent / 100;
+ computeUpdates();
}
-static int computePercent(int done, int total)
+/*!
+ \internal
+
+ Implemented from KDUpdater::Task::doStop().
+*/
+bool UpdateFinder::doStop()
{
- return total ? done * Q_INT64_C(100) / total : 0 ;
+ cancelComputeUpdates();
+
+ // Wait until the cancel has actually happened, and then return.
+ // Thinking of using QMutex for this. Frank/Till any suggestions?
+
+ return true;
+}
+
+/*!
+ \internal
+
+ Implemented from KDUpdater::Task::doStop().
+*/
+bool UpdateFinder::doPause()
+{
+ // Not a pausable task
+ return false;
+}
+
+/*!
+ \internal
+
+ Implemented from KDUpdater::Task::doStop().
+*/
+bool UpdateFinder::doResume()
+{
+ // Not a pausable task, hence it is not resumable as well
+ return false;
}
/*!
@@ -128,20 +164,22 @@ static int computePercent(int done, int total)
Releases all internal resources consumed while downloading and computing updates.
*/
-void UpdateFinder::Private::clear()
+void UpdateFinder::clear()
{
- qDeleteAll(updates);
- updates.clear();
+ qDeleteAll(m_updates);
+ m_updates.clear();
const QList<Data> values = m_updatesInfoList.values();
foreach (const Data &data, values)
delete data.downloader;
- qDeleteAll(m_updatesInfoList.keys());
+ qDeleteAll(m_updatesInfoList.keyBegin(), m_updatesInfoList.keyEnd());
m_updatesInfoList.clear();
- downloadCompleteCount = 0;
+ m_downloadCompleteCount = 0;
m_downloadsToComplete = 0;
+ qDeleteAll(m_xmlFileTasks);
+ m_xmlFileTasks.clear();
}
/*!
@@ -164,51 +202,59 @@ void UpdateFinder::Private::clear()
\note Each time this function is called, all the previously computed updates are discarded
and its resources are freed.
*/
-void UpdateFinder::Private::computeUpdates()
+void UpdateFinder::computeUpdates()
{
// Computing updates is done in two stages
// 1. Downloading Update XML files from all the update sources
- // 2. Matching updates with Package XML and figuring out available updates
-
+ // 2. Parse attributes from Update XML documents to UpdateInfoList
+ // 3. Remove all updates with invalid content
+ // 4. Matching updates with Package XML and figuring out available updates
clear();
- cancel = false;
+ m_cancel = false;
// First do some quick sanity checks on the packages info
std::shared_ptr<LocalPackageHub> packages = m_localPackageHub.lock();
if (!packages) {
- q->reportError(tr("Cannot access the package information of this application."));
+ reportError(tr("Cannot access the package information of this application."));
return;
}
if (!packages->isValid()) {
- q->reportError(packages->errorString());
+ reportError(packages->errorString());
return;
}
// Now do some quick sanity checks on the package sources.
- if (packageSources.count() <= 0) {
- q->reportError(tr("No package sources set for this application."));
+ if (m_packageSources.count() <= 0) {
+ reportError(tr("No package sources set for this application."));
return;
}
// Now we can start...
+ if (!downloadUpdateXMLFiles() || m_cancel) {
+ clear();
+ return;
+ }
- // Step 1: 0 - 49 percent
- if (!downloadUpdateXMLFiles() || cancel) {
+ if (!parseUpdateXMLFiles() || m_cancel) {
clear();
return;
}
- // Step 2: 50 - 100 percent
- if (!computeApplicableUpdates() || cancel) {
+ if (!removeInvalidObjects() || m_cancel) {
+ clear();
+ return;
+ }
+
+ if (!computeApplicableUpdates() || m_cancel) {
clear();
return;
}
// All done
- q->reportProgress(100, tr("%n update(s) found.", "", updates.count()));
- q->reportDone();
+ reportProgress(100, tr("%n update(s) found.", "", m_updates.count()));
+ reportDone();
}
/*!
@@ -218,9 +264,9 @@ void UpdateFinder::Private::computeUpdates()
\sa computeUpdates()
*/
-void UpdateFinder::Private::cancelComputeUpdates()
+void UpdateFinder::cancelComputeUpdates()
{
- cancel = true;
+ m_cancel = true;
}
/*!
@@ -239,32 +285,32 @@ void UpdateFinder::Private::cancelComputeUpdates()
The function gets into an event loop until all the downloads are complete.
*/
-bool UpdateFinder::Private::downloadUpdateXMLFiles()
+bool UpdateFinder::downloadUpdateXMLFiles()
{
// create UpdatesInfo for each update source
- foreach (const PackageSource &info, packageSources) {
+ foreach (const PackageSource &info, m_packageSources) {
const QUrl url = QString::fromLatin1("%1/Updates.xml").arg(info.url.toString());
if (url.scheme() != QLatin1String("resource") && url.scheme() != QLatin1String("file")) {
// create FileDownloader (except for local files and resources)
- FileDownloader *downloader = FileDownloaderFactory::instance().create(url.scheme(), q);
+ FileDownloader *downloader = FileDownloaderFactory::instance().create(url.scheme(), this);
if (!downloader)
break;
downloader->setUrl(url);
downloader->setAutoRemoveDownloadedFile(true);
- connect(downloader, SIGNAL(downloadCanceled()), q, SLOT(slotDownloadDone()));
- connect(downloader, SIGNAL(downloadCompleted()), q, SLOT(slotDownloadDone()));
- connect(downloader, SIGNAL(downloadAborted(QString)), q, SLOT(slotDownloadDone()));
- m_updatesInfoList.insert(new UpdatesInfo, Data(info, downloader));
+ connect(downloader, SIGNAL(downloadCanceled()), this, SLOT(slotDownloadDone()));
+ connect(downloader, SIGNAL(downloadCompleted()), this, SLOT(slotDownloadDone()));
+ connect(downloader, SIGNAL(downloadAborted(QString)), this, SLOT(slotDownloadDone()));
+ m_updatesInfoList.insert(new UpdatesInfo(info.postLoadComponentScript), Data(info, downloader));
} else {
- UpdatesInfo *updatesInfo = new UpdatesInfo;
+ UpdatesInfo *updatesInfo = new UpdatesInfo(info.postLoadComponentScript);
updatesInfo->setFileName(QInstaller::pathFromUrl(url));
m_updatesInfoList.insert(updatesInfo, Data(info));
}
}
// Trigger download of Updates.xml file
- downloadCompleteCount = 0;
+ m_downloadCompleteCount = 0;
m_downloadsToComplete = 0;
foreach (const Data &data, m_updatesInfoList) {
if (data.downloader) {
@@ -274,39 +320,53 @@ bool UpdateFinder::Private::downloadUpdateXMLFiles()
}
// Wait until all downloaders have completed their downloads.
- while (true) {
- QCoreApplication::processEvents();
- if (cancel)
- return false;
-
- if (downloadCompleteCount == m_downloadsToComplete)
- break;
-
- q->reportProgress(computePercent(downloadCompleteCount, m_downloadsToComplete),
- tr("Downloading Updates.xml from update sources."));
- }
+ return waitForJobToFinish(m_downloadCompleteCount, m_downloadsToComplete);
+}
+/*!
+ \internal
+*/
+bool UpdateFinder::parseUpdateXMLFiles()
+{
// Setup the update info objects with the files from download.
- foreach (UpdatesInfo *updatesInfo, m_updatesInfoList.keys()) {
+ m_updatesXmlTasks = 0;
+ m_updatesXmlTasksToComplete = 0;
+ QList<UpdatesInfo *> keys = m_updatesInfoList.keys();
+ for (UpdatesInfo *updatesInfo : qAsConst(keys)) {
const Data data = m_updatesInfoList.value(updatesInfo);
if (data.downloader) {
if (!data.downloader->isDownloaded()) {
- q->reportError(tr("Cannot download package source %1 from \"%2\".").arg(data
- .downloader->url().fileName(), data.info.url.toString()));
+ reportError(tr("Cannot download package source %1 from \"%2\".").arg(data.
+ downloader->url().fileName(), data.info.url.toString()));
} else {
updatesInfo->setFileName(data.downloader->downloadedFileName());
}
}
+ if (!updatesInfo->fileName().isEmpty()) {
+ ParseXmlFilesTask *const task = new ParseXmlFilesTask(updatesInfo);
+ m_xmlFileTasks.append(task);
+ QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
+ m_updatesXmlTasksToComplete++;
+ connect(watcher, &QFutureWatcherBase::finished, this, &UpdateFinder::parseUpdatesXmlTaskFinished);
+ watcher->setFuture(QtConcurrent::run(&ParseXmlFilesTask::doTask, task));
+ }
}
- // Remove all invalid update info objects.
+ // Wait until all updates.xml files are parsed
+ return waitForJobToFinish(m_updatesXmlTasks, m_updatesXmlTasksToComplete);
+}
+/*!
+ \internal
+*/
+bool UpdateFinder::removeInvalidObjects()
+{
QMutableHashIterator<UpdatesInfo *, Data> it(m_updatesInfoList);
while (it.hasNext()) {
UpdatesInfo *info = it.next().key();
if (info->isValid())
continue;
- q->reportError(info->errorString());
+ reportError(info->errorString());
delete info;
it.remove();
}
@@ -314,7 +374,7 @@ bool UpdateFinder::Private::downloadUpdateXMLFiles()
if (m_updatesInfoList.isEmpty())
return false;
- q->reportProgress(49, tr("Updates.xml file(s) downloaded from update sources."));
+ reportProgress(49, tr("Updates.xml file(s) downloaded from update sources."));
return true;
}
@@ -326,36 +386,40 @@ bool UpdateFinder::Private::downloadUpdateXMLFiles()
KDUpdater::PackagesInfo. Thereby figures out whether an update is applicable for
this application or not.
*/
-bool UpdateFinder::Private::computeApplicableUpdates()
+bool UpdateFinder::computeApplicableUpdates()
{
int i = 0;
- foreach (UpdatesInfo *updatesInfo, m_updatesInfoList.keys()) {
+ QList<UpdatesInfo *> keys = m_updatesInfoList.keys();
+ for (UpdatesInfo *updatesInfo : qAsConst(keys)) {
// Fetch updates applicable to this application.
QList<UpdateInfo> updates = applicableUpdates(updatesInfo);
if (!updates.count())
continue;
- if (cancel)
+ if (m_cancel)
return false;
const PackageSource updateSource = m_updatesInfoList.value(updatesInfo).info;
// Create Update objects for updates that have a valid
// UpdateFile
createUpdateObjects(updateSource, updates);
- if (cancel)
+ if (m_cancel)
return false;
// Report progress
- q->reportProgress(computeProgressPercentage(51, 100, computePercent(i,
+ reportProgress(computeProgressPercentage(51, 100, computePercent(i,
m_updatesInfoList.count())), tr("Computing applicable updates."));
++i;
}
- q->reportProgress(99, tr("Application updates computed."));
+ reportProgress(99, tr("Application updates computed."));
return true;
}
-QList<UpdateInfo> UpdateFinder::Private::applicableUpdates(UpdatesInfo *updatesInfo)
+/*!
+ \internal
+*/
+QList<UpdateInfo> UpdateFinder::applicableUpdates(UpdatesInfo *updatesInfo)
{
const QList<UpdateInfo> dummy;
if (!updatesInfo || updatesInfo->updateInfoCount() == 0)
@@ -375,7 +439,7 @@ QList<UpdateInfo> UpdateFinder::Private::applicableUpdates(UpdatesInfo *updatesI
// Catch hold of app names contained updatesInfo->applicationName()
// If the application appName isn't one of the app names, then the updates are not applicable.
- const QStringList apps = appName.split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
+ const QStringList apps = appName.split(QInstaller::commaRegExp(), Qt::SkipEmptyParts);
if (apps.indexOf([&packages] { return packages->isValid() ? packages->applicationName()
: QCoreApplication::applicationName(); } ()) < 0) {
return dummy;
@@ -384,7 +448,10 @@ QList<UpdateInfo> UpdateFinder::Private::applicableUpdates(UpdatesInfo *updatesI
return updatesInfo->updatesInfo();
}
-void UpdateFinder::Private::createUpdateObjects(const PackageSource &source,
+/*!
+ \internal
+*/
+void UpdateFinder::createUpdateObjects(const PackageSource &source,
const QList<UpdateInfo> &updateInfoList)
{
foreach (const UpdateInfo &info, updateInfoList) {
@@ -394,23 +461,24 @@ void UpdateFinder::Private::createUpdateObjects(const PackageSource &source,
const QString name = info.data.value(QLatin1String("Name")).toString();
if (value == Resolution::RemoveExisting)
- delete updates.take(name);
+ delete m_updates.take(name);
// Create and register the update
- updates.insert(name, new Update(source, info));
+ m_updates.insert(name, new Update(source, info));
}
}
-/*
+/*!
+ \internal
If a package of the same name exists, always use the one with the higher
version. If the new package has the same version but a higher
priority, use the new new package, otherwise keep the already existing package.
*/
-UpdateFinder::Private::Resolution UpdateFinder::Private::checkPriorityAndVersion(
+UpdateFinder::Resolution UpdateFinder::checkPriorityAndVersion(
const PackageSource &source, const QVariantHash &newPackage) const
{
const QString name = newPackage.value(QLatin1String("Name")).toString();
- if (Update *existingPackage = updates.value(name)) {
+ if (Update *existingPackage = m_updates.value(name)) {
// Bingo, package was previously found elsewhere.
const int match = compareVersion(newPackage.value(QLatin1String("Version")).toString(),
@@ -442,108 +510,51 @@ UpdateFinder::Private::Resolution UpdateFinder::Private::checkPriorityAndVersion
return Resolution::AddPackage;
}
-//
-// UpdateFinder
-//
-
-/*!
- Constructs an update finder.
-*/
-UpdateFinder::UpdateFinder()
- : Task(QLatin1String("UpdateFinder"), Stoppable),
- d(new Private(this))
-{
-}
-
-/*!
- Destructor
-*/
-UpdateFinder::~UpdateFinder()
-{
- delete d;
-}
-
-/*!
- Returns a list of KDUpdater::Update objects.
-*/
-QList<Update *> UpdateFinder::updates() const
-{
- return d->updates.values();
-}
-
-/*!
- Sets the information about installed local packages \a hub.
-*/
-void UpdateFinder::setLocalPackageHub(std::weak_ptr<LocalPackageHub> hub)
-{
- d->m_localPackageHub = std::move(hub);
-}
-
-/*!
- Sets the package \a sources information when searching for applicable packages.
-*/
-void UpdateFinder::setPackageSources(const QSet<PackageSource> &sources)
-{
- d->packageSources = sources;
-}
-
-/*!
- \internal
-
- Implemented from KDUpdater::Task::doRun().
-*/
-void UpdateFinder::doRun()
-{
- d->computeUpdates();
-}
-
/*!
\internal
-
- Implemented from KDUpdater::Task::doStop().
*/
-bool UpdateFinder::doStop()
+bool UpdateFinder::waitForJobToFinish(const int &currentCount, const int &totalsCount)
{
- d->cancelComputeUpdates();
+ while (true) {
+ QCoreApplication::processEvents();
+ if (m_cancel)
+ return false;
- // Wait until the cancel has actually happened, and then return.
- // Thinking of using QMutex for this. Frank/Till any suggestions?
+ if (currentCount == totalsCount)
+ break;
+ reportProgress(computePercent(currentCount, totalsCount),
+ tr("Downloading Updates.xml from update sources."));
+ }
return true;
}
-
/*!
\internal
-
- Implemented from KDUpdater::Task::doStop().
*/
-bool UpdateFinder::doPause()
+void UpdateFinder::parseUpdatesXmlTaskFinished()
{
- // Not a pausable task
- return false;
-}
+ ++m_updatesXmlTasks;
-/*!
- \internal
+ int pc = computePercent(m_updatesXmlTasks, m_updatesXmlTasksToComplete);
+ pc = computeProgressPercentage(0, 45, pc);
+ reportProgress( pc, tr("Downloading Updates.xml from update sources.") );
- Implemented from KDUpdater::Task::doStop().
-*/
-bool UpdateFinder::doResume()
-{
- // Not a pausable task, hence it is not resumable as well
- return false;
+ QFutureWatcher<void> *watcher = static_cast<QFutureWatcher<void> *>(sender());
+ watcher->waitForFinished();
+ watcher->deleteLater();
}
+
/*!
\internal
*/
-void UpdateFinder::Private::slotDownloadDone()
+void UpdateFinder::slotDownloadDone()
{
- ++downloadCompleteCount;
+ ++m_downloadCompleteCount;
- int pc = computePercent(downloadCompleteCount, m_downloadsToComplete);
+ int pc = computePercent(m_downloadCompleteCount, m_downloadsToComplete);
pc = computeProgressPercentage(0, 45, pc);
- q->reportProgress( pc, tr("Downloading Updates.xml from update sources.") );
+ reportProgress( pc, tr("Downloading Updates.xml from update sources.") );
}
@@ -589,8 +600,9 @@ int KDUpdater::compareVersion(const QString &v1, const QString &v2)
return 0;
// Split version components across ".", "-" or "_"
- QStringList v1_comps = v1.split(QRegExp(QLatin1String( "\\.|-|_")));
- QStringList v2_comps = v2.split(QRegExp(QLatin1String( "\\.|-|_")));
+ static const QRegularExpression regex(QLatin1String( "\\.|-|_"));
+ QStringList v1_comps = v1.split(regex);
+ QStringList v2_comps = v2.split(regex);
// Check each component of the version
int index = 0;
diff --git a/src/libs/kdtools/updatefinder.h b/src/libs/kdtools/updatefinder.h
index 7a3e4df1e..626a700fd 100644
--- a/src/libs/kdtools/updatefinder.h
+++ b/src/libs/kdtools/updatefinder.h
@@ -1,8 +1,8 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
@@ -32,19 +32,68 @@
#include "task.h"
#include "packagesource.h"
+#include "filedownloader.h"
+#include "updatesinfo_p.h"
+#include "abstracttask.h"
#include <memory>
+using namespace QInstaller;
namespace KDUpdater {
class LocalPackageHub;
class Update;
+class ParseXmlFilesTask : public AbstractTask<void>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ParseXmlFilesTask)
+
+public:
+ ParseXmlFilesTask(UpdatesInfo *info)
+ : m_info(info)
+ {}
+
+ void doTask(QFutureInterface<void> &fi) override
+ {
+ fi.reportStarted();
+ fi.setExpectedResultCount(1);
+
+ if (fi.isCanceled()) {
+ fi.reportFinished();
+ return; // ignore already canceled
+ }
+ m_info->parseFile();
+
+ fi.reportFinished();
+ }
+
+private:
+ UpdatesInfo *const m_info;
+};
+
+
class KDTOOLS_EXPORT UpdateFinder : public Task
{
Q_OBJECT
class Private;
+ struct Data {
+ Data()
+ : downloader(0) {}
+ explicit Data(const QInstaller::PackageSource &i, KDUpdater::FileDownloader *d = 0)
+ : info(i), downloader(d) {}
+
+ QInstaller::PackageSource info;
+ KDUpdater::FileDownloader *downloader;
+ };
+
+ enum struct Resolution {
+ AddPackage,
+ KeepExisting,
+ RemoveExisting
+ };
+
public:
UpdateFinder();
~UpdateFinder();
@@ -55,14 +104,39 @@ public:
void setPackageSources(const QSet<QInstaller::PackageSource> &sources);
private:
- void doRun();
- bool doStop();
- bool doPause();
- bool doResume();
+ void doRun() override;
+ bool doStop() override;
+ bool doPause() override;
+ bool doResume() override;
+ void clear();
+ void computeUpdates();
+ void cancelComputeUpdates();
+ bool downloadUpdateXMLFiles();
+ bool parseUpdateXMLFiles();
+ bool removeInvalidObjects();
+ bool computeApplicableUpdates();
+
+ QList<UpdateInfo> applicableUpdates(UpdatesInfo *updatesInfo);
+ void createUpdateObjects(const PackageSource &source, const QList<UpdateInfo> &updateInfoList);
+ Resolution checkPriorityAndVersion(const QInstaller::PackageSource &source, const QVariantHash &data) const;
+ bool waitForJobToFinish(const int &currentCount, const int &totalsCount);
+
+private slots:
+ void parseUpdatesXmlTaskFinished();
+ void slotDownloadDone();
private:
- Private *d;
- Q_PRIVATE_SLOT(d, void slotDownloadDone())
+ QSet<PackageSource> m_packageSources;
+ std::weak_ptr<LocalPackageHub> m_localPackageHub;
+ QHash<QString, Update *> m_updates;
+
+ bool m_cancel;
+ int m_downloadCompleteCount;
+ int m_downloadsToComplete;
+ QHash<UpdatesInfo *, Data> m_updatesInfoList;
+ int m_updatesXmlTasks;
+ int m_updatesXmlTasksToComplete;
+ QList<ParseXmlFilesTask*> m_xmlFileTasks;
};
} // namespace KDUpdater
diff --git a/src/libs/kdtools/updateoperation.cpp b/src/libs/kdtools/updateoperation.cpp
index 897fecf1b..af89382a8 100644
--- a/src/libs/kdtools/updateoperation.cpp
+++ b/src/libs/kdtools/updateoperation.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -80,6 +81,21 @@ using namespace KDUpdater;
Undo operation.
*/
+/*!
+ \enum UpdateOperation::OperationGroup
+ This enum specifies the execution group of the operation.
+
+ \value Unpack
+ Operation should be run in the unpacking phase. Operations in
+ this group are run concurrently between all selected components.
+ \value Install
+ Operation should be run in the installation phase.
+ \value All
+ All available operation groups.
+ \value Default
+ The default group for operations, synonym for Install.
+*/
+
/*
\internal
Returns a filename for a temporary file based on \a templateName.
@@ -99,10 +115,13 @@ static QString backupFileName(const QString &templateName)
\internal
*/
UpdateOperation::UpdateOperation(QInstaller::PackageManagerCore *core)
- : m_error(0)
+ : m_group(OperationGroup::Default)
+ , m_error(0)
, m_core(core)
, m_requiresUnreplacedVariables(false)
{
+ qRegisterMetaType<UpdateOperation *>();
+
// Store the value for compatibility reasons.
m_values[QLatin1String("installer")] = QVariant::fromValue(core);
}
@@ -139,6 +158,16 @@ QString UpdateOperation::operationCommand() const
}
/*!
+ Returns the execution group this operation belongs to.
+
+ \sa setGroup()
+*/
+UpdateOperation::OperationGroup UpdateOperation::group() const
+{
+ return m_group;
+}
+
+/*!
Returns \c true if a value called \a name exists, otherwise returns \c false.
*/
bool UpdateOperation::hasValue(const QString &name) const
@@ -180,6 +209,17 @@ void UpdateOperation::setName(const QString &name)
}
/*!
+ Sets the execution group of the operation to \a group. Subclasses can change
+ the group to control which installation phase this operation should be run in.
+
+ The default group is \c Install.
+*/
+void UpdateOperation::setGroup(const OperationGroup &group)
+{
+ m_group = group;
+}
+
+/*!
Sets the arguments for the update operation to \a args.
*/
void UpdateOperation::setArguments(const QStringList &args)
@@ -252,23 +292,18 @@ QStringList UpdateOperation::parsePerformOperationArguments()
}
/*!
- Returns undo operation argument list. If the installation is
- cancelled or failed, returns an empty list so that full undo
- operation can be performed.
+ Returns \c true if operation undo should not be performed.
+ Returns \c false if the installation is cancelled or failed, or
+ \c UNDOOPERATION is not set in operation call.
*/
-QStringList UpdateOperation::parseUndoOperationArguments()
+bool UpdateOperation::skipUndoOperation()
{
//Install has failed, allow a normal undo
if (m_core && (m_core->status() == QInstaller::PackageManagerCore::Canceled
|| m_core->status() == QInstaller::PackageManagerCore::Failure)) {
- return QStringList();
- }
- int index = arguments().indexOf(QLatin1String("UNDOOPERATION"));
- QStringList args;
- if ((index != -1) && (arguments().length() > index + 1)) {
- args = arguments().mid(index + 1);
+ return false;
}
- return args;
+ return arguments().contains(QLatin1String("UNDOOPERATION"));
}
/*!
@@ -281,6 +316,41 @@ void UpdateOperation::setRequiresUnreplacedVariables(bool isRequired)
m_requiresUnreplacedVariables = isRequired;
}
+/*!
+ Replaces installer \c value \a variableValue with predefined variable.
+ If \c key is found for the \a variableValue and the \c key ends with string _OLD,
+ the initial \a variableValue is replaced with the \c value having a key
+ without _OLD ending. This way we can replace the hard coded values defined for operations,
+ if the value has for some reason changed. For example if we set following variables
+ in install script:
+ \badcode
+ installer.setValue("MY_OWN_EXECUTABLE", "C:/Qt/NewLocation/Tools.exe")
+ installer.setValue("MY_OWN_EXECUTABLE_OLD", "C:/Qt/OldLocation/Tools.exe")
+ \endcode
+ and we have moved the Tools.exe from OldLocation to NewLocation, the operation
+ continues to work and use the Tools.exe from NewLocation although original
+ installation has been made with Tools.exe in OldLocation.
+ Returns \c true if \a variableValue is replaced.
+*/
+bool UpdateOperation::variableReplacement(QString *variableValue)
+{
+ bool variableValueChanged = false;
+ const QString valueNormalized = QDir::cleanPath(*variableValue);
+ QString key = m_core->key(valueNormalized);
+ if (key.endsWith(QLatin1String("_OLD"))) {
+ key.chop(4);
+ if (m_core->containsValue(key)) {
+ key.prepend(QLatin1String("@"));
+ key.append(QLatin1String("@"));
+ *variableValue = m_core->replaceVariables(key);
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Running above operation with replaced value: " << valueNormalized
+ << "has been replaced with" << *variableValue;
+ variableValueChanged = true;
+ }
+ }
+ return variableValueChanged;
+}
+
struct StartsWith
{
explicit StartsWith(const QString &searchTerm)
@@ -475,8 +545,15 @@ QDomDocument UpdateOperation::toXml() const
const QString target = m_core ? m_core->value(QInstaller::scTargetDir) : QString();
Q_FOREACH (const QString &s, arguments()) {
QDomElement arg = doc.createElement(QLatin1String("argument"));
- arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target,
- QLatin1String(QInstaller::scRelocatable))));
+ // Do not call cleanPath to Execute operations paths. The operation might require the
+ // exact separators that are set in the operation call.
+ if (name() == QLatin1String("Execute")) {
+ arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target,
+ QLatin1String(QInstaller::scRelocatable), false)));
+ } else {
+ arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target,
+ QLatin1String(QInstaller::scRelocatable))));
+ }
args.appendChild(arg);
}
root.appendChild(args);
@@ -495,14 +572,21 @@ QDomDocument UpdateOperation::toXml() const
value.setAttribute(QLatin1String("name"), it.key());
value.setAttribute(QLatin1String("type"), QLatin1String(variant.typeName()));
- if (variant.type() != QVariant::List && variant.type() != QVariant::StringList
- && variant.canConvert(QVariant::String)) {
- // it can convert to string? great!
- value.appendChild(doc.createTextNode(QInstaller::replacePath(variant.toString(),
- target, QLatin1String(QInstaller::scRelocatable))));
+ int variantType;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ variantType = variant.typeId();
+#else
+ variantType = variant.type();
+#endif
+
+ if (variantType != QMetaType::QStringList
+ && variant.canConvert<QString>()) {
+ // it can convert to string? great!
+ value.appendChild(doc.createTextNode(QInstaller::replacePath(variant.toString(),
+ target, QLatin1String(QInstaller::scRelocatable))));
} else {
// no? then we have to go the hard way...
- if (variant.type() == QVariant::StringList) {
+ if (variantType == QMetaType::QStringList) {
QStringList list = variant.toStringList();
for (int i = 0; i < list.count(); ++i) {
list[i] = QInstaller::replacePath(list.at(i), target,
@@ -528,6 +612,7 @@ QDomDocument UpdateOperation::toXml() const
bool UpdateOperation::fromXml(const QDomDocument &doc)
{
QString target = QCoreApplication::applicationDirPath();
+ static const QLatin1String relocatable = QLatin1String(QInstaller::scRelocatable);
// Does not change target on non macOS platforms.
if (QInstaller::isInBundle(target, &target))
target = QDir::cleanPath(target + QLatin1String("/.."));
@@ -539,8 +624,20 @@ bool UpdateOperation::fromXml(const QDomDocument &doc)
for (QDomNode n = argsElem.firstChild(); ! n.isNull(); n = n.nextSibling()) {
const QDomElement e = n.toElement();
if (!e.isNull() && e.tagName() == QLatin1String("argument")) {
- args << QInstaller::replacePath(e.text(), QLatin1String(QInstaller::scRelocatable),
- target);
+ // Sniff the Execute -operations file path separator. The operation might be
+ // strict with the used path separator
+ bool useCleanPath = true;
+ if (name() == QLatin1String("Execute")) {
+ if (e.text().startsWith(relocatable) && e.text().size() > relocatable.size()) {
+ const QChar separator = e.text().at(relocatable.size());
+ if (separator == QLatin1Char('\\')) {
+ target = QDir::toNativeSeparators(target);
+ useCleanPath = false;
+ }
+ }
+ }
+ args << QInstaller::replacePath(e.text(), relocatable,
+ target, useCleanPath);
}
}
setArguments(args);
@@ -556,25 +653,31 @@ bool UpdateOperation::fromXml(const QDomDocument &doc)
const QString type = v.attribute(QLatin1String("type"));
const QString value = v.text();
+ int variantType;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ const QMetaType t = QMetaType::fromName(type.toLatin1().data());
+ variantType = t.id();
+#else
const QVariant::Type t = QVariant::nameToType(type.toLatin1().data());
- QVariant var = qVariantFromValue(value);
- if (t == QVariant::List || t == QVariant::StringList || !var.convert(t)) {
- QDataStream stream(QByteArray::fromBase64( value.toLatin1()));
+ variantType = t;
+#endif
+ QVariant var = QVariant::fromValue(value);
+ if (variantType == QMetaType::QStringList || !var.canConvert(t)) {
+ QDataStream stream(QByteArray::fromBase64(value.toLatin1()));
stream >> var;
- if (t == QVariant::StringList) {
+ if (variantType == QMetaType::QStringList) {
QStringList list = var.toStringList();
for (int i = 0; i < list.count(); ++i) {
list[i] = QInstaller::replacePath(list.at(i),
- QLatin1String(QInstaller::scRelocatable), target);
+ relocatable, target);
}
var = QVariant::fromValue(list);
}
- } else if (t == QVariant::String) {
- const QString str = QInstaller::replacePath(value,
- QLatin1String(QInstaller::scRelocatable), target);
- var = QVariant::fromValue(str);
+ } else if (variantType == QMetaType::QString) {
+ const QString str = QInstaller::replacePath(value,
+ relocatable, target);
+ var = QVariant::fromValue(str);
}
-
m_values[name] = var;
}
@@ -582,6 +685,18 @@ bool UpdateOperation::fromXml(const QDomDocument &doc)
}
/*!
+ Returns a numerical representation of how this operation compares to
+ other operations in size, and in time it takes to perform the operation.
+
+ The default returned value is \c 1. Subclasses may override this method to
+ implement custom size hints.
+*/
+quint64 UpdateOperation::sizeHint()
+{
+ return 1;
+}
+
+/*!
\overload
Restores operation arguments and values from the XML file at path \a xml. Returns \c true on
diff --git a/src/libs/kdtools/updateoperation.h b/src/libs/kdtools/updateoperation.h
index a8110791c..e25846cd3 100644
--- a/src/libs/kdtools/updateoperation.h
+++ b/src/libs/kdtools/updateoperation.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -59,11 +60,20 @@ public:
Undo
};
+ enum OperationGroup {
+ Unpack = 0x1,
+ Install = 0x2,
+ All = (Unpack | Install),
+ Default = Install
+ };
+ Q_DECLARE_FLAGS(OperationGroups, OperationGroup)
+
explicit UpdateOperation(QInstaller::PackageManagerCore *core);
virtual ~UpdateOperation();
QString name() const;
QString operationCommand() const;
+ OperationGroup group() const;
bool hasValue(const QString &name) const;
void clearValue(const QString &name);
@@ -90,8 +100,11 @@ public:
virtual bool fromXml(const QString &xml);
virtual bool fromXml(const QDomDocument &doc);
+ virtual quint64 sizeHint();
+
protected:
void setName(const QString &name);
+ void setGroup(const OperationGroup &group);
void setErrorString(const QString &errorString);
void setError(int error, const QString &errorString = QString());
void registerForDelayedDeletion(const QStringList &files);
@@ -99,11 +112,13 @@ protected:
bool checkArgumentCount(int minArgCount, int maxArgCount, const QString &argDescription = QString());
bool checkArgumentCount(int argCount);
QStringList parsePerformOperationArguments();
- QStringList parseUndoOperationArguments();
+ bool skipUndoOperation();
void setRequiresUnreplacedVariables(bool isRequired);
+ bool variableReplacement(QString *variableValue);
private:
QString m_name;
+ OperationGroup m_group;
QStringList m_arguments;
QString m_errorString;
int m_error;
@@ -115,4 +130,6 @@ private:
} // namespace KDUpdater
+Q_DECLARE_METATYPE(KDUpdater::UpdateOperation *)
+
#endif // UPDATEOPERATION_H
diff --git a/src/libs/kdtools/updateoperations.cpp b/src/libs/kdtools/updateoperations.cpp
index 9301d4f13..5f6135103 100644
--- a/src/libs/kdtools/updateoperations.cpp
+++ b/src/libs/kdtools/updateoperations.cpp
@@ -127,7 +127,7 @@ QString CopyOperation::sourcePath()
QString CopyOperation::destinationPath()
{
- QString destination = arguments().last();
+ QString destination = arguments().at(1);
// if the target is a directory use the source filename to complete the destination path
if (QFileInfo(destination).isDir())
@@ -135,7 +135,6 @@ QString CopyOperation::destinationPath()
return destination;
}
-
void CopyOperation::backup()
{
QString destination = destinationPath();
@@ -156,8 +155,8 @@ void CopyOperation::backup()
bool CopyOperation::performOperation()
{
// We need two args to complete the copy operation. First arg provides the complete file name of source
- // Second arg provides the complete file name of dest
- if (!checkArgumentCount(2))
+ // Second arg provides the complete file name of dest. Optionally UNDOOPERATION can be added as well
+ if (!checkArgumentCount(2, 4, QLatin1String("<source filename> <destination filename> [UNDOOPERATION, \"\"]")))
return false;
QString source = sourcePath();
@@ -193,6 +192,8 @@ bool CopyOperation::performOperation()
bool CopyOperation::undoOperation()
{
+ if (skipUndoOperation())
+ return true;
QString source = sourcePath();
QString destination = destinationPath();
@@ -270,7 +271,7 @@ MoveOperation::~MoveOperation()
void MoveOperation::backup()
{
- const QString dest = arguments().last();
+ const QString dest = arguments().at(1);
if (!QFile::exists(dest)) {
clearValue(QLatin1String("backupOfExistingDestination"));
return;
@@ -286,9 +287,10 @@ void MoveOperation::backup()
bool MoveOperation::performOperation()
{
- // We need two args to complete the copy operation. // First arg provides the complete file name of
- // source, second arg provides the complete file name of dest
- if (!checkArgumentCount(2))
+ // We need two args to complete the copy operation. First arg provides the complete file name of
+ // source, second arg provides the complete file name of dest. Optionally UNDOOPERATION can be added as well
+ if (!checkArgumentCount(2, 4, QLatin1String("<complete source file name> <complete destination "
+ "file name> [UNDOOPERATION, \"\"]")))
return false;
const QStringList args = arguments();
@@ -318,8 +320,10 @@ bool MoveOperation::performOperation()
bool MoveOperation::undoOperation()
{
+ if (skipUndoOperation())
+ return true;
const QStringList args = arguments();
- const QString dest = args.last();
+ const QString dest = args.at(1);
// first: copy back the destination to source
QFile destF(dest);
if (!destF.copy(args.first())) {
@@ -391,7 +395,8 @@ void DeleteOperation::backup()
bool DeleteOperation::performOperation()
{
// Requires only one parameter. That is the name of the file to remove.
- if (!checkArgumentCount(1))
+ // Optionally UNDOOPERATION can be added as well
+ if (!checkArgumentCount(1, 3, QLatin1String("<file to remove> [UNDOOPERATION, \"\"]")))
return false;
return deleteFileNowOrLater(arguments().at(0));
@@ -399,7 +404,7 @@ bool DeleteOperation::performOperation()
bool DeleteOperation::undoOperation()
{
- if (!hasValue(QLatin1String("backupOfExistingFile")))
+ if (skipUndoOperation())
return true;
const QString fileName = arguments().first();
@@ -478,7 +483,8 @@ void MkdirOperation::backup()
bool MkdirOperation::performOperation()
{
// Requires only one parameter. That is the path which should be created
- if (!checkArgumentCount(1))
+ // Optionally UNDOOPERATION can be added as well
+ if (!checkArgumentCount(1, 3, QLatin1String("<file to remove> [UNDOOPERATION, \"\"]")))
return false;
const QString dirName = arguments().at(0);
@@ -493,7 +499,8 @@ bool MkdirOperation::performOperation()
bool MkdirOperation::undoOperation()
{
- Q_ASSERT(arguments().count() == 1);
+ if (skipUndoOperation())
+ return true;
QString createdDirValue = value(QLatin1String("createddir")).toString();
if (packageManager()) {
@@ -572,7 +579,8 @@ void RmdirOperation::backup()
bool RmdirOperation::performOperation()
{
// Requires only one parameter. That is the name of the file to remove.
- if (!checkArgumentCount(1))
+ // Optionally UNDOOPERATION can be added as well
+ if (!checkArgumentCount(1, 3, QLatin1String("<file to remove> [UNDOOPERATION, \"\"]")))
return false;
const QString firstArg = arguments().at(0);
@@ -597,7 +605,7 @@ bool RmdirOperation::performOperation()
bool RmdirOperation::undoOperation()
{
- if (!value(QLatin1String("removed")).toBool())
+ if (!value(QLatin1String("removed")).toBool() || skipUndoOperation())
return true;
errno = 0;
@@ -633,6 +641,12 @@ AppendFileOperation::AppendFileOperation(QInstaller::PackageManagerCore *core)
setName(QLatin1String("AppendFile"));
}
+AppendFileOperation::~AppendFileOperation()
+{
+ if (skipUndoOperation())
+ deleteFileNowOrLater(value(QLatin1String("backupOfFile")).toString());
+}
+
void AppendFileOperation::backup()
{
const QString filename = arguments().first();
@@ -653,10 +667,10 @@ bool AppendFileOperation::performOperation()
{
// This operation takes two arguments. First argument is the name of the file into which a text has to be
// appended. Second argument is the text to append.
- if (!checkArgumentCount(2))
+ if (!checkArgumentCount(2, 4, QLatin1String("<filename> <text to apply> [UNDOOPERATION, \"\"]")))
return false;
- const QStringList args = this->arguments();
+ const QStringList args = arguments();
const QString fName = args.at(0);
QFile file(fName);
if (!file.open(QFile::Append)) {
@@ -695,6 +709,9 @@ bool AppendFileOperation::performOperation()
bool AppendFileOperation::undoOperation()
{
+ if (skipUndoOperation())
+ return true;
+
// backupOfFile being empty -> file didn't exist before -> no error
const QString filename = arguments().first();
const QString backupOfFile = value(QLatin1String("backupOfFile")).toString();
@@ -746,6 +763,12 @@ PrependFileOperation::PrependFileOperation(QInstaller::PackageManagerCore *core)
setName(QLatin1String("PrependFile"));
}
+PrependFileOperation::~PrependFileOperation()
+{
+ if (skipUndoOperation())
+ deleteFileNowOrLater(value(QLatin1String("backupOfFile")).toString());
+}
+
void PrependFileOperation::backup()
{
const QString filename = arguments().first();
@@ -767,10 +790,10 @@ bool PrependFileOperation::performOperation()
// This operation takes two arguments. First argument is the name
// of the file into which a text has to be appended. Second argument
// is the text to append.
- if (!checkArgumentCount(2))
+ if (!checkArgumentCount(2, 4, QLatin1String("<filename> <text to prepend> [UNDOOPERATION, \"\"]")))
return false;
- const QStringList args = this->arguments();
+ const QStringList args = arguments();
const QString fName = args.at(0);
// Load the file first.
QFile file(fName);
@@ -810,7 +833,9 @@ bool PrependFileOperation::performOperation()
bool PrependFileOperation::undoOperation()
{
- // bockupOfFile being empty -> file didn't exist before -> no error
+ if (skipUndoOperation())
+ return true;
+
const QString filename = arguments().first();
const QString backupOfFile = value(QLatin1String("backupOfFile")).toString();
if (!backupOfFile.isEmpty() && !QFile::exists(backupOfFile)) {
diff --git a/src/libs/kdtools/updateoperations.h b/src/libs/kdtools/updateoperations.h
index b13a42559..adbfc7de1 100644
--- a/src/libs/kdtools/updateoperations.h
+++ b/src/libs/kdtools/updateoperations.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -40,12 +41,12 @@ public:
explicit CopyOperation(QInstaller::PackageManagerCore *core = 0);
~CopyOperation();
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
- QDomDocument toXml() const;
+ QDomDocument toXml() const override;
private:
QString sourcePath();
QString destinationPath();
@@ -58,10 +59,10 @@ public:
explicit MoveOperation(QInstaller::PackageManagerCore *core = 0);
~MoveOperation();
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
class KDTOOLS_EXPORT DeleteOperation : public UpdateOperation
@@ -71,12 +72,12 @@ public:
explicit DeleteOperation(QInstaller::PackageManagerCore *core = 0);
~DeleteOperation();
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
- QDomDocument toXml() const;
+ QDomDocument toXml() const override;
};
class KDTOOLS_EXPORT MkdirOperation : public UpdateOperation
@@ -85,10 +86,10 @@ class KDTOOLS_EXPORT MkdirOperation : public UpdateOperation
public:
explicit MkdirOperation(QInstaller::PackageManagerCore *core = 0);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
class KDTOOLS_EXPORT RmdirOperation : public UpdateOperation
@@ -97,10 +98,10 @@ class KDTOOLS_EXPORT RmdirOperation : public UpdateOperation
public:
RmdirOperation(QInstaller::PackageManagerCore *core = 0);
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
class KDTOOLS_EXPORT AppendFileOperation : public UpdateOperation
@@ -108,11 +109,12 @@ class KDTOOLS_EXPORT AppendFileOperation : public UpdateOperation
Q_DECLARE_TR_FUNCTIONS(KDUpdater::AppendFileOperation)
public:
explicit AppendFileOperation(QInstaller::PackageManagerCore *core = 0);
+ ~AppendFileOperation();
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
class KDTOOLS_EXPORT PrependFileOperation : public UpdateOperation
@@ -120,11 +122,12 @@ class KDTOOLS_EXPORT PrependFileOperation : public UpdateOperation
Q_DECLARE_TR_FUNCTIONS(KDUpdater::PrependFileOperation)
public:
explicit PrependFileOperation(QInstaller::PackageManagerCore *core = 0);
+ ~PrependFileOperation();
- void backup();
- bool performOperation();
- bool undoOperation();
- bool testOperation();
+ void backup() override;
+ bool performOperation() override;
+ bool undoOperation() override;
+ bool testOperation() override;
};
} // namespace KDUpdater
diff --git a/src/libs/kdtools/updatesinfo.cpp b/src/libs/kdtools/updatesinfo.cpp
index eaa9b039e..e82c1c1fb 100644
--- a/src/libs/kdtools/updatesinfo.cpp
+++ b/src/libs/kdtools/updatesinfo.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -28,18 +29,20 @@
#include "updatesinfo_p.h"
#include "utils.h"
+#include "constants.h"
-#include <QDomDocument>
#include <QFile>
#include <QLocale>
#include <QPair>
#include <QVector>
#include <QUrl>
+#include <QXmlStreamReader>
using namespace KDUpdater;
-UpdatesInfoData::UpdatesInfoData()
+UpdatesInfoData::UpdatesInfoData(const bool postLoadComponentScript)
: error(UpdatesInfo::NotYetReadError)
+ , m_postLoadComponentScript(postLoadComponentScript)
{
}
@@ -62,35 +65,26 @@ void UpdatesInfoData::parseFile(const QString &updateXmlFile)
return;
}
- QDomDocument doc;
- QString parseErrorMessage;
- int parseErrorLine, parseErrorColumn;
- if (!doc.setContent(&file, &parseErrorMessage, &parseErrorLine, &parseErrorColumn)) {
- error = UpdatesInfo::InvalidXmlError;
- errorMessage = tr("Parse error in %1 at %2, %3: %4").arg(updateXmlFile,
- QString::number(parseErrorLine), QString::number(parseErrorColumn), parseErrorMessage);
- return;
- }
-
- QDomElement rootE = doc.documentElement();
- if (rootE.tagName() != QLatin1String("Updates")) {
- setInvalidContentError(tr("Root element %1 unexpected, should be \"Updates\".").arg(rootE.tagName()));
- return;
- }
-
- QDomNodeList childNodes = rootE.childNodes();
- for(int i = 0; i < childNodes.count(); i++) {
- const QDomElement childE = childNodes.at(i).toElement();
- if (childE.isNull())
- continue;
-
- if (childE.tagName() == QLatin1String("ApplicationName"))
- applicationName = childE.text();
- else if (childE.tagName() == QLatin1String("ApplicationVersion"))
- applicationVersion = childE.text();
- else if (childE.tagName() == QLatin1String("PackageUpdate")) {
- if (!parsePackageUpdateElement(childE))
- return; //error handled in subroutine
+ QXmlStreamReader reader(&file);
+ if (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("Updates")) {
+ while (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("ApplicationName")) {
+ applicationName = reader.readElementText();
+ } else if (reader.name() == QLatin1String("ApplicationVersion")) {
+ applicationVersion = reader.readElementText();
+ } else if (reader.name() == QLatin1String("Checksum")) {
+ checkSha1CheckSum = (reader.readElementText());
+ } else if (reader.name() == QLatin1String("PackageUpdate")) {
+ if (!parsePackageUpdateElement(reader, checkSha1CheckSum))
+ return; //error handled in subroutine
+ } else {
+ reader.skipCurrentElement();
+ }
+ }
+ } else {
+ setInvalidContentError(tr("Root element %1 unexpected, should be \"Updates\".").arg(reader.name()));
+ return;
}
}
@@ -108,70 +102,58 @@ void UpdatesInfoData::parseFile(const QString &updateXmlFile)
error = UpdatesInfo::NoError;
}
-bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
+bool UpdatesInfoData::parsePackageUpdateElement(QXmlStreamReader &reader, const QString &checkSha1CheckSum)
{
- if (updateE.isNull())
- return false;
-
UpdateInfo info;
- QMap<QString, QString> localizedDescriptions;
- for (int i = 0; i < updateE.childNodes().count(); i++) {
- QDomElement childE = updateE.childNodes().at(i).toElement();
- if (childE.isNull())
+ QHash<QString, QVariant> scriptHash;
+ while (reader.readNext()) {
+ const QString elementName = reader.name().toString();
+ if ((reader.name() == QLatin1String("PackageUpdate"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
+ }
+ if (elementName.isEmpty() || reader.tokenType() == QXmlStreamReader::EndElement)
continue;
-
- if (childE.tagName() == QLatin1String("ReleaseNotes")) {
- info.data[childE.tagName()] = QUrl(childE.text());
- } else if (childE.tagName() == QLatin1String("Licenses")) {
- QHash<QString, QVariant> licenseHash;
- const QDomNodeList licenseNodes = childE.childNodes();
- for (int index = 0; index < licenseNodes.count(); ++index) {
- const QDomNode licenseNode = licenseNodes.at(index);
- if (licenseNode.nodeName() == QLatin1String("License")) {
- QDomElement element = licenseNode.toElement();
- QVariantMap attributes;
- attributes.insert(QLatin1String("file"), element.attributeNode(QLatin1String("file")).value());
- if (!element.attributeNode(QLatin1String("priority")).isNull())
- attributes.insert(QLatin1String("priority"), element.attributeNode(QLatin1String("priority")).value());
- else
- attributes.insert(QLatin1String("priority"), QLatin1String("0"));
- licenseHash.insert(element.attributeNode(QLatin1String("name")).value(), attributes);
- }
- }
- if (!licenseHash.isEmpty())
- info.data.insert(QLatin1String("Licenses"), licenseHash);
- } else if (childE.tagName() == QLatin1String("Version")) {
+ if (elementName == QLatin1String("Licenses")) {
+ parseLicenses(reader, info.data);
+ } else if (elementName == QLatin1String("TreeName")) {
+ const QXmlStreamAttributes attr = reader.attributes();
+ const bool moveChildren = attr.value(QLatin1String("moveChildren")).toString().toLower() == QInstaller::scTrue ? true : false;
+ const QPair<QString, bool> treeNamePair(reader.readElementText(), moveChildren);
+ info.data.insert(QLatin1String("TreeName"), QVariant::fromValue(treeNamePair));
+ } else if (elementName == QLatin1String("Version")) {
+ const QXmlStreamAttributes attr = reader.attributes();
info.data.insert(QLatin1String("inheritVersionFrom"),
- childE.attribute(QLatin1String("inheritVersionFrom")));
- info.data[childE.tagName()] = childE.text();
- } else if (childE.tagName() == QLatin1String("DisplayName")) {
- processLocalizedTag(childE, info.data);
- } else if (childE.tagName() == QLatin1String("Description")) {
- if (!childE.hasAttribute(QLatin1String("xml:lang")))
- info.data[QLatin1String("Description")] = childE.text();
- QString languageAttribute = childE.attribute(QLatin1String("xml:lang"), QLatin1String("en"));
- localizedDescriptions.insert(languageAttribute.toLower(), childE.text());
- } else if (childE.tagName() == QLatin1String("UpdateFile")) {
- info.data[QLatin1String("CompressedSize")] = childE.attribute(QLatin1String("CompressedSize"));
- info.data[QLatin1String("UncompressedSize")] = childE.attribute(QLatin1String("UncompressedSize"));
- } else if (childE.tagName() == QLatin1String("Operations")) {
- const QDomNodeList operationNodes = childE.childNodes();
- QVariant operationListVariant = parseOperations(childE.childNodes());
- info.data.insert(QLatin1String("Operations"), operationListVariant);
+ attr.value(QLatin1String("inheritVersionFrom")).toString());
+ info.data[elementName] = reader.readElementText();
+ } else if (elementName == QLatin1String("DisplayName")
+ || elementName == QLatin1String("Description")) {
+ processLocalizedTag(reader, info.data);
+ } else if (elementName == QLatin1String("UpdateFile")) {
+ info.data[QLatin1String("CompressedSize")] = reader.attributes().value(QLatin1String("CompressedSize")).toString();
+ info.data[QLatin1String("UncompressedSize")] = reader.attributes().value(QLatin1String("UncompressedSize")).toString();
+ } else if (elementName == QLatin1String("Operations")) {
+ parseOperations(reader, info.data);
+ } else if (elementName == QLatin1String("Script")) {
+ const QXmlStreamAttributes attr = reader.attributes();
+ bool postLoad = false;
+ // postLoad can be set either to individual components or to whole repositories.
+ // If individual components has the postLoad attribute, it overwrites the repository value.
+ if (attr.hasAttribute(QLatin1String("postLoad")))
+ postLoad = attr.value(QLatin1String("postLoad")).toString().toLower() == QInstaller::scTrue ? true : false;
+ else if (m_postLoadComponentScript)
+ postLoad = true;
+
+ if (postLoad)
+ scriptHash.insert(QLatin1String("postLoadScript"), reader.readElementText());
+ else
+ scriptHash.insert(QLatin1String("installScript"), reader.readElementText());
} else {
- info.data[childE.tagName()] = childE.text();
- }
- }
-
- QStringList candidates;
- foreach (const QString &lang, QLocale().uiLanguages())
- candidates << QInstaller::localeCandidates(lang.toLower());
- foreach (const QString &candidate, candidates) {
- if (localizedDescriptions.contains(candidate)) {
- info.data[QLatin1String("Description")] = localizedDescriptions.value(candidate);
- break;
+ info.data[elementName] = reader.readElementText();
}
}
+ if (!scriptHash.isEmpty())
+ info.data.insert(QLatin1String("Script"), scriptHash);
if (!info.data.contains(QLatin1String("Name"))) {
setInvalidContentError(tr("PackageUpdate element without Name"));
@@ -185,54 +167,87 @@ bool UpdatesInfoData::parsePackageUpdateElement(const QDomElement &updateE)
setInvalidContentError(tr("PackageUpdate element without ReleaseDate"));
return false;
}
-
+ info.data[QLatin1String("CheckSha1CheckSum")] = checkSha1CheckSum;
updateInfoList.append(info);
return true;
}
-void UpdatesInfoData::processLocalizedTag(const QDomElement &childE, QHash<QString, QVariant> &info) const
+void UpdatesInfoData::processLocalizedTag(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const
{
- QString languageAttribute = childE.attribute(QLatin1String("xml:lang")).toLower();
- if (!info.contains(childE.tagName()) && (languageAttribute.isEmpty()))
- info[childE.tagName()] = childE.text();
+ const QString languageAttribute = reader.attributes().value(QLatin1String("xml:lang")).toString().toLower();
+ const QString elementName = reader.name().toString();
+ if (!info.contains(elementName) && (languageAttribute.isEmpty()))
+ info[elementName] = reader.readElementText();
+ if (languageAttribute.isEmpty())
+ return;
// overwrite default if we have a language specific description
if (QLocale().name().startsWith(languageAttribute, Qt::CaseInsensitive))
- info[childE.tagName()] = childE.text();
+ info[elementName] = reader.readElementText();
}
-QVariant UpdatesInfoData::parseOperations(const QDomNodeList &operationNodes)
+void UpdatesInfoData::parseOperations(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const
{
- QVariant operationListVariant;
QList<QPair<QString, QVariant>> operationsList;
- for (int i = 0; i < operationNodes.count(); ++i) {
- const QDomNode operationNode = operationNodes.at(i);
- if (operationNode.nodeName() == QLatin1String("Operation")) {
- const QDomNodeList argumentNodes = operationNode.childNodes();
- QStringList attributes;
- for (int index = 0; index < argumentNodes.count(); ++index) {
- const QDomNode argumentNode = argumentNodes.at(index);
- if (argumentNode.nodeName() == QLatin1String("Argument")) {
- QDomElement argumentElement = argumentNode.toElement();
- attributes.append(argumentElement.text());
- }
+ while (reader.readNext()) {
+ const QString subElementName = reader.name().toString();
+ // End of parsing operations
+ if ((subElementName == QLatin1String("Operations"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
+ }
+ if (subElementName != QLatin1String("Operation") || reader.tokenType() == QXmlStreamReader::EndElement)
+ continue;
+ QStringList attributes;
+ const QXmlStreamAttributes attr = reader.attributes();
+ while (reader.readNext()) {
+ const QString subElementName2 = reader.name().toString();
+ // End of parsing single operation
+ if ((subElementName2 == QLatin1String("Operation"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
}
- QPair<QString, QVariant> pair;
- pair.first = operationNode.toElement().attributeNode(QLatin1String("name")).value();
- pair.second = attributes;
- operationsList.append(pair);
+ if (subElementName2 != QLatin1String("Argument") || reader.tokenType() == QXmlStreamReader::EndElement)
+ continue;
+ attributes.append(reader.readElementText());
}
+ QPair<QString, QVariant> pair;
+ pair.first = attr.value(QLatin1String("name")).toString();
+ pair.second = attributes;
+ operationsList.append(pair);
}
- operationListVariant.setValue(operationsList);
- return operationListVariant;
+ info.insert(QLatin1String("Operations"), QVariant::fromValue(operationsList));
}
-
+void UpdatesInfoData::parseLicenses(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const
+{
+ QHash<QString, QVariant> licenseHash;
+ while (reader.readNext()) {
+ const QString subElementName = reader.name().toString();
+ // End of parsing Licenses
+ if ((subElementName == QLatin1String("Licenses"))
+ && (reader.tokenType() == QXmlStreamReader::EndElement)) {
+ break;
+ }
+ if (subElementName != QLatin1String("License") || reader.tokenType() == QXmlStreamReader::EndElement)
+ continue;
+ const QXmlStreamAttributes attr = reader.attributes();
+ QVariantMap attributes;
+ attributes.insert(QLatin1String("file"), attr.value(QLatin1String("file")).toString());
+ if (!attr.value(QLatin1String("priority")).isNull())
+ attributes.insert(QLatin1String("priority"), attr.value(QLatin1String("priority")).toString());
+ else
+ attributes.insert(QLatin1String("priority"), QLatin1String("0"));
+ licenseHash.insert(attr.value(QLatin1String("name")).toString(), attributes);
+ }
+ if (!licenseHash.isEmpty())
+ info.insert(QLatin1String("Licenses"), licenseHash);
+}
//
// UpdatesInfo
//
-UpdatesInfo::UpdatesInfo()
- : d(new UpdatesInfoData)
+UpdatesInfo::UpdatesInfo(const bool postLoadComponentScript)
+ : d(new UpdatesInfoData(postLoadComponentScript))
{
}
@@ -260,6 +275,10 @@ void UpdatesInfo::setFileName(const QString &updateXmlFile)
d->updateInfoList.clear();
d->updateXmlFile = updateXmlFile;
+}
+
+void UpdatesInfo::parseFile()
+{
d->parseFile(d->updateXmlFile);
}
@@ -278,6 +297,11 @@ QString UpdatesInfo::applicationVersion() const
return d->applicationVersion;
}
+QString UpdatesInfo::checkSha1CheckSum() const
+{
+ return d->checkSha1CheckSum;
+}
+
int UpdatesInfo::updateInfoCount() const
{
return d->updateInfoList.count();
diff --git a/src/libs/kdtools/updatesinfo_p.h b/src/libs/kdtools/updatesinfo_p.h
index 93e2fe8c6..a3768232a 100644
--- a/src/libs/kdtools/updatesinfo_p.h
+++ b/src/libs/kdtools/updatesinfo_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -58,7 +59,7 @@ public:
InvalidContentError
};
- UpdatesInfo();
+ UpdatesInfo(const bool postLoadComponentScript = false);
~UpdatesInfo();
bool isValid() const;
@@ -68,10 +69,13 @@ public:
QString fileName() const;
void setFileName(const QString &updateXmlFile);
+ void parseFile();
QString applicationName() const;
QString applicationVersion() const;
+ QString checkSha1CheckSum() const;
+
int updateInfoCount() const;
UpdateInfo updateInfo(int index) const;
QList<UpdateInfo> updatesInfo() const;
diff --git a/src/libs/kdtools/updatesinfodata_p.h b/src/libs/kdtools/updatesinfodata_p.h
index 07da6fcf0..c71a85193 100644
--- a/src/libs/kdtools/updatesinfodata_p.h
+++ b/src/libs/kdtools/updatesinfodata_p.h
@@ -32,8 +32,7 @@
#include <QCoreApplication>
#include <QSharedData>
-QT_FORWARD_DECLARE_CLASS(QDomElement)
-QT_FORWARD_DECLARE_CLASS(QDomNodeList)
+QT_FORWARD_DECLARE_CLASS(QXmlStreamReader)
namespace KDUpdater {
@@ -44,7 +43,7 @@ struct UpdatesInfoData : public QSharedData
Q_DECLARE_TR_FUNCTIONS(KDUpdater::UpdatesInfoData)
public:
- UpdatesInfoData();
+ UpdatesInfoData(const bool postLoadComponentScript);
~UpdatesInfoData();
int error;
@@ -52,16 +51,19 @@ public:
QString updateXmlFile;
QString applicationName;
QString applicationVersion;
+ QString checkSha1CheckSum;
QList<UpdateInfo> updateInfoList;
+ bool m_postLoadComponentScript;
void parseFile(const QString &updateXmlFile);
- bool parsePackageUpdateElement(const QDomElement &updateE);
+ bool parsePackageUpdateElement(QXmlStreamReader &reader, const QString &checkSha1CheckSum);
void setInvalidContentError(const QString &detail);
private:
- void processLocalizedTag(const QDomElement &childE, QHash<QString, QVariant> &info) const;
- QVariant parseOperations(const QDomNodeList &operationNodes);
+ void processLocalizedTag(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const;
+ void parseOperations(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const;
+ void parseLicenses(QXmlStreamReader &reader, QHash<QString, QVariant> &info) const;
};
} // namespace KDUpdater
diff --git a/src/libs/libs.pro b/src/libs/libs.pro
index 64bc41d51..076f83b5d 100644
--- a/src/libs/libs.pro
+++ b/src/libs/libs.pro
@@ -1,3 +1,5 @@
TEMPLATE = subdirs
-SUBDIRS += 3rdparty 7zip installer
-installer.depends = 3rdparty 7zip
+
+SUBDIRS += 3rdparty installer
+installer.depends = 3rdparty
+
diff --git a/src/sdk/aboutapplicationdialog.cpp b/src/sdk/aboutapplicationdialog.cpp
new file mode 100644
index 000000000..dc47c956e
--- /dev/null
+++ b/src/sdk/aboutapplicationdialog.cpp
@@ -0,0 +1,100 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "aboutapplicationdialog.h"
+
+#include <packagemanagercore.h>
+#include <settings.h>
+
+#include <QGridLayout>
+#include <QLabel>
+#include <QDialogButtonBox>
+#include <QPixmap>
+
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
+#define ABOUT_IFW_VERSION "Built with Qt Installer Framework " QUOTE(IFW_VERSION_STR)
+#define ABOUT_QT_VERSION "Based on Qt " QT_VERSION_STR
+#define ABOUT_BUILD_DATE "Built on " __DATE__
+#define ABOUT_BUILD_YEAR (__DATE__ + 7)
+#define ABOUT_SHA "From revision " QUOTE(_GIT_SHA1_)
+
+AboutApplicationDialog::AboutApplicationDialog(QInstaller::PackageManagerCore *core, QWidget *parent)
+ : QDialog(parent)
+{
+ setObjectName(QLatin1String("AboutApplicationDialog"));
+
+ const QString productName = core->value(QLatin1String("ProductName"));
+ if (core->isInstaller())
+ setWindowTitle(tr("About %1 installer").arg(productName));
+ else
+ setWindowTitle(tr("About %1 Maintenance Tool").arg(productName));
+
+ QGridLayout *layout = new QGridLayout(this);
+ layout->setSizeConstraint(QLayout::SetFixedSize);
+
+ QLabel *logoLabel = new QLabel;
+#ifdef Q_OS_MACOS
+ QPixmap pixmap;
+ if (pixmap.load(core->settings().installerApplicationIcon()))
+ logoLabel->setPixmap(pixmap);
+#else
+ logoLabel->setPixmap(core->settings().installerWindowIcon());
+#endif
+ const QString description = QString::fromLatin1(
+ "<h3>%1</h3>"
+ "%2<br/>"
+ "<br/>"
+ "%3<br/>"
+ "<br/>"
+ "%4<br/>"
+ "<br/>"
+ "Copyright %5 The Qt Company Ltd. All rights reserved.<br/>"
+ "<br/>"
+ "The program is provided AS IS with NO WARRANTY OF ANY KIND, "
+ "INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A "
+ "PARTICULAR PURPOSE.<br/>")
+ .arg(QLatin1String(ABOUT_IFW_VERSION),
+ QLatin1String(ABOUT_QT_VERSION),
+ QLatin1String(ABOUT_BUILD_DATE),
+ QLatin1String(ABOUT_SHA),
+ QLatin1String(ABOUT_BUILD_YEAR)
+ );
+
+ QLabel *aboutLabel = new QLabel(description);
+ aboutLabel->setWordWrap(true);
+ aboutLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ layout->addWidget(logoLabel , 0, 0, 1, 1);
+ layout->addWidget(aboutLabel, 0, 1, 4, 4);
+ layout->addWidget(buttonBox, 4, 0, 1, 5);
+}
diff --git a/src/sdk/aboutapplicationdialog.h b/src/sdk/aboutapplicationdialog.h
new file mode 100644
index 000000000..5f05aa6d9
--- /dev/null
+++ b/src/sdk/aboutapplicationdialog.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef ABOUTAPPLICATIONDIALOG_H
+#define ABOUTAPPLICATIONDIALOG_H
+
+#include <QDialog>
+
+namespace QInstaller {
+ class PackageManagerCore;
+}
+
+class AboutApplicationDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit AboutApplicationDialog(QInstaller::PackageManagerCore *core,
+ QWidget *parent = nullptr);
+ ~AboutApplicationDialog() = default;
+};
+
+#endif // ABOUTAPPLICATIONDIALOG_H
diff --git a/src/sdk/commandlineinterface.cpp b/src/sdk/commandlineinterface.cpp
index 6b674364c..44f028fd5 100644
--- a/src/sdk/commandlineinterface.cpp
+++ b/src/sdk/commandlineinterface.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -63,6 +63,7 @@ bool CommandLineInterface::initialize()
return false;
}
// Filter the arguments list by removing any key=value pair occurrences.
+ QString command;
m_positionalArguments = m_parser.positionalArguments();
foreach (const QString &argument, m_positionalArguments) {
if (argument.contains(QLatin1Char('=')))
@@ -76,9 +77,10 @@ bool CommandLineInterface::initialize()
} else {
// Sanity and order of arguments already checked in main(), we should be
// quite safe to assume that command is the first positional argument.
+ command = m_positionalArguments.first();
m_positionalArguments.removeFirst();
}
-
+ m_core->saveGivenArguments(QStringList() << command << m_parser.optionNames());
QString ctrlScript = controlScript();
if (!ctrlScript.isEmpty()) {
m_core->controlScriptEngine()->loadInContext(
@@ -96,20 +98,15 @@ int CommandLineInterface::checkUpdates()
qCWarning(QInstaller::lcInstallerInstallLog) << "Cannot check updates with installer.";
return EXIT_FAILURE;
}
- m_core->setUpdater();
- if (!m_core->fetchRemotePackagesTree()) {
- qCWarning(QInstaller::lcInstallerInstallLog) << m_core->error();
- return EXIT_FAILURE;
- }
-
- const QList<QInstaller::Component *> components =
- m_core->components(QInstaller::PackageManagerCore::ComponentType::Root);
- if (components.isEmpty()) {
- qCWarning(QInstaller::lcInstallerInstallLog) << "There are currently no updates available.";
+ try {
+ if (m_core->searchAvailableUpdates() != QInstaller::PackageManagerCore::Success) {
+ return EXIT_FAILURE;
+ }
return EXIT_SUCCESS;
+ } catch (const QInstaller::Error &err) {
+ qCCritical(QInstaller::lcInstallerInstallLog) << err.message();
+ return EXIT_FAILURE;
}
- QInstaller::LoggingHandler::instance().printUpdateInformation(components);
- return EXIT_SUCCESS;
}
int CommandLineInterface::listInstalledPackages()
@@ -139,7 +136,19 @@ int CommandLineInterface::searchAvailablePackages()
QString regexp;
if (!m_positionalArguments.isEmpty())
regexp = m_positionalArguments.first();
- m_core->listAvailablePackages(regexp, parsePackageFilters());
+
+ if (m_parser.isSet(CommandLineOptions::scTypeLong)) {
+ // If type is specified, only list relevant contents
+ if (m_parser.value(CommandLineOptions::scTypeLong) == QLatin1String("package"))
+ m_core->listAvailablePackages(regexp, parsePackageFilters());
+ else if (m_parser.value(CommandLineOptions::scTypeLong) == QLatin1String("alias"))
+ m_core->listAvailableAliases(regexp);
+ } else {
+ // No type - we can try again with packages search if there were no matching aliases
+ if (!m_core->listAvailableAliases(regexp))
+ m_core->listAvailablePackages(regexp, parsePackageFilters());
+ }
+
return EXIT_SUCCESS;
}
@@ -248,6 +257,18 @@ int CommandLineInterface::createOfflineInstaller()
}
}
+int CommandLineInterface::clearLocalCache()
+{
+ if (!initialize())
+ return EXIT_FAILURE;
+
+ if (!m_core->clearLocalCache())
+ return EXIT_FAILURE;
+
+ qCDebug(QInstaller::lcInstallerInstallLog) << "Cache cleared successfully!";
+ return EXIT_SUCCESS;
+}
+
bool CommandLineInterface::checkLicense()
{
const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance();
@@ -267,7 +288,7 @@ bool CommandLineInterface::setTargetDir()
targetDir = m_core->value(QInstaller::scTargetDir);
qCDebug(QInstaller::lcInstallerInstallLog) << "No target directory specified, using default value:" << targetDir;
}
- if (m_core->checkTargetDir(targetDir)) {
+ if (m_core->installationAllowedToDirectory(targetDir)) {
QString targetDirWarning = m_core->targetDirWarning(targetDir);
if (!targetDirWarning.isEmpty()) {
qCWarning(QInstaller::lcInstallerInstallLog) << m_core->targetDirWarning(targetDir);
@@ -291,7 +312,7 @@ QHash<QString, QString> CommandLineInterface::parsePackageFilters()
const QString element = filter.left(i).trimmed();
const QString value = filter.mid(i + 1).trimmed();
- if ((i == -1) || (filter.count(QLatin1Char('=') > 1))
+ if ((i == -1) || (filter.count(QLatin1Char('=')) > 1)
|| element.isEmpty() || value.isEmpty()) {
qCWarning(QInstaller::lcInstallerInstallLog).nospace() << "Ignoring unknown entry "
<< filter << "in package filter arguments. Please use syntax \"element=regex,...\".";
diff --git a/src/sdk/commandlineinterface.h b/src/sdk/commandlineinterface.h
index 29bae74a4..aeaca780f 100644
--- a/src/sdk/commandlineinterface.h
+++ b/src/sdk/commandlineinterface.h
@@ -49,6 +49,7 @@ public:
int uninstallPackages();
int removeInstallation();
int createOfflineInstaller();
+ int clearLocalCache();
private:
bool initialize();
diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp
index 32df0b550..ac2c9d367 100644
--- a/src/sdk/installerbase.cpp
+++ b/src/sdk/installerbase.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -97,18 +97,18 @@ int InstallerBase::run()
if (status != QInstaller::PackageManagerCore::Success)
return status;
+ m_core->saveGivenArguments(m_parser.optionNames());
+
#ifdef ENABLE_SQUISH
- int squishPort = 11233;
if (m_parser.isSet(CommandLineOptions::scSquishPortLong)) {
- squishPort = m_parser.value(CommandLineOptions::scSquishPortLong).toInt();
- }
- if (squishPort != 0) {
- if (Squish::allowAttaching(squishPort))
- qCDebug(QInstaller::lcDeveloperBuild) << "Attaching to squish port " << squishPort << " succeeded";
- else
- qCDebug(QInstaller::lcDeveloperBuild) << "Attaching to squish failed.";
- } else {
- qCWarning(QInstaller::lcDeveloperBuild) << "Invalid squish port number: " << squishPort;
+ const int maxSquishPortNumber = 65535;
+ int squishPort = m_parser.value(CommandLineOptions::scSquishPortLong).toInt();
+ if (squishPort <= 0 || squishPort > maxSquishPortNumber) {
+ qWarning().noquote() << "Invalid Squish port:" << squishPort;
+ } else {
+ bool attachSucceeded = Squish::allowAttaching(squishPort);
+ qCDebug(QInstaller::lcDeveloperBuild) << "Attach to squish port" << squishPort << "succeeded: "<<attachSucceeded;
+ }
}
#endif
const int result = QCoreApplication::instance()->exec();
diff --git a/src/sdk/main.cpp b/src/sdk/main.cpp
index a2eb22189..abfc9dc5a 100644
--- a/src/sdk/main.cpp
+++ b/src/sdk/main.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -38,13 +38,23 @@
#include <utils.h>
#include <loggingutils.h>
+#ifdef IFW_LIB7Z
+#include <7zVersion.h>
+#endif
+#ifdef IFW_LIBARCHIVE
+#include <archive.h>
+#endif
+
#include <QCommandLineParser>
#include <QDateTime>
#include <QNetworkProxyFactory>
+#include <QThread>
+#include <QThreadPool>
+#include <QDeadlineTimer>
#include <iostream>
-#if defined(Q_OS_MACOS) or defined(Q_OS_UNIX)
+#if defined(Q_OS_MACOS) || defined(Q_OS_UNIX)
# include <unistd.h>
# include <sys/types.h>
#endif
@@ -56,8 +66,47 @@
#define SHA "Installer Framework SHA1: " QUOTE(_GIT_SHA1_)
static const char PLACEHOLDER[32] = "MY_InstallerCreateDateTime_MY";
+#ifdef Q_OS_WIN
+static void cleanupUpdate(const CommandLineParser &parser, bool *exit)
+{
+ QString cleanupPath;
+ QString cleanupOption;
+ *exit = false;
+
+ if (parser.isSet(CommandLineOptions::scCleanupUpdate)) {
+ cleanupPath = parser.value(CommandLineOptions::scCleanupUpdate);
+ cleanupOption = CommandLineOptions::scCleanupUpdate;
+ } else if (parser.isSet(CommandLineOptions::scCleanupUpdateOnly)) {
+ cleanupPath = parser.value(CommandLineOptions::scCleanupUpdateOnly);
+ cleanupOption = CommandLineOptions::scCleanupUpdateOnly;
+ *exit = true;
+ }
+
+ if (cleanupOption.isEmpty())
+ return;
+
+ // Since Windows does not support that the maintenance tool deletes itself we
+ // remove the old executable here after update (as the new maintenance tool).
+ if (!cleanupPath.isEmpty()) {
+ QFile fileToRemove(cleanupPath);
+ // Give up after 120 seconds if the old process has not exited and released the file
+ QDeadlineTimer deadline(120000);
+ while (fileToRemove.exists() && !deadline.hasExpired()) {
+ if (fileToRemove.remove()) {
+ std::cout << "Removed leftover file: " << qPrintable(cleanupPath)
+ << " after update." << std::endl;
+ }
+ QThread::msleep(1000);
+ }
+ } else {
+ std::cout << "Invalid value for option " << qPrintable(cleanupOption);
+ }
+}
+#endif
+
int main(int argc, char *argv[])
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (!qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR")
&& !qEnvironmentVariableIsSet("QT_SCALE_FACTOR")
&& !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) {
@@ -66,6 +115,7 @@ int main(int argc, char *argv[])
#if defined(Q_OS_WIN)
QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
#endif
+#endif
// increase maximum numbers of file descriptors
#if defined(Q_OS_MACOS)
QCoreApplication::setSetuidAllowed(true);
@@ -75,6 +125,13 @@ int main(int argc, char *argv[])
setrlimit(RLIMIT_NOFILE, &rl);
#endif
+ // Try to avoid running into situations where the application would hang due to "nested" blocking
+ // usage of the global threadpool that has only one thread available, i.e. main thread invokes
+ // QtConcurrent::run(&myFunction) and myFunction() calls QtConcurrent::blockingFiltered()
+ // for a container.
+ if (QThread::idealThreadCount() == 1)
+ QThreadPool::globalInstance()->setMaxThreadCount(2);
+
// We need to start either a command line application or a GUI application. Since we
// fail doing so at least on Linux while parsing the argument using a core application
// object and later starting the GUI application, we now parse the arguments first.
@@ -112,8 +169,10 @@ int main(int argc, char *argv[])
.arg(mutually.join(QLatin1String(", ")));
sanityCheck = false;
}
- const QSet<QString> commands = parser.positionalArguments().toSet()
- .intersect(CommandLineOptions::scCommandLineInterfaceOptions.toSet());
+ const QStringList positionalArgs = parser.positionalArguments();
+ QSet<QString> commands(positionalArgs.begin(), positionalArgs.end());
+ commands.intersect(QSet<QString>(CommandLineOptions::scCommandLineInterfaceOptions.begin(),
+ CommandLineOptions::scCommandLineInterfaceOptions.end()));
// Check sanity of the given argument sequence.
if (commands.size() > 1) {
sanityMessage = QString::fromLatin1("%1 commands provided, only one can be used at a time.")
@@ -130,6 +189,12 @@ int main(int argc, char *argv[])
if (parser.isSet(CommandLineOptions::scVersionLong)) {
std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl;
+#ifdef IFW_LIB7Z
+ std::cout << "LZMA SDK version: " << MY_VERSION << std::endl;
+#endif
+#ifdef IFW_LIBARCHIVE
+ std::cout << "Libarchive version: " << archive_version_details() << std::endl;
+#endif
const QDateTime dateTime = QDateTime::fromString(QLatin1String(PLACEHOLDER),
QLatin1String("yyyy-MM-dd - HH:mm:ss"));
if (dateTime.isValid())
@@ -144,9 +209,18 @@ int main(int argc, char *argv[])
return help ? EXIT_SUCCESS : EXIT_FAILURE;
}
+#ifdef Q_OS_WIN
+ {
+ bool exit = false;
+ cleanupUpdate(parser, &exit);
+ if (exit)
+ return EXIT_SUCCESS;
+ }
+#endif
+
if (parser.isSet(CommandLineOptions::scStartServerLong)) {
const QStringList arguments = parser.value(CommandLineOptions::scStartServerLong)
- .split(QLatin1Char(','), QString::SkipEmptyParts);
+ .split(QLatin1Char(','), Qt::SkipEmptyParts);
QString socketName, key;
const QString mode = arguments.value(0);
@@ -267,6 +341,9 @@ int main(int argc, char *argv[])
} else if (parser.positionalArguments().contains(CommandLineOptions::scCreateOfflineShort)
|| parser.positionalArguments().contains(CommandLineOptions::scCreateOfflineLong)) {
return CommandLineInterface(argc, argv).createOfflineInstaller();
+ } else if (parser.positionalArguments().contains(CommandLineOptions::scClearCacheShort)
+ || parser.positionalArguments().contains(CommandLineOptions::scClearCacheLong)) {
+ return CommandLineInterface(argc, argv).clearLocalCache();
}
if (QInstaller::LoggingHandler::instance().isVerbose()) {
std::cout << VERSION << std::endl << BUILDDATE << std::endl << SHA << std::endl;
diff --git a/src/sdk/sdk.pro b/src/sdk/sdk.pro
index d952d3462..ee4e8fb1d 100644
--- a/src/sdk/sdk.pro
+++ b/src/sdk/sdk.pro
@@ -9,7 +9,7 @@ include(../../installerfw.pri)
include($$SQUISH_PATH/qtbuiltinhook.pri)
}
-QT += network qml xml widgets
+QT += network qml xml widgets concurrent
# add the minimal plugin in static build to be able to start the installer headless with:
# installer-binary --platform minimal
# using QT += qpa_minimal_plugin would result in a minimal only compiled version
@@ -18,10 +18,11 @@ QT += network qml xml widgets
}
CONFIG(static, static|shared) {
- # prevent qmake from automatically linking in imageformats, bearer, qmltooling plugins
- QTPLUGIN.imageformats = -
+ # prevent qmake from automatically linking in bearer and qmltooling plugins
QTPLUGIN.bearer = -
QTPLUGIN.qmltooling = -
+ # ICNS support required on macOS, prevent linking on other platforms
+ !macos:QTPLUGIN.imageformats = -
}
DESTDIR = $$IFW_APP_PATH
@@ -39,7 +40,9 @@ exists($$LRELEASE) {
"<RCC>" \
" <qresource prefix=\"/\">"
for (file, IB_TRANSLATIONS) {
- lang = $$replace(file, .*_([^/]*)\\.ts, \\1)
+ lang = $$basename(file)
+ lang = $$replace(lang, .ts, "")
+ lang = $$replace(lang, ifw_, "")
qlang = $${lang}
qfile = $$[QT_INSTALL_TRANSLATIONS]/qtbase_$${lang}.qm
!exists($$qfile) {
@@ -100,15 +103,17 @@ HEADERS += \
settingsdialog.h \
sdkapp.h \
commandlineinterface.h \
- installerbase.h
+ installerbase.h \
+ aboutapplicationdialog.h
-SOURCES = \
+SOURCES += \
main.cpp \
installerbase.cpp \
tabcontroller.cpp \
installerbasecommons.cpp \
settingsdialog.cpp \
- commandlineinterface.cpp
+ commandlineinterface.cpp \
+ aboutapplicationdialog.cpp
win32 {
# Use our own manifest file
diff --git a/src/sdk/sdkapp.h b/src/sdk/sdkapp.h
index 0c09897d7..eef0110ec 100644
--- a/src/sdk/sdkapp.h
+++ b/src/sdk/sdkapp.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -60,6 +60,10 @@
#include <QMetaEnum>
#include <QTranslator>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QNetworkInformation>
+#endif
+
template<class T>
class SDKApp : public T
{
@@ -71,6 +75,9 @@ public:
, m_core(nullptr)
{
m_parser.parse(QCoreApplication::arguments());
+#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
+ QNetworkInformation::loadDefaultBackend();
+#endif
}
virtual ~SDKApp()
@@ -83,6 +90,8 @@ public:
{
try {
return T::notify(receiver, event);
+ } catch (QInstaller::Error &e) {
+ qFatal("Exception thrown: %s", qPrintable(e.message()));
} catch (std::exception &e) {
qFatal("Exception thrown: %s", e.what());
} catch (...) {
@@ -107,14 +116,9 @@ public:
}
binary.close();
#endif
- QString fileName = datFile(binaryFile());
- quint64 cookie = QInstaller::BinaryContent::MagicCookieDat;
- if (fileName.isEmpty()) {
- fileName = binaryFile();
- cookie = QInstaller::BinaryContent::MagicCookie;
- }
-
- binary.setFileName(fileName);
+ QString datFileName = datFile(binaryFile());
+ quint64 cookie = datFileName.isEmpty() ? QInstaller::BinaryContent::MagicCookie : QInstaller::BinaryContent::MagicCookieDat;
+ binary.setFileName(!datFileName.isEmpty() ? datFileName : binaryFile());
QInstaller::openForRead(&binary);
qint64 magicMarker;
@@ -143,7 +147,7 @@ public:
if (m_parser.isSet(CommandLineOptions::scLoggingRulesLong)) {
loggingRules = QLatin1String("ifw.* = false\n");
loggingRules += m_parser.value(CommandLineOptions::scLoggingRulesLong)
- .split(QLatin1Char(','), QString::SkipEmptyParts)
+ .split(QLatin1Char(','), Qt::SkipEmptyParts)
.join(QLatin1Char('\n')); // take rules from command line
} else if (isCommandLineInterface) {
loggingRules = QLatin1String("ifw.* = false\n"
@@ -161,7 +165,7 @@ public:
}
QLoggingCategory::setFilterRules(loggingRules);
qCDebug(QInstaller::lcInstallerInstallLog).noquote() << "Arguments:" <<
- QCoreApplication::arguments().join(QLatin1String(", "));
+ m_parser.arguments().join(QLatin1String(", "));
for (auto &optionName : m_parser.optionNames()) {
if (isCommandLineInterface)
@@ -181,14 +185,14 @@ public:
const QHash<QString, QString> userArgs = userArguments();
if (m_parser.isSet(CommandLineOptions::scStartClientLong)) {
const QStringList arguments = m_parser.value(CommandLineOptions::scStartClientLong)
- .split(QLatin1Char(','), QString::SkipEmptyParts);
+ .split(QLatin1Char(','), Qt::SkipEmptyParts);
m_core = new QInstaller::PackageManagerCore(
- magicMarker, oldOperations,
+ magicMarker, oldOperations, datFileName,
arguments.value(0, QLatin1String(QInstaller::Protocol::DefaultSocket)),
arguments.value(1, QLatin1String(QInstaller::Protocol::DefaultAuthorizationKey)),
QInstaller::Protocol::Mode::Debug, userArgs, isCommandLineInterface);
} else {
- m_core = new QInstaller::PackageManagerCore(magicMarker, oldOperations,
+ m_core = new QInstaller::PackageManagerCore(magicMarker, oldOperations, datFileName,
QUuid::createUuid().toString(), QUuid::createUuid().toString(),
QInstaller::Protocol::Mode::Production, userArgs, isCommandLineInterface);
}
@@ -203,8 +207,9 @@ public:
const QStringList translations = m_core->settings().translations();
if (translations.isEmpty()) {
- foreach (const QLocale locale, QLocale().uiLanguages()) {
- QScopedPointer<QTranslator> qtTranslator(new QTranslator(QCoreApplication::instance()));
+ for (const QString &language : QLocale().uiLanguages()) {
+ const QLocale locale(language);
+ std::unique_ptr<QTranslator> qtTranslator(new QTranslator(QCoreApplication::instance()));
bool qtLoaded = qtTranslator->load(locale, QLatin1String("qt"),
QLatin1String("_"), newDirectory);
if (!qtLoaded)
@@ -213,26 +218,33 @@ public:
if (qtLoaded || locale.language() == QLocale::English) {
if (qtLoaded)
- QCoreApplication::instance()->installTranslator(qtTranslator.take());
+ QCoreApplication::instance()->installTranslator(qtTranslator.release());
- QScopedPointer<QTranslator> ifwTranslator(new QTranslator(QCoreApplication::instance()));
+ std::unique_ptr <QTranslator> ifwTranslator(new QTranslator(QCoreApplication::instance()));
bool ifwLoaded = ifwTranslator->load(locale, QLatin1String("ifw"), QLatin1String("_"), newDirectory);
if (!ifwLoaded)
ifwLoaded = ifwTranslator->load(locale, QLatin1String("ifw"), QLatin1String("_"), directory);
- if (ifwLoaded)
- QCoreApplication::instance()->installTranslator(ifwTranslator.take());
+ if (ifwLoaded) {
+ QCoreApplication::instance()->installTranslator(ifwTranslator.release());
+ } else {
+ qCWarning(QInstaller::lcDeveloperBuild) << "Could not load IFW translation for language"
+ << QLocale::languageToString(locale.language());
+ }
// To stop loading other translations it's sufficient that
// qt was loaded successfully or we hit English as system language
lang = locale;
break;
+ } else {
+ qCWarning(QInstaller::lcDeveloperBuild) << "Could not load Qt translation for language"
+ << QLocale::languageToString(locale.language());
}
}
} else {
foreach (const QString &translation, translations) {
- QScopedPointer<QTranslator> translator(new QTranslator(QCoreApplication::instance()));
+ std::unique_ptr<QTranslator> translator(new QTranslator(QCoreApplication::instance()));
if (translator->load(translation, QLatin1String(":/translations")))
- QCoreApplication::instance()->installTranslator(translator.take());
+ QCoreApplication::instance()->installTranslator(translator.release());
}
QLocale currentLocale(translations.at(0).section(QLatin1Char('_'), 1));
lang = currentLocale;
@@ -262,6 +274,16 @@ public:
KDUpdater::FileDownloaderFactory::instance().setProxyFactory(m_core->proxyFactory());
}
+ if (m_parser.isSet(CommandLineOptions::scLocalCachePathLong)) {
+ const QString cachePath = m_parser.value(CommandLineOptions::scLocalCachePathLong);
+ if (cachePath.isEmpty()) {
+ errorMessage = QObject::tr("Empty value for option 'cache-path'.");
+ return false;
+ }
+ m_core->settings().setLocalCachePath(cachePath);
+ }
+ m_core->resetLocalCache(true);
+
if (m_parser.isSet(CommandLineOptions::scShowVirtualComponentsLong))
QInstaller::PackageManagerCore::setVirtualComponentsVisible(true);
@@ -344,6 +366,16 @@ public:
.isSet(CommandLineOptions::scCreateLocalRepositoryLong)
|| m_core->settings().createLocalRepository());
+ if (m_parser.isSet(CommandLineOptions::scMaxConcurrentOperationsLong)) {
+ bool isValid;
+ const int count = m_parser.value(CommandLineOptions::scMaxConcurrentOperationsLong).toInt(&isValid);
+ if (!isValid) {
+ errorMessage = QObject::tr("Invalid value for 'max-concurrent-operations'.");
+ return false;
+ }
+ QInstaller::PackageManagerCore::setMaxConcurrentOperations(count);
+ }
+
if (m_parser.isSet(CommandLineOptions::scAcceptLicensesLong))
m_core->setAutoAcceptLicenses();
@@ -363,7 +395,7 @@ public:
if (m_parser.isSet(CommandLineOptions::scMessageAutomaticAnswerLong)) {
const QString positionalArguments = m_parser.value(CommandLineOptions::scMessageAutomaticAnswerLong);
- const QStringList items = positionalArguments.split(QLatin1Char(','), QString::SkipEmptyParts);
+ const QStringList items = positionalArguments.split(QLatin1Char(','), Qt::SkipEmptyParts);
if (items.count() > 0) {
errorMessage = setMessageBoxAutomaticAnswers(items);
if (!errorMessage.isEmpty())
@@ -376,7 +408,7 @@ public:
}
if (m_parser.isSet(CommandLineOptions::scFileDialogAutomaticAnswer)) {
const QString positionalArguments = m_parser.value(CommandLineOptions::scFileDialogAutomaticAnswer);
- const QStringList items = positionalArguments.split(QLatin1Char(','), QString::SkipEmptyParts);
+ const QStringList items = positionalArguments.split(QLatin1Char(','), Qt::SkipEmptyParts);
foreach (const QString &item, items) {
if (item.contains(QLatin1Char('='))) {
@@ -396,7 +428,7 @@ public:
}
m_core->setValue(QInstaller::scUILanguage, lang.name());
- emit m_core->defaultTranslationsLoadedForLanguage(lang.language());
+ emit m_core->defaultTranslationsLoadedForLanguage(lang);
ProductKeyCheck::instance()->addPackagesFromXml(QLatin1String(":/metadata/Updates.xml"));
return true;
@@ -450,13 +482,39 @@ public:
if (magicMarker == QInstaller::BinaryContent::MagicUninstallerMarker) {
QFileInfo fi(binaryFile);
QString bundlePath;
+ QString datFileName;
if (QInstaller::isInBundle(fi.absoluteFilePath(), &bundlePath))
fi.setFile(bundlePath);
#ifdef Q_OS_MACOS
- return fi.absoluteDir().filePath(fi.baseName() + QLatin1String(".dat"));
+ datFileName = fi.absoluteDir().filePath(fi.baseName() + QLatin1String(".dat"));
#else
- return fi.absoluteDir().filePath(qApp->applicationName() + QLatin1String(".dat"));
+ datFileName = fi.absoluteDir().filePath(qApp->applicationName() + QLatin1String(".dat"));
#endif
+ // When running maintenance tool, datFile name should be the same as the application name.
+ // In case we have updated maintenance tool in previous maintenance tool run, the datFile
+ // name may not match if the maintenance tool name has changed. In that case try to
+ // look for the dat file from the root folder of the install.
+ if (!QFileInfo::exists(datFileName)) {
+ QFileInfo fi(datFileName);
+ QDirIterator it(fi.absolutePath(),
+ QStringList() << QLatin1String("*.dat"),
+ QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
+ while (it.hasNext()) {
+ try {
+ QFile f(it.next());
+ f.open(QIODevice::ReadOnly);
+ if (f.fileName().endsWith(QLatin1String("installer.dat")))
+ continue;
+ QInstaller::BinaryContent::findMagicCookie(&f, magicMarker);
+ datFileName = f.fileName();
+ break;
+ } catch (const QInstaller::Error &error) {
+ Q_UNUSED(error)
+ continue;
+ }
+ }
+ }
+ return datFileName;
}
return QString();
}
@@ -485,7 +543,7 @@ public:
QStringList repositories(const QString &list) const
{
- const QStringList items = list.split(QLatin1Char(','), QString::SkipEmptyParts);
+ const QStringList items = list.split(QLatin1Char(','), Qt::SkipEmptyParts);
foreach (const QString &item, items)
qCDebug(QInstaller::lcInstallerInstallLog) << "Adding custom repository:" << item;
return items;
@@ -498,7 +556,7 @@ public:
foreach (const QString &argument, positionalArguments) {
if (argument.contains(QLatin1Char('='))) {
const QString name = argument.section(QLatin1Char('='), 0, 0);
- const QString value = argument.section(QLatin1Char('='), 1, 1);
+ const QString value = argument.section(QLatin1Char('='), 1);
params.insert(name, value);
}
}
@@ -547,7 +605,7 @@ public:
QString controlScript = QString();
if (m_parser.isSet(CommandLineOptions::scScriptLong)) {
controlScript = m_parser.value(CommandLineOptions::scScriptLong);
- if (!QFileInfo(controlScript).exists())
+ if (!QFileInfo::exists(controlScript))
qCDebug(QInstaller::lcInstallerInstallLog) << "Script file does not exist.";
} else if (!m_core->settings().controlScript().isEmpty()) {
diff --git a/src/sdk/settingsdialog.cpp b/src/sdk/settingsdialog.cpp
index c3159ac36..0a16377b3 100644
--- a/src/sdk/settingsdialog.cpp
+++ b/src/sdk/settingsdialog.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -194,6 +194,7 @@ SettingsDialog::SettingsDialog(PackageManagerCore *core, QWidget *parent)
, m_ui(new Ui::SettingsDialog)
, m_core(core)
, m_showPasswords(false)
+ , m_cacheCleared(false)
{
m_ui->setupUi(this);
setupRepositoriesTreeWidget();
@@ -238,6 +239,23 @@ SettingsDialog::SettingsDialog(PackageManagerCore *core, QWidget *parent)
this, &SettingsDialog::selectAll);
connect(m_ui->m_deselectAll, &QAbstractButton::clicked,
this, &SettingsDialog::deselectAll);
+
+ connect(m_ui->m_clearPushButton, &QAbstractButton::clicked,
+ this, &SettingsDialog::clearLocalCacheClicked);
+ connect(m_ui->m_clearPushButton, &QAbstractButton::clicked, this, [&] {
+ // Disable the button as the new settings will only take effect after
+ // closing the dialog.
+ m_ui->m_clearPushButton->setEnabled(false);
+ m_cacheCleared = true;
+ });
+ connect(m_ui->m_cachePathLineEdit, &QLineEdit::textChanged, this, [&] {
+ if (!m_cacheCleared) {
+ // Disable the button if the path is modified between applying settings
+ m_ui->m_clearPushButton->setEnabled(
+ settings.localCachePath() == m_ui->m_cachePathLineEdit->text());
+ }
+ });
+
useTmpRepositoriesOnly(settings.hasReplacementRepos());
m_ui->m_useTmpRepositories->setChecked(settings.hasReplacementRepos());
m_ui->m_useTmpRepositories->setEnabled(settings.hasReplacementRepos());
@@ -248,6 +266,16 @@ SettingsDialog::SettingsDialog(PackageManagerCore *core, QWidget *parent)
m_ui->m_repositories->setParent(this);
m_ui->m_repositories->setVisible(settings.repositorySettingsPageVisible());
}
+
+ m_ui->m_cachePathLineEdit->setText(settings.localCachePath());
+ m_ui->m_clearPushButton->setEnabled(m_core->isValidCache());
+ showClearCacheProgress(false);
+}
+
+void SettingsDialog::showClearCacheProgress(bool show)
+{
+ m_ui->m_clearCacheProgressLabel->setVisible(show);
+ m_ui->m_clearCacheProgressBar->setVisible(show);
}
void SettingsDialog::accept()
@@ -290,6 +318,14 @@ void SettingsDialog::accept()
settingsChanged |= (settings.httpProxy() != newSettings.httpProxy());
}
+ // need to fetch metadata again
+ settingsChanged |= m_cacheCleared;
+ m_cacheCleared = false;
+
+ // update cache path
+ newSettings.setLocalCachePath(m_ui->m_cachePathLineEdit->text());
+ settingsChanged |= (settings.localCachePath() != newSettings.localCachePath());
+
if (settingsChanged)
emit networkSettingsChanged(newSettings);
diff --git a/src/sdk/settingsdialog.h b/src/sdk/settingsdialog.h
index 97bdd0467..5f5c017a8 100644
--- a/src/sdk/settingsdialog.h
+++ b/src/sdk/settingsdialog.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -104,11 +104,14 @@ class SettingsDialog : public QDialog
public:
explicit SettingsDialog(QInstaller::PackageManagerCore *core, QWidget *parent = 0);
+ void showClearCacheProgress(bool show);
+
public slots:
void accept();
signals:
void networkSettingsChanged(const QInstaller::Settings &settings);
+ void clearLocalCacheClicked();
private slots:
void addRepository();
@@ -131,6 +134,7 @@ private:
QInstaller::PackageManagerCore *m_core;
bool m_showPasswords;
+ bool m_cacheCleared;
QList<QTreeWidgetItem*> m_rootItems;
};
diff --git a/src/sdk/settingsdialog.ui b/src/sdk/settingsdialog.ui
index 6645e6460..90580877d 100644
--- a/src/sdk/settingsdialog.ui
+++ b/src/sdk/settingsdialog.ui
@@ -274,6 +274,102 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="m_localCache">
+ <attribute name="title">
+ <string>Local cache</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QLabel" name="m_cacheDescriptionLabel">
+ <property name="text">
+ <string>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="m_cachePathLabel">
+ <property name="text">
+ <string>Path for cache:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="m_cachePathLineEdit"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_clearCacheProgressLabel">
+ <property name="text">
+ <string>Clearing cache...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="m_clearCacheProgressBar">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximum">
+ <number>0</number>
+ </property>
+ <property name="value">
+ <number>-1</number>
+ </property>
+ <property name="format">
+ <string notr="true">%p%</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="m_clearPushButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Deletes the contents of the cache directory</string>
+ </property>
+ <property name="text">
+ <string>Clear cache</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item>
diff --git a/src/sdk/tabcontroller.cpp b/src/sdk/tabcontroller.cpp
index 3bcb3f11a..8c15243f8 100644
--- a/src/sdk/tabcontroller.cpp
+++ b/src/sdk/tabcontroller.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,6 +29,7 @@
#include "installerbasecommons.h"
#include "settingsdialog.h"
+#include "aboutapplicationdialog.h"
#include "globals.h"
#include <packagemanagercore.h>
@@ -36,6 +37,8 @@
#include <productkeycheck.h>
#include <QtCore/QTimer>
+#include <QtWidgets/QMessageBox>
+#include <QtConcurrent>
using namespace QInstaller;
@@ -118,6 +121,8 @@ int TabController::init()
connect(d->m_gui, &QWizard::currentIdChanged, this, &TabController::onCurrentIdChanged);
connect(d->m_gui, &PackageManagerGui::settingsButtonClicked,
this, &TabController::onSettingsButtonClicked);
+ connect(d->m_gui, &PackageManagerGui::aboutApplicationClicked,
+ this, &TabController::onAboutApplicationClicked);
}
IntroductionPage *page =
@@ -125,7 +130,7 @@ int TabController::init()
if (page) {
page->setMessage(QString());
page->setErrorMessage(QString());
- page->onCoreNetworkSettingsChanged();
+ page->resetFetchedState();
}
d->m_gui->restart();
@@ -151,6 +156,8 @@ void TabController::restartWizard()
d->m_core->settings().setDefaultRepositories(d->m_settings.defaultRepositories());
d->m_core->settings().setTemporaryRepositories(d->m_settings.temporaryRepositories(),
d->m_settings.hasReplacementRepos());
+ d->m_core->settings().setLocalCachePath(d->m_settings.localCachePath());
+
d->m_core->networkSettingsChanged();
}
@@ -166,8 +173,11 @@ void TabController::restartWizard()
void TabController::onSettingsButtonClicked()
{
SettingsDialog dialog(d->m_core);
+ dialog.adjustSize();
connect(&dialog, &SettingsDialog::networkSettingsChanged,
this, &TabController::onNetworkSettingsChanged);
+ connect(&dialog, &SettingsDialog::clearLocalCacheClicked,
+ this, &TabController::onClearCacheClicked);
dialog.exec();
if (d->m_networkSettingsChanged) {
@@ -182,11 +192,65 @@ void TabController::onSettingsButtonClicked()
}
}
+void TabController::onAboutApplicationClicked()
+{
+ AboutApplicationDialog dialog(d->m_core);
+ dialog.exec();
+}
+
+void TabController::onClearCacheClicked()
+{
+ SettingsDialog *settingsDialog = static_cast<SettingsDialog *>(sender());
+ settingsDialog->setEnabled(false);
+ settingsDialog->showClearCacheProgress(true);
+
+ QString errorMessage;
+ bool success = true;
+
+ // Clearing might take some time, run in a separate thread
+ QEventLoop loop;
+ QFutureWatcher<bool> futureWatcher;
+
+ connect(&futureWatcher, &QFutureWatcher<bool>::finished, this, [&]() {
+ success = futureWatcher.future().result();
+ if (loop.isRunning())
+ loop.quit();
+ });
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ futureWatcher.setFuture(QtConcurrent::run(&PackageManagerCore::clearLocalCache,
+ d->m_core, &errorMessage));
+#else
+ futureWatcher.setFuture(QtConcurrent::run(d->m_core,
+ &PackageManagerCore::clearLocalCache, &errorMessage));
+#endif
+
+ if (!futureWatcher.isFinished())
+ loop.exec();
+
+ settingsDialog->setEnabled(true);
+ settingsDialog->showClearCacheProgress(false);
+
+ QMessageBox msgBox(settingsDialog);
+ msgBox.setWindowModality(Qt::WindowModal);
+ msgBox.setStandardButtons(QMessageBox::Close);
+
+ msgBox.setIcon(success
+ ? QMessageBox::Information
+ : QMessageBox::Critical);
+
+ msgBox.setText(success
+ ? tr("Cache cleared successfully!")
+ : errorMessage);
+
+ msgBox.exec();
+}
+
void TabController::onCurrentIdChanged(int newId)
{
if (d->m_gui) {
if (PackageManagerPage *page = qobject_cast<PackageManagerPage *>(d->m_gui->page(newId)))
- d->m_gui->showSettingsButton(page->settingsButtonRequested());
+ d->m_gui->requestSettingsButtonByInstaller(page->settingsButtonRequested());
}
}
diff --git a/src/sdk/tabcontroller.h b/src/sdk/tabcontroller.h
index 5fc63aff3..236ff9fb8 100644
--- a/src/sdk/tabcontroller.h
+++ b/src/sdk/tabcontroller.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -60,6 +60,8 @@ public Q_SLOTS:
private Q_SLOTS:
void restartWizard();
void onSettingsButtonClicked();
+ void onAboutApplicationClicked();
+ void onClearCacheClicked();
void onCurrentIdChanged(int newId);
void onNetworkSettingsChanged(const QInstaller::Settings &settings);
diff --git a/src/sdk/translations/ifw_ar.ts b/src/sdk/translations/ifw_ar.ts
index 65df7ecb6..e10f790d6 100644
--- a/src/sdk/translations/ifw_ar.ts
+++ b/src/sdk/translations/ifw_ar.ts
@@ -212,6 +212,30 @@
<source>User defined repositories</source>
<translation>المستودعات المعرفة من قبل المستخدم</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>ذاكرة التخزين المؤقت المحلية</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>يتم تخزين معلومات التعريف من المستودعات البعيدة مؤقتًا على القرص لتحسين أوقات التحميل. يمكنك تحديد دليل آخر لتخزين ذاكرة التخزين المؤقت أو مسح محتويات ذاكرة التخزين المؤقت الحالية.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>مسار ذاكرة التخزين المؤقت:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>حذف محتويات دليل ذاكرة التخزين المؤقت</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>مسح ذاكرة التخزين المؤقت</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>جاري مسح ذاكرة التخزين المؤقت ...</translation>
+ </message>
</context>
<context>
<name>QObject</name>
@@ -271,6 +295,14 @@
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>الرجاء التأكد من أن المستخدم الحالي لديه حق قراءة الملف &amp;quot;%1&amp;quot; أو حاول تشغيل%2 كمسؤول.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>قيمة غير صالحة لـ &apos;max-concurrent-operations&apos;</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>قيمة فارغة للخيار &apos;cache-path&apos;.</translation>
+ </message>
</context>
<context>
<name>QInstaller</name>
@@ -382,6 +414,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>محتوى غير صالح في &quot;%1&quot;.</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>يمكن حل هذا عن طريق إعادة تشغيل التطبيق بعد مسح ذاكرة التخزين المؤقت من:</translation>
+ </message>
</context>
<context>
<name>BinaryLayout</name>
@@ -442,18 +478,6 @@
<translation>لا يمكن للمكونات أن تحتوي على أطفال في وضع التحديث.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>لا يمكن فتح ملف واجهة المستخدم المطلوب &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>لا يمكن تحميل ملف واجهة المتسخدم المطلوب &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>لا يمكن فتح ملف الرخصة المطلوب &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>خطأ</translation>
</message>
@@ -473,6 +497,26 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>كان هناك خطأ أثناء تحميل المكون المحدد. هذا المكون لا يمكن تثبيته.</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>لا يمكن فتح ملف واجهة المستخدم المطلوب &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>لا يمكن تحميل ملف واجهة المتسخدم المطلوب &quot;%1&quot;: %2.%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>لا يمكن فتح ملف الرخصة المطلوب &quot;%1&quot;: %2.%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -520,62 +564,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>الاف&amp;تراضي</translation>
+ <source>Default</source>
+ <translation>الافتراضي</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>حدد المكونات الافتراضية في العرض الشجري.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;أعد الضبط</translation>
+ <source>Reset</source>
+ <translation>أعد الضبط</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>إعادة تعيين جميع المكونات إلى حالة التحديد الأصلية في طريقة العرض الشجري.</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>&amp;حدّد الكل</translation>
+ <source>Select All</source>
+ <translation>حدّد الكل</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>قم بتحديد جميع المكونات في عرض الشجري.</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>&amp;ألغِ تحديد الكل</translation>
+ <source>Deselect All</source>
+ <translation>ألغِ تحديد الكل</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>قم بإلغاء تحديد المكونات الافتراضية في عرض الشجري.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;تصفح ملفات QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>حدد ملف حزمة دعم لوحة Qt لتثبيت محتوى إضافي غير متاح مباشرة في المستودعات التي عبر الإنترنت.</translation>
</message>
@@ -608,13 +628,37 @@
<translation>يرجى تحديد المكونات التي تريد إزالتها.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
<translation>حدّد المكونات التي تريد تثبيتها. ألغِ تحديد المكونات المثبتة لإزالتها. أي مكونات مثبتة بالفعل لن يتم تحديثها.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>المكونات الضرورية التي يجب تحديثها أولاً قبل اختيار المكونات الآخرى للتحديث.</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>بحث</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>تصفح ملفات &amp;QBSP</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>اختيار</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>خطأ</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>إنشاء المثبت دون اتصال</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>إنشاء برنامج تثبيت دون اتصال من المكونات المحددة، بدلاً من التثبيت الآن.</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentSelectionPagePrivate</name>
@@ -627,7 +671,7 @@
<translation>خطأ</translation>
</message>
<message>
- <source>Component Information</source>
+ <source>Information</source>
<translation>معلومات المكون</translation>
</message>
</context>
@@ -646,12 +690,8 @@
<translation>لا يمكن حفظ إخراج &quot;%1&quot; إلى قيمة مفتاح تثبيت فارغة.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>الملف &quot;%1&quot; غير موجود أو ليس قابلاً للتنفيذ.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>تشغيل &quot;%1&quot; تسبب في إنهيار.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>فشل تشغيل الأمر: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -792,6 +832,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>لا يمكن إنشاء الأرشيف &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>أرشيف غير مدعوم &quot;%1&quot;: لم يتم تسجيل أي معالج للاحقة الملف &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -924,6 +968,11 @@ Error while loading %2</source>
<source>Total: </source>
<translation>المجموع: </translation>
</message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>تم تجاوز عدد مرات إعادة المحاولة (%1).
+</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1066,6 +1115,22 @@ Error while loading %2</source>
<source>Extracting &quot;%1&quot;</source>
<translation>استخراج &quot;%1&quot;</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>أرشيف غير مدعوم &quot;%1&quot;: لم يتم تسجيل أي معالج للاحقة الملف &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>لا يمكن فتح الأرشيف &quot;%1&quot; للقراءة: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>حدث خطأ أثناء قراءة محتويات الأرشيف &quot;%1&quot;: %2.</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>إزالة الملفات المستخرجة من &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
@@ -1119,6 +1184,18 @@ Error while loading %2</source>
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>لا يمكن العثور على الاعتمادية المفقودة &quot;%1&quot; لـ &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>تم الكشف عن تحليل تبعية مستحيلة. سيتم إلغاء تثبيت مكون التثبيت الإجباري &quot;%1&quot; بسبب أن التبعية &quot;%2&quot; تم تعليمها لإلغاء التثبيت بسبب: &quot;%3&quot;.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>المكونات المحددة بواسطة الاسم المستعار &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>تم اكتشاف التكرار، الاسم المستعار للمكون &quot;%1&quot; تم الاضافة مسبقا.</translation>
+ </message>
</context>
<context>
<name>QInstaller::InstallIconsOperation</name>
@@ -1146,6 +1223,10 @@ Error while loading %2</source>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>لا يمكن إنشاء المجلد &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>لا يمكن التحضير لملف النسخ الاحتياطي &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>Lib7z</name>
@@ -1274,10 +1355,6 @@ Error while loading %2</source>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>لا يمكن كتابة ملف الرخصة &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>لم يُعثر على ملفات ترخيص لحذفها.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1301,10 +1378,6 @@ Error while loading %2</source>
<translation>محرك نواة مدير الحزم مفقود.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>جارٍ تحضير تنزيل ملفات التعريف...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>جارٍ فك ضغط المستودعات المضغوطة. قد يستغرق هذا بعص الوقت...</translation>
</message>
@@ -1341,14 +1414,6 @@ Error while loading %2</source>
<translation>اكتُشف عدم تطابق تدقيق المجموع لـ &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>جارٍ الحصول على معلومات التعريف من المستودع البعيد... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>جارٍ الحصول على معلومات التعريف من المستودع البعيد... </translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>حدث خطأ أثناء إستخراج الأرشيف &quot;%1&quot;: %2</translation>
</message>
@@ -1356,6 +1421,49 @@ Error while loading %2</source>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>لا يمكن فتح الملف &quot;%1&quot; للقراءة: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>أرشيف غير مدعوم &quot;%1&quot;: لم يتم تسجيل أي معالج للاحقة الملف &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>جاري إحضار معلومات التحديث الأخيرة...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>جاري تحديث ذاكرة التخزين المؤقت المحلية بـ%n من العناصر الجديدة...</numerusform>
+ <numerusform>جاري تحديث ذاكرة التخزين المؤقت المحلية بـ%n من العناصر الجديدة...</numerusform>
+ <numerusform>جاري تحديث ذاكرة التخزين المؤقت المحلية بـ%n من العناصر الجديدة...</numerusform>
+ <numerusform>جاري تحديث ذاكرة التخزين المؤقت المحلية بـ%n من العناصر الجديدة...</numerusform>
+ <numerusform>جاري تحديث ذاكرة التخزين المؤقت المحلية بـ%n من العناصر الجديدة...</numerusform>
+ <numerusform>جاري تحديث ذاكرة التخزين المؤقت المحلية بـ%n من العناصر الجديدة...</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>قد يؤدي مسح دليل ذاكرة التخزين المؤقت وإعادة تشغيل التطبيق إلى حل هذه المشكلة.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>حدث خطأ غير معروف أثناء تحديث ذاكرة التخزين المؤقت.</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>لا يمكن فتح الملف المستخرج &quot;%1&quot; للقراءة: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>لا يمكن فتح الملف &quot;%1&quot; للكتابة: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>الحصول على المعلومات من المستودع البعيد...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>جارٍ الحصول على معلومات التعريف من المستودع البعيد...</translation>
+ </message>
</context>
<context>
<name>QInstaller::FileTaskObserver</name>
@@ -1431,10 +1539,8 @@ Error while loading %2</source>
<translation>خطأ في كتابة أداة الصيانة</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-جارٍ تنزيل الحزم...</translation>
+ <source>Downloading packages...</source>
+ <translation>جارٍ تنزيل الحزم...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1535,10 +1641,6 @@ Do you want to continue?</source>
<translation>لم يُعثر على حزم مثبتة.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>المكون ذو المعرف %1 موجود بالفعل.</translation>
- </message>
- <message>
<source>Application running in Uninstaller mode.</source>
<translation>يعمل التطبيق في وضع إزالة التثبيت.</translation>
</message>
@@ -1551,42 +1653,24 @@ Do you want to continue?</source>
<translation>لا يمكن الحصول على كافة الاعتماديات.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>المكونات على وشك الحذف.</translation>
- </message>
- <message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>المكون غير موجود.
-</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>المكون غير موجود.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>تم تثبيت المكون فقط كتبعية تلقائية لـ %2.
-</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>تم تثبيت المكون فقط كتبعية تلقائية لـ %2.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>المكون غير قابل للتحقق مما يعني أنه يجب عليك تحديد أحد المكونات الفرعية.
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>المكون غير قابل للتحقق مما يعني أنه يجب عليك تحديد أحد المكونات الفرعية.</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>المكون %1 مثبت بالفعل
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>المكون %1 مثبت بالفعل</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>المكون افتراضي.
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>وجدت العمليات الجارية.</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>المكون افتراضي.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1609,10 +1693,6 @@ Do you want to continue?</source>
<translation>لا توجد مساحة كافية لتخزين جميع المكونات المحددة! بينما المساحة المطلوبة هي %2 على الأقل، المساحة المتاحة هي %1.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>لا توجد مساحة كافية لتخزين الملفات المؤقتة!. بينما المساحة المطلوبة هي %2 على الأقل، المساحة المتاحة هي %1.</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>يبدو أن وحدة التخزين التي حددتها للتثبيت بها مساحة كافية للتثبيت، ولكن سيكون هناك أقل من 1% من مساحة وحدة التخزين المتاحة بعد ذلك.</translation>
</message>
@@ -1629,14 +1709,40 @@ Do you want to continue?</source>
<translation>غير صالح</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>المكون تابع لمكون ظاهري %2.
-</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>المكون تابع لمكون ظاهري %2.</translation>
</message>
<message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
- <translation type="unfinished"></translation>
+ <translation>قد يتجاوز الحجم المقدر للمثبّت 1% حد الحجم القابل للتنفيذ المعتمد وهو %2. قد لا يكون التطبيق قادرًا على التشغيل.</translation>
+ </message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>المكونات التالية على وشك الإزالة:</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>لا يمكن تثبيت المكون%1. حدثت مشكلة أثناء تحميل هذا المكون، لذلك تم وضع علامة &quot;غير مستقر&quot; عليه ولا يمكن اختياره.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>لا توجد مساحة كافية على القرص لتخزين الملفات المؤقتة! يتوفر%1 ، بينما الحد الأدنى المطلوب هو%2. يمكنك تحديد موقع آخر للملفات المؤقتة عن طريق تعديل مسار ذاكرة التخزين المؤقت المحلية من إعدادات المثبت.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>لا يمكن تحديد المكونات المطلوب إزالتها.</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>لا يمكن تحديد الاسم المستعار %1. حدثت مشكلة أثناء تحميل هذا الاسم المستعار، لذا تم وضع علامة عليه كغير مستقر ولا يمكن تحديده.</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>لا يمكن تحديد %1. تم وضع علامة على الاسم المستعار افتراضيًا، مما يعني أنه لا يمكن تحديده يدويًا.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>سيستخدم المثبت الذي تم إنشاؤه %1 من مساحة القرص.</translation>
</message>
</context>
<context>
@@ -1746,16 +1852,12 @@ Do you want to continue?</source>
<translation>إنشاء أداة الصيانة</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-انتهى التثبيت!</translation>
+ <source>Installation finished!</source>
+ <translation>انتهى التثبيت!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-أُلغي التثبيت!</translation>
+ <source>Installation aborted!</source>
+ <translation>أُلغي التثبيت!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1766,16 +1868,12 @@ Installation aborted!</source>
<translation>جارٍ حذف المكونات الغير محددة...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-انتهى التحديث!</translation>
+ <source>Update finished!</source>
+ <translation>انتهى التحديث!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-أُلغي التحديث!</translation>
+ <source>Update aborted!</source>
+ <translation>أُلغي التحديث!</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1818,8 +1916,7 @@ Update aborted!</source>
<translation>تم إحباط الجيل غير المتصل!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
+ <source>Installing component %1</source>
<translation>لا يمكن تثبيت المكون %1</translation>
</message>
<message>
@@ -1867,10 +1964,6 @@ Installing component %1</source>
<translation>لا يمكن الحصول على بيانات التعريف: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>لا تمكن إضافة معلومات مصدر التحديث المؤقت.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>لا يمكن العثور على أي معلومات مصدر تحديث.</translation>
</message>
@@ -1884,6 +1977,50 @@ Installing component %1</source>
%1</source>
<translation>يجب إيقاف هذه العمليات للمتابعة:%1</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>جاري التحضير لتفريغ المكونات ...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>اكتملت%1 من%2 عملية.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>جاري تفريغ المكونات ...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>تم التراجع عن1% من2% عملية.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>تم إكمال التراجع.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>تم تثبيت1% من2% مكونات.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>تم تثبيت جميع المكونات.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>جاري تحميل البرامج النصية للمكونات...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>الاسم المستعار يعلن عن اسم يتعارض مع مكون موجود &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>لم يتم التمكن من تحديد الأسماء المستعارة للمكونات</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>تم اكتشاف تبعية دورية بين الأسماء المستعارة &quot;%1&quot; و &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -1920,7 +2057,7 @@ Installing component %1</source>
<translation>سؤال %1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>الإعدادات</translation>
</message>
<message>
@@ -1941,11 +2078,11 @@ Please copy the installer to a local drive</source>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>الإعداد - %1</translation>
+ <source>Welcome</source>
+ <translation>مَرْحَبًا</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>مرحباً بك في إعداد %1.</translation>
</message>
<message>
@@ -1973,10 +2110,6 @@ Please copy the installer to a local drive</source>
<translation>لا تحديثات متوفرة.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> إدارة الحزم المحلية هي المتاحة فقط.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>&amp;اخرج</translation>
</message>
@@ -2063,7 +2196,7 @@ Please copy the installer to a local drive</source>
<translation>جاهز لإزالة التثبيت</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>الإعداد جاهز الآن لبدأ حذف %1 من حاسوبك. .&lt;br&gt;&lt;font color=&quot;red&quot;&gt;مجلد البرنامج %2 سيُحذف تماماً&lt;/font&gt; مع كل المحتوى فيه!</translation>
</message>
<message>
@@ -2075,7 +2208,7 @@ Please copy the installer to a local drive</source>
<translation>جاهز لتحديث الحزم</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>الإعداد جاهز لبدأ تحديث تثبيتك.</translation>
</message>
<message>
@@ -2087,13 +2220,25 @@ Please copy the installer to a local drive</source>
<translation>جاهز للتثبيت</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>الإعداد جاهز الآن لبدأ تثبيت %1 على حاسوبك.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>جاهز للتحديث</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>إنشاء المثبت دون اتصال</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>جاهز لإنشاء برنامج التثبيت دون اتصال</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>جميع المعلومات المطلوبة متاحة الآن لإنشاء برنامج تثبيت دون اتصال للمكونات المحددة.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PerformInstallationPage</name>
@@ -2133,11 +2278,23 @@ Please copy the installer to a local drive</source>
<source>Uninstalling</source>
<translation>إلغاء التثبيت</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>&amp; إنشاء برنامج التثبيت دون اتصال</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>إنشاء برنامج تثبيت دون اتصال لـ %1</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>إنشاء المثبت دون اتصال</translation>
+ </message>
</context>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>إكمال معالج %1</translation>
</message>
<message>
@@ -2145,7 +2302,7 @@ Please copy the installer to a local drive</source>
<translation>مكتمل</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>اضغط %1 للخروج من معالج %2.</translation>
</message>
<message>
@@ -2157,14 +2314,14 @@ Please copy the installer to a local drive</source>
<translation>شغل %1 الآن.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>فشل معالج %1.</translation>
</message>
</context>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>إكمال معالج إعداد %1</translation>
</message>
</context>
@@ -2287,7 +2444,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>لا يمكن فتح ملف الإعدادات %1 للقراءة: %2</translation>
</message>
<message>
- <source>Select Categories</source>
+ <source>Categories</source>
<translation>حدد الاقسام</translation>
</message>
</context>
@@ -2495,6 +2652,10 @@ or accept the elevation of access rights if being asked.</source>
<source>Try again</source>
<translation>حاول مرة آخرى</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>لا يمكن تحميل %1. لا يمكن إنشاء دليل لـ &quot;%2&quot;</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -2770,10 +2931,6 @@ or accept the elevation of access rights if being asked.</source>
<translation>لا يمكن قراءة &quot;%1&apos;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>خطأ في فرز %1 في %2، %3:%4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>عنصر الجذر %1 غير متوقع، يجب أن يكون &quot;Updates&quot;.</translation>
</message>
@@ -2823,20 +2980,178 @@ or accept the elevation of access rights if being asked.</source>
<translation>لا يمكن فتح الأرشيف &quot;%1&quot; للقراءة: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation>حدث خطأ أثناء قراءة محتويات الأرشيف &quot;%1&quot;: %2.</translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>حدث خطأ أثناء إستخراج الأرشيف &quot;%1&quot;: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation>لا يمكن التحضير للملف &quot;%1&quot;.</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>لا يمكن فتح الأرشيف للقراءة: 1%</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation>تم إلغاء استخراج الارشيف &quot;%1&quot;.</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>لا يمكن قراءة الإدخال 1%.</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>حدث خطأ أثناء إستخراج الأرشيف &quot;%1&quot;: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>لا يمكن كتابة الإدخال &quot;%1&quot; إلى القرص: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>لا يمكن فتح الأرشيف للقراءة: 1%</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>لا يمكن قراءة الإدخال 1%.</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>لا يمكن كتابة الإدخال &quot;%1&quot; إلى القرص: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>لا يمكن فتح الملف &quot;%1&quot; للكتابة: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>لا يمكن فتح الملف &quot;%1&quot; للقراءة: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>لا يمكن كتابة الإدخال لـ &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>إلغاء اختيار المكونات:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>تم استبدال المكونات بـ &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>إزالة المكونات الافتراضية الغير محتوية على تبعيات:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>تم إزالة تبعيات المكونات &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>تم إزالة الاعتماد الذاتي لالمكونات &quot;%1&quot;:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>حول مثبّت %1</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>حول أداة الصيانة %1</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>لا يمكن تهيئة ذاكرة التخزين المؤقت بمسار فارغ.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>لا يمكن إنشاء دليل &quot;%1&quot; لذاكرة التخزين المؤقت.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>لا يمكن تهيئة ذاكرة التخزين المؤقت: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>لا يمكن مسح ذاكرة التخزين المؤقت غير الصالحة.</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>لا يمكن إزالة ملف البيان: %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>خطأ أثناء مسح ذاكرة التخزين المؤقت: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>لا يمكن استرداد العناصر من ذاكرة التخزين المؤقت غير الصالحة.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>لا يمكن استرداد العنصر من ذاكرة التخزين المؤقت غير الصالحة.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>لا يمكن تسجيل العنصر في ذاكرة التخزين المؤقت غير الصالحة.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>لا يمكن تسجيل عنصر فارغ.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>لا يمكن تسجيل عنصر غير صالح مع المجموع الاختباري %1</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>لا يمكن تسجيل العنصر بالمجموع الاختباري %1. عنصر بنفس المجموع الاختباري موجود بالفعل في ذاكرة التخزين المؤقت.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>خطأ أثناء نسخ العنصر إلى المسار &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>لا يمكن إزالة العنصر من ذاكرة التخزين المؤقت غير الصالحة.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>لا يمكن إزالة العنصر المحدد بواسطة المجموع الاختباري %1: لا يوجد مثل هذا العنصر.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>خطأ أثناء إزالة الدليل &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>خطأ أثناء إبطال ذاكرة التخزين المؤقت: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>لا يمكن فتح ملف البيان: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>لا يمكن كتابة محتويات لملف البيان: %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>لا يمكن مزامنة ذاكرة التخزين المؤقت غير الصالحة.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>تم اختبار وضع تسجيل غير معروف!</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>تم مسح ذاكرة التخزين المؤقت بنجاح!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_ca.ts b/src/sdk/translations/ifw_ca.ts
index c9d37264c..ddd7efc13 100644
--- a/src/sdk/translations/ifw_ca.ts
+++ b/src/sdk/translations/ifw_ca.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>No s&apos;ha pogut trobar la dependència «%1» que falta per a «%2».</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -306,6 +318,10 @@
<source>Try again</source>
<translation>Torna a intentar-ho</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -489,10 +505,6 @@
<translation>No s&apos;ha pogut llegir «%1»</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Error d&apos;anàlisi en %1 a %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Element arrel %1 inesperat, hauria de ser «Updates».</translation>
</message>
@@ -744,6 +756,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -752,18 +768,6 @@
<translation>Els components no poden tenir elements secundaris en el mode actualitzador.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>No s&apos;ha pogut obrir el fitxer UI «%1» sol·licitat: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>No s&apos;ha pogut carregar el fitxer UI «%1» sol·licitat: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>No s&apos;ha pogut obrir el fitxer de llicència «%1» sol·licitat: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Error</translation>
</message>
@@ -784,8 +788,24 @@
<translation type="unfinished"></translation>
</message>
<message>
- <source>There was an error loading the selected component. This component cannot be updated.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>No s&apos;ha pogut obrir el fitxer UI «%1» sol·licitat: %2. %3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>No s&apos;ha pogut carregar el fitxer UI «%1» sol·licitat: %2. %3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>No s&apos;ha pogut obrir el fitxer de llicència «%1» sol·licitat: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -834,42 +854,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>Predetermin&amp;at</translation>
+ <source>Default</source>
+ <translation>Predeterminat</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Restableix</translation>
+ <source>Reset</source>
+ <translation>Restableix</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>&amp;Selecciona-ho tot</translation>
+ <source>Select All</source>
+ <translation>Selecciona-ho tot</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Desselecciona-ho tot</translation>
+ <source>Deselect All</source>
+ <translation>Desselecciona-ho tot</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>Explora els fitxers Q&amp;BSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation type="unfinished"></translation>
</message>
@@ -898,35 +914,39 @@
<translation>Seleccioneu els components que voleu desinstal·lar.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Seleccioneu els components que voleu instal·lar. Desseleccioneu els components instal·lats per a desinstal·lar-los. No s&apos;actualitzaran els components ja instal·lats.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Seleccioneu els components que voleu instal·lar. Desseleccioneu els components instal·lats per a desinstal·lar-los.&lt;br&gt;No s&apos;actualitzaran els components ja instal·lats.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>Cal que actualitzeu els components obligatoris abans de poder seleccionar altres components per actualitzar-los.</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Filter the enabled repository categories</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
+ <source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Select</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
+ <source>Error</source>
+ <translation type="unfinished">Error</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -941,8 +961,8 @@
<translation>Error</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Informació</translation>
</message>
</context>
<context>
@@ -960,12 +980,8 @@
<translation>No s&apos;ha pogut desar la sortida de «%1» a un valor de clau buit de l&apos;instal·lador.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>El fitxer «%1» no existeix o no és un binari executable.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>L&apos;execució de «%1» ha resultat en una fallada.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -1102,6 +1118,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>No s&apos;ha pogut eliminar el directori «%1»: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>No s&apos;ha pogut crear l&apos;arxiu «%1»: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1166,6 +1190,62 @@ Error en descarregar %2</translation>
<source>Cannot find component for %1.</source>
<translation>No s&apos;ha pogut trobar el component per a %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation type="unfinished">%1 de %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>S&apos;ha descarregat %1.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dia, </numerusform>
+ <numerusform>%n dies, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n hora, </numerusform>
+ <numerusform>%n hores, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minut</numerusform>
+ <numerusform>%n minuts</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n segon</numerusform>
+ <numerusform>%n segons</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - resta %1%2%3%4.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - temps restant desconegut.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1240,20 +1320,21 @@ Error en descarregar %2</translation>
<source>Extracting &quot;%1&quot;</source>
<translation>S&apos;està extraient «%1»</translation>
</message>
-</context>
-<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
<translation>No s&apos;ha pogut obrir el fitxer «%1» per a lectura: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Error en extreure l&apos;arxiu «%1»: %2</translation>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>S&apos;ha produït una excepció desconeguda en extreure «%1».</translation>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -1325,7 +1406,7 @@ Error en descarregar %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>S&apos;ha completat l&apos;Assistent de %1</translation>
</message>
<message>
@@ -1333,7 +1414,7 @@ Error en descarregar %2</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Feu clic a %1 per a sortir de l&apos;Assistent de %2.</translation>
</message>
<message>
@@ -1345,7 +1426,7 @@ Error en descarregar %2</translation>
<translation>Executa %1 ara.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Ha fallat l&apos;Assistent de %1.</translation>
</message>
</context>
@@ -1386,15 +1467,19 @@ Error en descarregar %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>No s&apos;ha pogut crear el directori «%1»: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Programa d&apos;instal·lació: %1</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Us donem la benvinguda a l&apos;Assistent de configuració de %1.</translation>
</message>
<message>
@@ -1422,13 +1507,13 @@ Error en descarregar %2</translation>
<translation>No hi ha disponible cap actualització.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Només està disponible la gestió dels paquets locals.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Su&amp;rt</translation>
</message>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1472,10 +1557,6 @@ Error en descarregar %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>No s&apos;ha pogut escriure en el fitxer de llicència «%1».</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>No s&apos;han trobat fitxers de llicència per a suprimir.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1499,10 +1580,6 @@ Error en descarregar %2</translation>
<translation>Manca el motor del nucli del gestor de paquets.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>S&apos;està preparant la descàrrega de la informació de les metadades...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>S&apos;estan desempaquetant els repositoris comprimits. Aquesta operació pot trigar una estona...</translation>
</message>
@@ -1535,29 +1612,56 @@ Error en descarregar %2</translation>
<translation>S&apos;ha detectat una discrepància en la suma de verificació per a «%1».</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>S&apos;està recuperant la informació de les metadades des del repositori remot... %1/%2 </translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Error en extreure l&apos;arxiu «%1»: %2</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>S&apos;està recuperant la informació de les metadades des del repositori remot... </translation>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>No s&apos;ha pogut obrir el fitxer «%1» per a lectura: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Error en extreure l&apos;arxiu «%1»: %2</translation>
+ <source>Metadata download canceled.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>S&apos;ha produït una excepció desconeguda en extreure l&apos;arxiu «%1».</translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>No s&apos;ha pogut obrir el fitxer «%1» per a lectura: %2</translation>
+ <source>Fetching latest update information...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
<message>
- <source>Metadata download canceled.</source>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>No s&apos;ha pogut obrir el fitxer «%1» per a escriptura: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>S&apos;està recuperant la informació des de repositoris remots...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>S&apos;està recuperant la informació de les metadades des del repositori remot...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1566,10 +1670,8 @@ Error en descarregar %2</translation>
<translation>Error en escriure a l&apos;Eina de manteniment</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-S&apos;estan descarregant els paquets...</translation>
+ <source>Downloading packages...</source>
+ <translation>S&apos;estan descarregant els paquets...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1674,31 +1776,19 @@ Voleu continuar?</translation>
<translation>No s&apos;han pogut resoldre totes les dependències.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Components que estan a punt d&apos;eliminar-se.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Component %1 already installed
-</source>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
+ <source>Component %1 already installed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
+ <source>Cannot install %1. Component is virtual.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Running processes found.</source>
+ <source>Cannot install %1. Component not found.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1730,10 +1820,6 @@ Voleu continuar?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation type="unfinished"></translation>
</message>
@@ -1742,13 +1828,11 @@ Voleu continuar?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1760,11 +1844,35 @@ Voleu continuar?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
+ <source>Invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Invalid</source>
+ <source>Components about to be removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1883,16 +1991,12 @@ Voleu continuar?</translation>
<translation>S&apos;està creant l&apos;Eina de manteniment</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-S&apos;ha finalitzat la instal·lació!</translation>
+ <source>Installation finished!</source>
+ <translation>S&apos;ha finalitzat la instal·lació!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-S&apos;ha interromput la instal·lació!</translation>
+ <source>Installation aborted!</source>
+ <translation>S&apos;ha interromput la instal·lació!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1903,16 +2007,12 @@ S&apos;ha interromput la instal·lació!</translation>
<translation>S&apos;estan eliminant els components desseleccionats...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Ha finalitzat l&apos;actualització!</translation>
+ <source>Update finished!</source>
+ <translation>Ha finalitzat l&apos;actualització!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-S&apos;ha interromput l&apos;actualització!</translation>
+ <source>Update aborted!</source>
+ <translation>S&apos;ha interromput l&apos;actualització!</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
@@ -1947,10 +2047,8 @@ S&apos;ha interromput l&apos;actualització!</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-S&apos;instal·la el component %1</translation>
+ <source>Installing component %1</source>
+ <translation>S&apos;instal·la el component %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1983,10 +2081,6 @@ S&apos;instal·la el component %1</translation>
<translation>No s&apos;ha pogut recuperar la informació de les metadades: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>No s&apos;ha pogut afegir la informació temporal de la font d&apos;actualització.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>No s&apos;ha pogut trobar cap informació de la font d&apos;actualització.</translation>
</message>
@@ -2015,6 +2109,50 @@ S&apos;instal·la el component %1</translation>
%1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2047,7 +2185,7 @@ S&apos;instal·la el component %1</translation>
<translation>Pregunta %1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Ajustaments</translation>
</message>
<message>
@@ -2118,6 +2256,18 @@ Copieu l&apos;instal·lador en una unitat local</translation>
<source>Uninstalling</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2161,7 +2311,7 @@ Copieu l&apos;instal·lador en una unitat local</translation>
<translation>Llest per a desinstal·lar</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>El programa d&apos;instal·lació està preparat per a començar a eliminar %1 de l&apos;ordinador.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;El directori del programa %2 se suprimirà completament&lt;/font&gt;, incloent tot el contingut d&apos;aquest directori.</translation>
</message>
<message>
@@ -2173,7 +2323,7 @@ Copieu l&apos;instal·lador en una unitat local</translation>
<translation>Llest per a actualitzar els paquets</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>El programa d&apos;instal·lació està preparat per a començar a actualitzar la vostra instal·lació.</translation>
</message>
<message>
@@ -2185,13 +2335,25 @@ Copieu l&apos;instal·lador en una unitat local</translation>
<translation>Llest per a instal·lar</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>El programa d&apos;instal·lació està preparat per a començar a instal·lar %1 en el vostre ordinador.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2248,7 +2410,7 @@ Copieu l&apos;instal·lador en una unitat local</translation>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>S&apos;està completant l&apos;Assistent d&apos;instal·lació de %1</translation>
</message>
</context>
@@ -2471,6 +2633,14 @@ Copieu l&apos;instal·lador en una unitat local</translation>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2515,8 +2685,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>No s&apos;ha pogut obrir el fitxer d&apos;ajustaments %1 per a lectura: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>Selecciona les categories dels paquets</translation>
+ <source>Categories</source>
+ <translation>Categories</translation>
</message>
</context>
<context>
@@ -2653,6 +2823,30 @@ or accept the elevation of access rights if being asked.</source>
<source>The server&apos;s URL that contains a valid repository.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2710,4 +2904,189 @@ or accept the elevation of access rights if being asked.</source>
<translation type="unfinished"></translation>
</message>
</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation::Worker</name>
+ <message>
+ <source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>No s&apos;ha pogut obrir el fitxer «%1» per a lectura: %2</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Error en extreure l&apos;arxiu «%1»: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>No s&apos;ha pogut obrir el fitxer «%1» per a escriptura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>No s&apos;ha pogut obrir el fitxer «%1» per a lectura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
</TS>
diff --git a/src/sdk/translations/ifw_da.ts b/src/sdk/translations/ifw_da.ts
index bbeec6687..a6325fb01 100644
--- a/src/sdk/translations/ifw_da.ts
+++ b/src/sdk/translations/ifw_da.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Kan ikke finde manglende afhængighed &quot;%1&quot; til &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -306,6 +318,10 @@
<source>Try again</source>
<translation>Prøv igen</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -489,10 +505,6 @@
<translation>Kan ikke læse &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Parse-fejl i %1 ved %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Rod-elementet %1 uventet, skulle være &quot;Updates&quot;.</translation>
</message>
@@ -744,6 +756,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -752,18 +768,6 @@
<translation>Komponenter må ikke have børn i opdateringstilstand.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Kan ikke åbne den anmodede UI-fil &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Kan ikke indlæse den anmodede UI-fil &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Kan ikke åbne den anmodede licensfil &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Fejl</translation>
</message>
@@ -784,8 +788,28 @@
<translation type="unfinished"></translation>
</message>
<message>
- <source>There was an error loading the selected component. This component cannot be updated.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Kan ikke åbne den anmodede UI-fil &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Kan ikke indlæse den anmodede UI-fil &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Kan ikke åbne den anmodede licensfil &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -834,32 +858,32 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>&amp;Standard</translation>
+ <source>Default</source>
+ <translation>Standard</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Nulstil</translation>
+ <source>Reset</source>
+ <translation>Nulstil</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>&amp;Vælg alle</translation>
+ <source>Select All</source>
+ <translation>Vælg alle</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Fravælg alle</translation>
+ <source>Deselect All</source>
+ <translation>Fravælg alle</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
@@ -870,12 +894,8 @@
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Gennemse QBSP-filer</translation>
- </message>
- <message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Vælg de komponenter du vil installere. Fravælg installeret komponenter for at afinstallere dem. Komponenter som allerede er installeret vil ikke blive opdateret.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Vælg de komponenter du vil installere. Fravælg installeret komponenter for at afinstallere dem.&lt;br&gt;Komponenter som allerede er installeret vil ikke blive opdateret.</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -906,29 +926,33 @@
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
+ <source>Filter the enabled repository categories</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
+ <source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+V</translation>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+F</translation>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
+ <source>Browse &amp;QBSP files</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Select</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Fejl</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -945,12 +969,8 @@
<translation>Kan ikke gemme outputtet fra &quot;%1&quot; til en tom installer-nøgleværdi.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Filen &quot;%1&quot; findes ikke eller er ikke en eksekverbar binær.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Kørsel af &quot;%1&quot; resulterede i at det holdt op med at virke.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -1087,6 +1107,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Kan ikke fjerne mappen &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>Kan ikke oprette arkivet &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1151,6 +1179,62 @@ Fejl under indlæsning af %2</translation>
<source>Cannot find component for %1.</source>
<translation>Kan ikke finde komponent til %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 af %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 downloadet.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dag, </numerusform>
+ <numerusform>%n dage, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n time, </numerusform>
+ <numerusform>%n timer, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minut</numerusform>
+ <numerusform>%n minutter</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n sekund</numerusform>
+ <numerusform>%n sekunder</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 tilbage.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - ukendt tid tilbage.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1220,21 +1304,6 @@ Fejl under indlæsning af %2</translation>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <message>
- <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
- <translation>Kan ikke åbne arkivet &quot;%1&quot; til læsning: %2</translation>
- </message>
- <message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Fejl under udpakning af arkivet &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Ukendt undtagelse fanget under udpakning af &quot;%1&quot;.</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1303,7 +1372,7 @@ Fejl under indlæsning af %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Fuldfører %1-assistenten</translation>
</message>
<message>
@@ -1311,7 +1380,7 @@ Fejl under indlæsning af %2</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Klik på %1 for at afslutte %2-assistenten.</translation>
</message>
<message>
@@ -1323,7 +1392,7 @@ Fejl under indlæsning af %2</translation>
<translation>Kør %1 nu.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>%1-assistenten mislykkedes.</translation>
</message>
</context>
@@ -1364,15 +1433,19 @@ Fejl under indlæsning af %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Kan ikke oprette mappen &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Opsætning - %1</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Velkommen til opsætningsassistenten for %1.</translation>
</message>
<message>
@@ -1388,10 +1461,6 @@ Fejl under indlæsning af %2</translation>
<translation>Ingen tilgængelige opdateringer.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Kun lokal pakkehåndtering tilgængeligt.</translation>
- </message>
- <message>
<source>&amp;Add or remove components</source>
<translation>&amp;Tilføj eller fjern komponenter</translation>
</message>
@@ -1407,6 +1476,10 @@ Fejl under indlæsning af %2</translation>
<source>&amp;Quit</source>
<translation>&amp;Afslut</translation>
</message>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1450,10 +1523,6 @@ Fejl under indlæsning af %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Kan ikke skrive licensfilen &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Ingen licensfil fundet til sletning.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1477,10 +1546,6 @@ Fejl under indlæsning af %2</translation>
<translation>Manglende pakkehåndterings-kernemotor.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Forbedreder download af metainformation...</translation>
- </message>
- <message>
<source>Unknown exception during extracting.</source>
<translation>Ukendt undtagelse under udpakning.</translation>
</message>
@@ -1509,10 +1574,6 @@ Fejl under indlæsning af %2</translation>
<translation>Fejl under udpakning af arkivet &quot;%1&quot;: %2</translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Ukendt undtagelse fanget under udpakning af arkivet &quot;%1&quot;.</translation>
- </message>
- <message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>Kan ikke åbne filen &quot;%1&quot; til læsning: %2</translation>
</message>
@@ -1525,17 +1586,48 @@ Fejl under indlæsning af %2</translation>
<translation>Tjeksum uoverensstemmelse registreret for &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Henter metainformation fra fjern-repository... %1/%2 </translation>
+ <source>Metadata download canceled.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Henter metainformation fra fjern-repository... </translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Metadata download canceled.</source>
+ <source>Fetching latest update information...</source>
<translation type="unfinished"></translation>
</message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Kan ikke åbne filen &quot;%1&quot; til skrivning: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Henter information fra fjern-repository...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Henter metainformation fra fjern-repository...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1544,10 +1636,8 @@ Fejl under indlæsning af %2</translation>
<translation>Fejl ved skrivning af vedligeholdelsesværktøj</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Downloader pakker...</translation>
+ <source>Downloading packages...</source>
+ <translation>Downloader pakker...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1652,31 +1742,19 @@ Vil du fortsætte?</translation>
<translation>Kan ikke løse alle afhængigheder.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Komponenter som er ved at blive fjernet.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Component %1 already installed
-</source>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
+ <source>Component %1 already installed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
+ <source>Cannot install %1. Component is virtual.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Running processes found.</source>
+ <source>Cannot install %1. Component not found.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1708,10 +1786,6 @@ Vil du fortsætte?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation type="unfinished"></translation>
</message>
@@ -1720,13 +1794,11 @@ Vil du fortsætte?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1738,11 +1810,35 @@ Vil du fortsætte?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
+ <source>Invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Invalid</source>
+ <source>Components about to be removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1861,16 +1957,12 @@ Vil du fortsætte?</translation>
<translation>Opretter vedligeholdelsesværktøj</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Installation færdig!</translation>
+ <source>Installation finished!</source>
+ <translation>Installation færdig!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Installation afbrudt!</translation>
+ <source>Installation aborted!</source>
+ <translation>Installation afbrudt!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1881,16 +1973,12 @@ Installation afbrudt!</translation>
<translation>Fjerner fravalgte komponenter...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Opdatering færdig!</translation>
+ <source>Update finished!</source>
+ <translation>Opdatering færdig!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Opdatering afbrudt!</translation>
+ <source>Update aborted!</source>
+ <translation>Opdatering afbrudt!</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
@@ -1925,10 +2013,8 @@ Opdatering afbrudt!</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Installerer komponenten %1</translation>
+ <source>Installing component %1</source>
+ <translation>Installerer komponenten %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1961,10 +2047,6 @@ Installerer komponenten %1</translation>
<translation>Kan ikke hente metainformation: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Kan ikke tilføje kildeinformation for midlertidig opdatering.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Kan ikke finde nogen kildeinformation for opdatering.</translation>
</message>
@@ -1993,6 +2075,50 @@ Installerer komponenten %1</translation>
%1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2025,7 +2151,7 @@ Installerer komponenten %1</translation>
<translation>%1 spørgsmål</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Indstillinger</translation>
</message>
<message>
@@ -2096,6 +2222,18 @@ Kopiér venligst installeren til et lokalt drev</translation>
<source>Uninstalling</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2139,7 +2277,7 @@ Kopiér venligst installeren til et lokalt drev</translation>
<translation>Klar til afinstallation</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Opsætningen er nu klar til at begynde fjernelsen af %1 fra din computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;Programmappen %2 slettes fuldstændigt&lt;/font&gt;, inklusiv alt indhold i mappen!</translation>
</message>
<message>
@@ -2151,7 +2289,7 @@ Kopiér venligst installeren til et lokalt drev</translation>
<translation>Klar til opdateringspakker</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>Opsætningen er nu klar til at begynde opdateringen af din installation.</translation>
</message>
<message>
@@ -2163,13 +2301,25 @@ Kopiér venligst installeren til et lokalt drev</translation>
<translation>Klar til installation</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Opsætningen er nu klar til at begynde installationen af %1 på din computer.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2226,7 +2376,7 @@ Kopiér venligst installeren til et lokalt drev</translation>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Fuldfører opsætningsassistenten for %1</translation>
</message>
</context>
@@ -2449,6 +2599,14 @@ Kopiér venligst installeren til et lokalt drev</translation>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2492,7 +2650,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>Kan ikke åbne indstillingsfilen %1 til læsning: %2</translation>
</message>
<message>
- <source>Select Categories</source>
+ <source>Categories</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2620,16 +2778,40 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished">Vælg alle</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished">Fravælg alle</translation>
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2691,7 +2873,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>Fejl</translation>
</message>
<message>
- <source>Component Information</source>
+ <source>Information</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2701,6 +2883,22 @@ or accept the elevation of access rights if being asked.</source>
<source>Extracting &quot;%1&quot;</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Kan ikke åbne arkivet &quot;%1&quot; til læsning: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2709,4 +2907,189 @@ or accept the elevation of access rights if being asked.</source>
<translation type="unfinished"></translation>
</message>
</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation::Worker</name>
+ <message>
+ <source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Kan ikke åbne arkivet &quot;%1&quot; til læsning: %2</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Fejl under udpakning af arkivet &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Kan ikke åbne filen &quot;%1&quot; til skrivning: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Kan ikke åbne filen &quot;%1&quot; til læsning: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
</TS>
diff --git a/src/sdk/translations/ifw_de.ts b/src/sdk/translations/ifw_de.ts
index c750189c8..ad80c6624 100644
--- a/src/sdk/translations/ifw_de.ts
+++ b/src/sdk/translations/ifw_de.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Konnte fehlende Abhängigkeit &apos;%1&apos; für &apos;%2&apos; nicht finden.</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>Die Abhängigkeiten sind nicht auflösbar. Die zur forcierten Installation vorgesehene Komponente &quot;%1&quot; würde deinstalliert werden, weil sie von Komponente &quot;%2&quot; abhängt, welche auf Grund von &quot;%3&quot; zur Deinstallation vorgesehen ist.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>Durch den Alias &quot;%1&quot; ausgewählte Komponenten</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>Es wurde eine Rekursion festegestellt; der Alias &quot;%1&quot; wurde bereits hinzugefügt.</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -306,6 +318,10 @@
<source>Try again</source>
<translation>Erneut versuchen</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>Kann %1 nicht herunterladen. Es kann kein Verzeichnis für &quot;%2&quot; erstellt werden</translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -489,10 +505,6 @@
<translation>Konnte Datei &quot;%1&quot; nicht lesen</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Ungültiges XML in Datei %1, Zeile %2, Spalte %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Unerwartetes Wurzelelement %1, erwartet wird &quot;UpdateSources&quot;.</translation>
</message>
@@ -744,6 +756,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>Ungültiger Inhalt in &quot;%1&quot;.</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>Das kann durch Neustart der Anwendung behoben werden; nach Löschen des Caches von:</translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -752,18 +768,6 @@
<translation>Komponenten können im Updater-Modus keine Kinder haben.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Konnte angeforderte UI-Datei &apos;%1&apos; nicht öffnen: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Konnte angeforderte UI-Datei &apos;%1&apos; nicht laden: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Konnte angeforderte Lizenzdatei &apos;%1&apos; nicht öffnen: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Fehler</translation>
</message>
@@ -783,6 +787,30 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>Es ist ein Fehler beim Laden der ausgewählten Komponente aufgetreten. Diese Komponente kann nicht installiert werden.</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Konnte angeforderte UI-Datei &quot;%1&quot; nicht öffnen: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Konnte angeforderte UI-Datei &quot;%1&quot; nicht laden: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Konnte angeforderte Lizenzdatei &quot;%1&quot; nicht öffnen: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -830,64 +858,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>St&amp;andard</translation>
+ <source>Default</source>
+ <translation>Standard</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>Wählt die Standardkomponenten in der Baumansicht aus.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+Z</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Zurücksetzen</translation>
+ <source>Reset</source>
+ <translation>Zurücksetzen</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>Setzt alle Komponenten in der Baumansicht auf die ursprüngliche Auswahl zurück.</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>Alle au&amp;swählen</translation>
+ <source>Select All</source>
+ <translation>Alle auswählen</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>Wählt alle Komponenten in der Baumansicht aus.</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+B</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>Alle a&amp;bwählen</translation>
+ <source>Deselect All</source>
+ <translation>Alle abwählen</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>Wählt alle Komponenten in der Baumansicht ab.</translation>
</message>
<message>
- <source>Open File</source>
- <translation>Datei öffnen</translation>
+ <source>Search</source>
+ <translation>Suchen</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>Durchsuche QBSP Dateien</translation>
+ <source>Open File</source>
+ <translation>Datei öffnen</translation>
</message>
<message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
@@ -918,13 +926,33 @@
<translation>Bitte wählen Sie die Komponenten aus, die Sie entfernen möchten.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Bitte wählen Sie die Komponenten aus, die Sie installieren möchten. Wählen Sie die Komponenten ab, die Sie entfernen möchten.</translation>
- </message>
- <message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>Obligatorische Komponenten müssen zuerst aktualisiert werden, bevor andere Komponenten zur Aktualisierung ausgewählt werden können.</translation>
</message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Durchsuche QBSP Dateien</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>Auswählen</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Fehler</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Offline-Installer Erstellen</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>Erstellt einen Offline-Installer von den ausgewählten Komponenten anstatt zu installieren</translation>
+ </message>
+ <message>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Bitte wählen Sie die Komponenten aus, die Sie installieren möchten. Wählen Sie die Komponenten ab, die Sie entfernen möchten.</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentSelectionPagePrivate</name>
@@ -937,8 +965,8 @@
<translation>Fehler</translation>
</message>
<message>
- <source>Component Information</source>
- <translation>Komponenteninformationen</translation>
+ <source>Information</source>
+ <translation>Informationen</translation>
</message>
</context>
<context>
@@ -956,12 +984,8 @@
<translation>Konnte die Ausgabe von &quot;%1&quot; nicht in einen leeren Schlüsselwert des Installers speichern.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Datei &apos;%1&apos; existiert nicht oder ist keine ausführbare Binärdatei.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Ausführen von &apos;%1&apos; führte zu einem Absturz.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>Das Kommando &quot;%1&quot; konnte nicht ausgeführt werden: %2</translation>
</message>
</context>
<context>
@@ -1051,6 +1075,10 @@
<translation>Konnte Datei &quot;%1&quot; nicht löschen: %2</translation>
</message>
<message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Nicht unterstütztes Archivformat: &quot;%1&quot;: Für die Dateiendung &quot;%2&quot; ist keine Behandlungsroutine registriert.</translation>
+ </message>
+ <message>
<source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
<translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%2&quot; verschieben: %3</translation>
</message>
@@ -1137,14 +1165,6 @@
<translation>Fehler beim Herunterladen</translation>
</message>
<message>
- <source>Hash verification while downloading failed. This is a temporary error, please retry.</source>
- <translation>Prüfsumme ungültig beim Herunterladen. Dies ist ein kurzzeitiger Fehler, bitte erneut versuchen.</translation>
- </message>
- <message>
- <source>Cannot verify Hash</source>
- <translation>Prüfsumme konnte nicht geprüft werden</translation>
- </message>
- <message>
<source>Cannot download archive %1: %2</source>
<translation>Konnte Archiv %1 nicht herunterladen: %2</translation>
</message>
@@ -1218,6 +1238,28 @@ Fehler beim Laden von %2</translation>
<source>Archive: </source>
<translation>Archiv: </translation>
</message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>Anzahl der Wiederholungen (%1) überschritten</translation>
+ </message>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.
+
+Expected: %1
+Downloaded: %2</source>
+ <translation>Prüfsumme ungültig beim Herunterladen. Dies ist ein kurzzeitiger Fehler, bitte erneut versuchen.
+
+Erwartet: %1
+Heruntergeladen: %2</translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash
+Expected: %1
+Downloaded: %2</source>
+ <translation>Prüfsumme konnte nicht geprüft werden
+Erwartet: %1
+Heruntergeladen: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1292,6 +1334,22 @@ Fehler beim Laden von %2</translation>
<source>Extracting &quot;%1&quot;</source>
<translation>&quot;%1&quot; wird extrahiert</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Nicht unterstütztes Archivformat: &quot;%1&quot;: Für die Dateiendung &quot;%2&quot; ist keine Behandlungsroutine registriert.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Konnte Archiv &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Fehler beim Lesen des Inhaltes des Archivs &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Lösche von &quot;%1&quot; ausgepackte Dateien</translation>
+ </message>
</context>
<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
@@ -1362,7 +1420,7 @@ Fehler beim Laden von %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Den %1-Assistent abschließen</translation>
</message>
<message>
@@ -1370,7 +1428,7 @@ Fehler beim Laden von %2</translation>
<translation>Abschließen</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Klicken Sie %1, um den %2 Assistenten zu beenden.</translation>
</message>
<message>
@@ -1382,7 +1440,7 @@ Fehler beim Laden von %2</translation>
<translation>Starte jetzt %1.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Der %1-Assistent ist fehlgeschlagen.</translation>
</message>
</context>
@@ -1408,6 +1466,10 @@ Fehler beim Laden von %2</translation>
<translation>Ungültiges Argument: Quellordner darf nicht leer sein.</translation>
</message>
<message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>Konnte Sichern der Datei &quot;%1&quot; nicht vorbereiten: %2</translation>
+ </message>
+ <message>
<source>Cannot backup file &quot;%1&quot;: %2</source>
<translation>Konnte Datei &quot;%1&quot; nicht sichern: %2</translation>
</message>
@@ -1427,11 +1489,11 @@ Fehler beim Laden von %2</translation>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Einrichten - %1</translation>
+ <source>Welcome</source>
+ <translation>Willkommen</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Willkommen zum %1-Einrichtungsassistenten.</translation>
</message>
<message>
@@ -1459,10 +1521,6 @@ Fehler beim Laden von %2</translation>
<translation>Keine Aktualisierungen verfügbar.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Nur lokale Paketverwaltung verfügbar.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Beenden</translation>
</message>
@@ -1514,10 +1572,6 @@ Fehler beim Laden von %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Konnte Lizenzdatei &quot;%1&quot; nicht schreiben.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Keine Lizenzdateien zum Löschen gefunden.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1541,10 +1595,6 @@ Fehler beim Laden von %2</translation>
<translation>Fehlende Paketmanager-Kernkomponente.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Herunterladen der Metainformationen wird vorbereitet ...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Entpacken des komprimierten Repository, Das könnte eine Weile dauern...</translation>
</message>
@@ -1581,12 +1631,8 @@ Fehler beim Laden von %2</translation>
<translation>Checksummen stimmen nicht überein &apos;%1&apos;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Metainformationen werden vom Installationsserver empfangen... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Metainformationen werden vom Installationsserver empfangen ... </translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Nicht unterstütztes Archivformat: &quot;%1&quot;: Für die Dateiendung &quot;%2&quot; ist keine Behandlungsroutine registriert.</translation>
</message>
<message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
@@ -1596,6 +1642,41 @@ Fehler beim Laden von %2</translation>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>Kann die Datei &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
</message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>Hole neue Update-Information...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>%n Element im lokalen Cache erneuert...</numerusform>
+ <numerusform>%n Elemente im lokalen Cache erneuert...</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>Das Löschen des Cache-Verzeichnisses and Neustarten der Anwendung kann das beheben.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Unbekannte Ausnahmebedingung beim Aktualisieren des Caches</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>Die extrahierte Datei &quot;%1&quot; konnte nicht zum Lesen geöffnet werden: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Die Datei &quot;%1&quot; konnte nicht zum Schreiben geöffnet werden: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Informationen werden vom Installationsserver empfangen...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Metainformationen werden vom Installationsserver empfangen...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1604,10 +1685,8 @@ Fehler beim Laden von %2</translation>
<translation>Fehler beim Schreiben des Verwaltungswerkzeugs</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Pakete werden heruntergeladen ...</translation>
+ <source>Downloading packages...</source>
+ <translation>Pakete werden heruntergeladen ...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1708,10 +1787,6 @@ Möchten Sie trotzdem fortsetzen?</translation>
<translation>Keine installierten Pakete gefunden.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>Komponente kann nicht registriert werden! Die Komponente mit dem Bezeichner %1 existiert bereits.</translation>
- </message>
- <message>
<source>Application running in Uninstaller mode.</source>
<translation>Die Anwendung läuft im Deinstallationsmodus.</translation>
</message>
@@ -1724,42 +1799,24 @@ Möchten Sie trotzdem fortsetzen?</translation>
<translation>Konnte nicht alle Abhängigkeiten auflösen.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Komponenten, die entfernt werden.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>Komponente %1 kann nicht installiert werden. Die Komponente wird nur als automatische Abhängigkeit von %2 installiert.
-</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>Komponente %1 kann nicht installiert werden. Die Komponente wird nur als automatische Abhängigkeit von %2 installiert.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>Komponente %1 kann nicht installiert werden. Die Komponente kann nicht ausgewählt werden, d.&#xa0;h., Sie müssen eine der Unterkomponenten auswählen.
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>Komponente %1 kann nicht installiert werden. Die Komponente kann nicht ausgewählt werden, d.&#xa0;h., Sie müssen eine der Unterkomponenten auswählen.</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>Komponente %1 ist bereits installiert
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>Komponente %1 ist bereits installiert</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>%1 kann nicht installiert werden. Die Komponente ist virtuell.
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>%1 kann nicht installiert werden. Die Komponente ist virtuell.</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>%1 kann nicht installiert werden. Komponente nicht gefunden.
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>Laufende Prozesse gefunden.</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>%1 kann nicht installiert werden. Komponente nicht gefunden.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1782,10 +1839,6 @@ Möchten Sie trotzdem fortsetzen?</translation>
<translation>Nicht genügend Festplattenplatz für alle ausgewählten Komponenten! Verfügbarer Platz: %1, mindestens benötigt: %2.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>Nicht genügend Festplattenplatz für temporäre Dateien! Verfügbarer Platz: %1, mindestens benötigt: %2.</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>Das für die Installation ausgewählte Laufwerk scheint über genügend Speicherplatz für die Installation zu verfügen, aber anschließend ist weniger als 1% des Speicherplatzes verfügbar.</translation>
</message>
@@ -1802,15 +1855,41 @@ Möchten Sie trotzdem fortsetzen?</translation>
<translation>ungültig</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>%1 kann nicht installiert werden. Die Komponente ist Nachkomme einer virtuellen Komponente %2.
-</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>%1 kann nicht installiert werden. Die Komponente ist Nachkomme einer virtuellen Komponente %2.</translation>
</message>
<message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation>Die geschätzte Größe des Installers von %1 würde die unterstützte maximale Größe ausführbarer Dateien überschreiten. Die Anwendung könnte möglicherweise nicht ausgeführt werden.</translation>
</message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>Zu löschende Komponenten:</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>Komponente %1 kann nicht installiert werden. Es gab ein Problem beim Laden, daher wird sie als instabil gekennzeichnet und kann nicht ausgewählt werden.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>Es gibt nicht ausreichend Plattenplatz, um die temporären Dateien zu speichern! %1 sind verfügbar, aber das erforderliche Minimum ist %2. Sie können einen anderen Speicherort für die temporären Dateien auswählen, indem Sie den lokalen Cache-Pfad in den Installationseinstellungen ändern.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Die zu deinstallierenden Komponenten konnten nicht aufgelöst werden.</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>Der Alias %1 kann nicht ausgewählt werden. Beim Laden trat ein Problem auf; er wurde daher als instabil gekennzeichnet und kann nicht ausgewählt werden.</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>Der Alias %1 kann nicht ausgewählt werden. Er ist als virtuell gekennzeichnet und kann nicht daher nicht manuell ausgewählt werden.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>Der erstellte Installer wird %1 Festplattenplatz verwenden.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCorePrivate</name>
@@ -1927,16 +2006,12 @@ Möchten Sie trotzdem fortsetzen?</translation>
<translation>Temporäre Datei &quot;%1&quot; konnte nicht entfernt werden: %2</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Installation abgeschlossen!</translation>
+ <source>Installation finished!</source>
+ <translation>Installation abgeschlossen!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Installation abgebrochen!</translation>
+ <source>Installation aborted!</source>
+ <translation>Installation abgebrochen!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1947,16 +2022,12 @@ Installation abgebrochen!</translation>
<translation>Abgewählte Komponenten werden entfernt ...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Aktualisierung beendet!</translation>
+ <source>Update finished!</source>
+ <translation>Aktualisierung beendet!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Aktualisierung abgebrochen!</translation>
+ <source>Update aborted!</source>
+ <translation>Aktualisierung abgebrochen!</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1999,10 +2070,8 @@ Aktualisierung abgebrochen!</translation>
<translation>Offline-Generierung abgebrochen!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Komponente %1 wird installiert</translation>
+ <source>Installing component %1</source>
+ <translation>Komponente %1 wird installiert</translation>
</message>
<message>
<source>Installer Error</source>
@@ -2049,10 +2118,6 @@ Komponente %1 wird installiert</translation>
<translation>Konnte die Metainformationen nicht empfangen: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Konnte Informationen nicht zu temporären Aktualisierungsquellen hinzufügen.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Konnte keine Informationen zu Aktualisierungsquellen finden.</translation>
</message>
@@ -2060,6 +2125,50 @@ Komponente %1 wird installiert</translation>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>Zyklische Abhängigkeit zwischen Komponenten entdeckt: &apos;%1&apos; und &apos;%2&apos;.</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>Bereite Auspacken der Komponenten vor...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%1 von %2 Schritten fertiggestellt.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>Packe Komponenten aus...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 von %2 Schritten rückgängig gemacht.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>Rückgängigmachen erfolgreich abgeschlossen.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%1 von %2 Komponenten installiert.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>Alle Komponenten installiert.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>Lade Komponenten-Skripte...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>Der Alias verwendet einen Namen, der mit der bereits existierenden Komponte &quot;%1&quot; kollidiert</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>Unaufgelöste Komponenten-Aliasse</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>Es wurde eine zyklische Abhängigkeit zwischen den Aliassen &quot;%1&quot; und &quot;%2&quot; festgestellt.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2096,7 +2205,7 @@ Komponente %1 wird installiert</translation>
<translation>%1 Frage</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
@@ -2163,6 +2272,18 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<source>Uninstalling</source>
<translation>Wird deinstalliert</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>Offline-Installer &amp;Erstellen</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>Erstelle Offline-Installer für %1</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>Erstelle Offline-Installer</translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2213,7 +2334,7 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<translation>Bereit zum Deinstallieren</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Das Einrichtungsprogramm ist jetzt bereit, %1 von Ihrem Computer zu entfernen. &lt;br&gt;&lt;font color=&quot;red&quot;&gt;Das Programmverzeichnis %2 wird vollständig gelöscht&lt;/font&gt;, inklusive allen Inhalten in diesem Verzeichnis!</translation>
</message>
<message>
@@ -2225,7 +2346,7 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<translation>Bereit zum Aktualisieren der Pakete</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>Das Einrichtungsprogramm ist jetzt bereit, Ihre Installation zu aktualisieren.</translation>
</message>
<message>
@@ -2237,13 +2358,25 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<translation>Bereit zum Installieren</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Das Einrichtungsprogramm ist jetzt bereit, %1 auf Ihrem Computer zu installieren.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>Bereit für Aktualisierung</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Offline-Installer Erstellen</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>Bereit zum Erstellen des Offline-Installers</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>Die erforderlichen Informationen zum Erstellen eines Offline-Installers für die ausgewählten Komponenten stehen bereit.</translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2300,7 +2433,7 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Der %1-Assistent wird abgeschlossen</translation>
</message>
</context>
@@ -2524,6 +2657,14 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>Bitte stellen Sie sicher, dass der aktuelle Benutzer Lesezugriff auf die Datei &quot;%1&quot; hat oder versuchen Sie, %2 als Administrator auszuführen.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>Ungültiger Wert für &apos;max-concurrent-operations&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>Leerer Wert für Option &apos;Cache-Pfad&apos;.</translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2567,8 +2708,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>Konnte Einstellungsdatei %1 nicht zum Lesen öffnen: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>Kategorien auswählen</translation>
+ <source>Categories</source>
+ <translation>Kategorien</translation>
</message>
</context>
<context>
@@ -2705,6 +2846,30 @@ or accept the elevation of access rights if being asked.</source>
<source>Deselect All</source>
<translation>Alle abwählen</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>Lokaler Cache</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>Die Meta-Information der entfernten Repositories wird auf der Festplatte zwischengespeichert, um die Ladezeiten zu verbessern. Sie können ein anderes Verzeichnis für diesen Cache festlegen oder den Inhalt des aktuellen Caches löschen.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>Pfad für Cache:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>Löscht den Inhalt des Cache-Verzeichnisses</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>Cache löschen</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>Lösche Cache...</translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2766,20 +2931,178 @@ or accept the elevation of access rights if being asked.</source>
<translation>Konnte Archiv &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation>Fehler beim Lesen des Inhaltes des Archivs &quot;%1&quot;: %2</translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Fehler beim Auspacken von &quot;%1&quot;: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation>Datei &quot;%1&quot; konnte nicht vorbereitet werden</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Archiv konnte nicht zum Lesen geöffnet werden: %1</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation>Auspacken des Archives &quot;%1&quot; abgebrochen.</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>Der Kopf des Eintrages konnte nicht gelesen werden: %1</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Fehler beim Auspacken von &quot;%1&quot;: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Der Eintrag &quot;%1&quot; konnte nicht auf die Festplatte geschrieben werden: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Archiv konnte nicht zum Lesen geöffnet werden: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>Der Kopf des Eintrages konnte nicht gelesen werden: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Der Eintrag &quot;%1&quot; konnte nicht auf die Festplatte geschrieben werden: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Schreiben öffnen: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>Der Kopf des Eintrags &quot;%1&quot; konnte nicht auf die Festplatte geschrieben werden: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>Abgewählte Komponenten</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>Durch &quot;%1&quot; ersetzte Komponenten:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>Entferne virtuelle Komponenten ohne existierende Abhängigkeiten:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>Abhängigkeit der Komponente &apos;%1&apos; entfernt:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>Automatische Abhängigkeit der Komponente &apos;%1&apos; entfernt:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>Über %1 Installationswerkzeug</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>Über %1 Verwaltungswerkzeug</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>Der Cache kann nicht mit einem leeren Pfad initialisiert werden.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>Das Verzeichnis %1 für den Cache konnte nicht angelegt werden.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>Cache kann nicht initialisiert werden: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>Ungültiger Cache kann nicht gelöscht werden.</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>Manifest-Datei kann nicht gelöscht werden: %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>Fehler beim Löschen des Caches: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>Es können keine Elemente vom ungültigem Cache geholt werden.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>Es kann kein Element vom ungültigem Cache geholt werden.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>Es kann kein Element im ungültigem Cache registriert werden.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>Leeres Element kann nicht registriert werden.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>Ungültiges Element mit Prüfsumme %1 kann nicht registriert werden.</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>Das Element mit der Prüfsumme %1 kann nicht registriert werden. Es existiert bereits ein Element mit der gleichen Prüfsumme im Cache.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>Fehler beim Kopieren eines Elements in das Verzeichnis &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>Es kann kein Element aus dem ungültigem Cache entfernt werden.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>Das Element mit der Prüfsumme %1 kann nicht gelöscht werden: Das Element existiert nicht.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>Fehler beim Löschen des Verzeichnisses &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>Fehler beim Markieren des Caches als ungültig: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>Manifest-Datei kann nicht geöffnet werden: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>Der Inhalt der Manifest-Datei konnte nicht geschrieben werden: %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>Ungültiger Cache kann nicht synchronisiert werden.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>Unbekannter Registrierungsmodus ausgewählt!</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>Cache wurde erfolgreich gelöscht!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_es.ts b/src/sdk/translations/ifw_es.ts
index 7b9ba7670..a0dad98f9 100644
--- a/src/sdk/translations/ifw_es.ts
+++ b/src/sdk/translations/ifw_es.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>No se puede encontrar la dependencia &quot;%1&quot; que falta para &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>Resolución de dependencia imposible detectada. El componente de instalación forzada &quot;%1&quot; se desinstalaría porque su dependencia &quot;%2&quot; está marcada para desinstalación con el motivo: &quot;%3&quot;.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>Compoentes seleccionados por el alias &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>Recursión detectada, el alias del componente &quot;%1&quot; ya se agregó.</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -306,6 +318,10 @@
<source>Try again</source>
<translation>Volver a intentar</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>No se puede descargar %1. No se puede crear el directorio para &quot;%2&quot;</translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -489,10 +505,6 @@
<translation>No se puede leer &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Error de análisis en %1 en %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Elemento raíz %1 inesperado, debería ser &quot;Updates&quot;.</translation>
</message>
@@ -744,6 +756,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>Contenido inválido en &quot;%1&quot;.</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>Esto puede solucionarse reiniciando la aplicación después de borrar el caché de:</translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -752,18 +768,6 @@
<translation>Los componentes no pueden tener elementos secundarios en el modo actualizador.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>No se puede abrir el archivo de UI &quot;%1&quot; solicitado: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>No se puede cargar el archivo de UI &quot;%1&quot; solicitado: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>No se puede abrir el archivo de licencia &quot;%1&quot; solicitado: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Error</translation>
</message>
@@ -783,6 +787,30 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>Se ha producido un error cargando el componente seleccionado. Este componente no se puede instalar.</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>No se puede abrir el archivo de UI &quot;%1&quot; solicitado: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>No se puede cargar el archivo de UI &quot;%1&quot; solicitado: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>No se puede abrir el archivo de licencia &quot;%1&quot; solicitado: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -830,62 +858,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>Predetermin&amp;ado</translation>
+ <source>Default</source>
+ <translation>Predeterminado</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>Selecciona los componentes predeterminados en la vista de árbol.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Restablecer</translation>
+ <source>Reset</source>
+ <translation>Restablecer</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>Restablece todos los componentes a su estado de selección original en la vista de árbol.</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>&amp;Seleccionar todo</translation>
+ <source>Select All</source>
+ <translation>Seleccionar todo</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>Selecciona todos los componentes en la vista de árbol.</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>Anular selección de to&amp;do</translation>
+ <source>Deselect All</source>
+ <translation>Anular selección de todo</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>Anula la selección de todos los componentes en la vista de árbol.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Examinar archivos QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>Selecciona un archivo de paquete de soporte de Qt Board para instalar contenido adicional que no esté disponible directamente en los repositorios en línea.</translation>
</message>
@@ -918,13 +922,37 @@
<translation>Seleccione los componentes que desea desinstalar.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Seleccione los componentes que desea instalar. Anule la selección de los componentes instalados para desinstalarlos. No se actualizarán los componentes ya instalados.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Seleccione los componentes que desea instalar. Anule la selección de los componentes instalados para desinstalarlos.&lt;br&gt;No se actualizarán los componentes ya instalados.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>Los componentes obligatorios deben actualizarse primero antes de poder seleccionar otros componentes para actualizarlos.</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>Buscar</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Examinar archivos &amp;QBSP</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>Seleccionar</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Crear instalador sin conexión</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>Crea un instalador sin conexión a partir de componentes seleccionados, en lugar de instalarlo ahora.</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -941,12 +969,8 @@
<translation>No se puede guardar la salida de &quot;%1&quot; en un valor de clave de instalador vacío.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>El archivo &quot;%1&quot; no existe o no es un binario ejecutable.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Se ha producido un error al ejecutar &quot;%1&quot;.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>No se pudo ejecutar el comando: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -1087,6 +1111,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>No se puede crear el archivo &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Archivo &quot;%1&quot; no soportado: ningún controlador registrado para el sufijo de archivo &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1203,6 +1231,10 @@ Error al descargar %2</translation>
<source>Total: </source>
<translation>Total: </translation>
</message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>Se superó el recuento de reintentos (%1)</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1340,7 +1372,7 @@ Error al descargar %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Completando el Asistente de %1</translation>
</message>
<message>
@@ -1348,7 +1380,7 @@ Error al descargar %2</translation>
<translation>Terminado</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Haga clic en %1 para salir del asistente de %2.</translation>
</message>
<message>
@@ -1360,7 +1392,7 @@ Error al descargar %2</translation>
<translation>Ejecute %1 ahora.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Error del Asistente de %1.</translation>
</message>
</context>
@@ -1401,15 +1433,19 @@ Error al descargar %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>No se puede crear el directorio &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>No se puede preparar para hacer hacer una copia de seguridad del archivo &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Programa de instalación - %1</translation>
+ <source>Welcome</source>
+ <translation>Bienvenido</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Bienvenido al Asistente de instalación de %1.</translation>
</message>
<message>
@@ -1437,10 +1473,6 @@ Error al descargar %2</translation>
<translation>No hay actualizaciones disponibles.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Solo está disponible la administración de paquetes locales.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Salir</translation>
</message>
@@ -1491,10 +1523,6 @@ Error al descargar %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>No se puede escribir en el archivo de licencia &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>No se han encontrado archivos de licencia para eliminar.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1518,10 +1546,6 @@ Error al descargar %2</translation>
<translation>Falta el motor de componente básico del administrador de paquetes.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Preparando la descarga de la información de metadatos...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Desempaquetando los repositorios comprimidos. Esta operación puede tardar...</translation>
</message>
@@ -1558,14 +1582,6 @@ Error al descargar %2</translation>
<translation>Discrepancia de suma de comprobación detectada para &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Recuperando información de metadatos del repositorio remoto... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Recuperando información de metadatos del repositorio remoto... </translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>Error al extraer el archivo &quot;%1&quot;: %2</translation>
</message>
@@ -1573,6 +1589,45 @@ Error al descargar %2</translation>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>No se puede abrir el archivo &quot;%1&quot; para la lectura: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Archivo &quot;%1&quot; no soportado: ningún controlador registrado para el sufijo de archivo &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>Obteniendo la información de la última actualización...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>Actualizando caché local con %n elemento nuevo...</numerusform>
+ <numerusform>Actualizando caché local con %n elementos nuevos...</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>Borrando el directorio de caché y reiniciando la aplicación puede resolver esto.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Excepción desconocida durante la actualización de caché.</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>No se puede abrir el archivo extraído &quot;%1&quot; para leer: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>No se puede abrir el archivo &apos;%1&apos; para la escritura: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Recuperando información de repositorios remotos...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Recuperando información de metadatos del repositorio remoto...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1581,10 +1636,8 @@ Error al descargar %2</translation>
<translation>Error al escribir la herramienta de mantenimiento</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Descargando paquetes...</translation>
+ <source>Downloading packages...</source>
+ <translation>Descargando paquetes...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1693,42 +1746,24 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
<translation>No se pueden resolver todas las dependencias.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Componentes que están a punto de eliminarse.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>No se puede instalar el componente %1. El componente se instala sólo como dependencia automática de %2.
-</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>No se puede instalar el componente %1. El componente no es seleccionable, lo que significa que tiene que seleccionar uno de los subcomponentes.
-</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>No se puede instalar el componente %1. El componente se instala sólo como dependencia automática de %2.</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>El componente %1 ya está instalado
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>No se puede instalar el componente %1. El componente no es seleccionable, lo que significa que tiene que seleccionar uno de los subcomponentes.</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>No se puede instalar %1. El componente es virtual.
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>El componente %1 ya está instalado</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>No se puede instalar %1. No se encuentra el componente.
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>No se puede instalar %1. El componente es virtual.</translation>
</message>
<message>
- <source>Running processes found.</source>
- <translation>Se han encontrado procesos en ejecución.</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>No se puede instalar %1. No se encuentra el componente.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1751,10 +1786,6 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
<translation>No hay suficiente espacio en disco para almacenar todos los componentes seleccionados. Se dispone de %1 y se requiere al menos un espacio de %2.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>No hay suficiente espacio en disco para almacenar los archivos temporales. Se dispone de %1 y se requiere al menos un espacio de %2.</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>El volumen seleccionado para la instalación parece tener espacio suficiente para la instalación, pero después habrá menos del 1% del espacio del volumen disponible.</translation>
</message>
@@ -1775,19 +1806,41 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
<translation>Se requiere la entrada del usuario pero el dispositivo de salida no está asociado a un terminal.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>No se puede registrar el componente. El componente con el identificador %1 ya existe.</translation>
- </message>
- <message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>No se puede instalar %1. El componente es descendiente de un componente virtual %2.
-</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>No se puede instalar %1. El componente es descendiente de un componente virtual %2.</translation>
</message>
<message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation>El tamaño estimado del instalador %1 exederá el límite del tamaño del ejecutable soportado de %2. Puede que la aplicación no se ejecute.</translation>
</message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>Componentes a punto de ser removidos:</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>No se puede instalar el componente %1. Hubo un problema al cargar este componente, por lo que está marcado como inestable y no se puede seleccionar.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>¡No hay suficiente espacio en disco para almacenar archivos temporales! %1 están disponibles, mientras que el mínimo requerido es %2. Puede seleccionar otra ubicación para los archivos temporales modificando la ruta de caché local desde la configuración del instalador.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>No se pueden resolver los componentes para desinstalar.</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>No se puede seleccionar el alias %1. Hubo un problema al cargar este alias, por lo que está marcado como inestable y no se puede seleccionar.</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>No se puede seleccionar %1. El alias está marcado como virtual, lo que significa que no se puede seleccionar manualmente.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>El instalador creado utilizará %1 del espacio en disco.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCorePrivate</name>
@@ -1904,16 +1957,12 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
<translation>Creando herramienta de mantenimiento</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Instalación completada.</translation>
+ <source>Installation finished!</source>
+ <translation>Instalación completada.</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Instalación cancelada.</translation>
+ <source>Installation aborted!</source>
+ <translation>Instalación cancelada.</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1924,16 +1973,12 @@ Instalación cancelada.</translation>
<translation>Eliminando componentes anulados de la selección...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Actualización completada.</translation>
+ <source>Update finished!</source>
+ <translation>Actualización completada.</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Actualización cancelada.</translation>
+ <source>Update aborted!</source>
+ <translation>Actualización cancelada.</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1976,10 +2021,8 @@ Actualización cancelada.</translation>
<translation>¡Generación fuera de línea cancelada!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Instalando componente %1</translation>
+ <source>Installing component %1</source>
+ <translation>Instalando componente %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -2026,10 +2069,6 @@ Instalando componente %1</translation>
<translation>No se puede recuperar la información de los metadatos: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>No se puede agregar la información de la fuente de actualización temporal.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>No se puede encontrar ninguna información de fuente de actualización.</translation>
</message>
@@ -2037,6 +2076,50 @@ Instalando componente %1</translation>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>Se ha detectado un ciclo de dependencia entre componentes los &quot;%1&quot; y &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>Preparándose para desempaquetar componentes...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%1 de %2 operaciones completadas.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>Desempaquetando componentes...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 de %2 operaciones revertidas.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>Reversiones completadas.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%1 de %2 componentes instalados.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>Todos los componentes fueron instalados.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>Cargando scripts de componentes...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>El alias declara un nombre que entra en conflicto con un componente existente &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>Alias de componentes no resueltos</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>Se detectó dependencia cíclica entre los alias &quot;%1&quot; y &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2073,7 +2156,7 @@ Instalando componente %1</translation>
<translation>%1 pregunta</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Configuración</translation>
</message>
<message>
@@ -2140,6 +2223,18 @@ Copie el instalador en una unidad local</translation>
<source>Uninstalling</source>
<translation>Desinstalando</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>&amp;Crear instalador sin conexión</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>Creando un instalador sin conexión para %1</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>Creando un instalador sin conexión</translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2183,7 +2278,7 @@ Copie el instalador en una unidad local</translation>
<translation>Preparado para desinstalar</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>El programa de instalación está preparado para empezar a eliminar %1 del equipo.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;El directorio del programa %2 se eliminará completamente&lt;/font&gt;, incluido todo el contenido del directorio.</translation>
</message>
<message>
@@ -2195,7 +2290,7 @@ Copie el instalador en una unidad local</translation>
<translation>Preparado para actualizar paquetes</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>El programa de instalación está preparado para empezar a actualizar la instalación.</translation>
</message>
<message>
@@ -2207,13 +2302,25 @@ Copie el instalador en una unidad local</translation>
<translation>Preparado para instalar</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>El programa de instalación está preparado para empezar a instalar %1 en su equipo.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>Listo para la actualización</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Crear instalador sin conexión</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>Listo para crear instalador sin conexión</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>Toda la información requerida ahora está disponible para crear un instalador sin conexión para los componentes seleccionados.</translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2270,7 +2377,7 @@ Copie el instalador en una unidad local</translation>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Completando el Asistente de instalación de %1</translation>
</message>
</context>
@@ -2493,6 +2600,14 @@ Copie el instalador en una unidad local</translation>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>Veuillez veiller à ce que l’utilisateur actuel dispose d’un accès en lecture au fichier &amp;amp;quot;%1&amp;amp;quot; ou essayez d’exécuter %2 en tant qu’administrateur.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>Valor inválido para &apos;max-concurrent-operations&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>Valor vacío para la opción &apos;cache-path&apos;.</translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2539,8 +2654,8 @@ O bien acepte la elevación de los derechos de acceso si se le pide.</translatio
<translation>No se puede abrir el archivo de configuración %1 para la lectura: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>Seleccione las categorías</translation>
+ <source>Categories</source>
+ <translation>Categorías</translation>
</message>
</context>
<context>
@@ -2677,6 +2792,30 @@ O bien acepte la elevación de los derechos de acceso si se le pide.</translatio
<source>Deselect All</source>
<translation>Anular seleccionar todo</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>Caché local</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>La metainformación de los repositorios remotos se almacena en caché en el disco para mejorar los tiempos de carga. Puede seleccionar otro directorio para almacenar el caché o borrar el contenido del caché actual.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>Ruta para el caché:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>Elimina el contenido del directorio de caché</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>Limpiar cache</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>Limpiando caché...</translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2738,8 +2877,8 @@ O bien acepte la elevación de los derechos de acceso si se le pide.</translatio
<translation>Error</translation>
</message>
<message>
- <source>Component Information</source>
- <translation>Información de componentes</translation>
+ <source>Information</source>
+ <translation>Información</translation>
</message>
</context>
<context>
@@ -2748,6 +2887,22 @@ O bien acepte la elevación de los derechos de acceso si se le pide.</translatio
<source>Extracting &quot;%1&quot;</source>
<translation>Extrayendo &quot;%1&quot;</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Archivo &quot;%1&quot; no soportado: ningún controlador registrado para el sufijo de archivo &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>No se puede abrir el archivo &quot;%1&quot; para la lectura: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Error al leer el contenido del archivo &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Eliminando archivos extraídos desde &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2767,20 +2922,178 @@ O bien acepte la elevación de los derechos de acceso si se le pide.</translatio
<translation>No se puede abrir el archivo &quot;%1&quot; para la lectura: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation>Error al leer el contenido del archivo &quot;%1&quot;: %2</translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Error al extraer el archivo &quot;%1&quot;: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation>No se puede preprar para el archivo &quot;%1&quot;</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>No se puede abrir archivo para lectura: %1</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation>La extracción para el archivo &quot;%1&quot; fue cancelada.</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>No se puede leer la entrada de la cabecera: %1</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Error al extraer el archivo &quot;%1&quot;: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>No se puede escribir la entrada &quot;%1&quot; al disco: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>No se puede abrir el archivo para lectura: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>No se puede leer la entrada de la cabecera: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>No se puede escribir la entrada &quot;%1&quot; al disco: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>No se puede abrir el archivo &apos;%1&apos; para la escritura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>No se puede abrir el archivo &quot;%1&quot; para la lectura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>No se puede escribir la entrada de la cabecera para &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>Componentes deseleccionados:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>Componentes reemplazados por &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>Eliminando componentes virtuales sin dependencias existentes:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>Dependencias del componente &quot;%1&quot; eliminadas:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>Auto dependencias de los componentes &quot;%1&quot;; eliminadas:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>Acerca el instalador %1</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>Acerca herramienta de mantención %1</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>No se puede inicializar el caché con la ruta vacía.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>No se puede crear el directorio &quot;%1&quot; para la memoria caché.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>No se puede inicializar el caché: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>No se puede borrar el caché invalidado.</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>No se puede eliminar el archivo de manifiesto: %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>Error al borrar el caché: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>No se pueden recuperar elementos de la memoria caché invalidada.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>No se puede recuperar el elemento de la memoria caché invalidada.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>No se puede registrar el elemento en la memoria caché invalidada.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>No se puede registrar un artículo nulo.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>No se puede registrar un artículo no válido con la suma de verificación %1</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>No se puede registrar el elemento con la suma de verificación %1. Ya existe un elemento con la misma suma de comprobación en la memoria caché.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>Error al copiar el elemento a la ruta &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>No se puede eliminar el elemento de la memoria caché invalidada.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>No se puede eliminar el elemento especificado por la suma de comprobación %1: no existe tal elemento.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>Error al eliminar el directorio &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>Error al invalidar caché: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>No se puede abrir el archivo de manifiesto: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>No se puede escribir el contenido del archivo de manifiesto: %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>No se puede sincronizar el caché invalidado.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>¡Modo de registro desconocido seleccionado!</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>¡Caché borrada con éxito!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_fr.ts b/src/sdk/translations/ifw_fr.ts
index 582b4ed81..2f2bd5bf5 100644
--- a/src/sdk/translations/ifw_fr.ts
+++ b/src/sdk/translations/ifw_fr.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>La dépendance manquante &quot;%1&quot; est introuvable pour &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>Résolution de dépendance impossible détectée. Le composant dont l&apos;installation est forcée &quot;%1&quot; serait désinstallé car sa dépendance &quot;%2&quot; est marquée pour désinstallation avec la raison : &quot;%3&quot;.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>Composants sélectionnés par alias &quot;%1&quot; :</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>Récursion détectée, componsant alias &quot;%1&quot; déjà ajouté.</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -306,6 +318,10 @@
<source>Try again</source>
<translation>Réessayez</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>Impossible de télécharger %1. Impossible de créer le répertoire pour &quot;%2&quot;</translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -489,10 +505,6 @@
<translation>Impossible de lire &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Erreur d’analyse dans %1 sur %2, %3 : %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Élément racine %1 inattendu, il doit s’agir de &quot;Updates&quot;.</translation>
</message>
@@ -744,6 +756,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>Contenu invalide dans &quot;%1&quot;.</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>Le problème peut être résolu en redémarrant l&apos;application après avoir vidé le cache de :</translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -752,18 +768,6 @@
<translation>Les composants ne peuvent pas comporter d’enfants en mode de mise à jour.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Impossible d’ouvrir le fichier d’interface utilisateur demandé &quot;%1&quot; : %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Impossible de charger le fichier d’interface utilisateur demandé &quot;%1&quot; : %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Impossible d’ouvrir le fichier de licence demandé &quot;%1&quot; : %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Erreur</translation>
</message>
@@ -783,6 +787,30 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>Une erreur s&amp;apos;est produite lors du chargement du composant sélectionné. Ce composant ne peut pas être installé.</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Impossible d’ouvrir le fichier d’interface utilisateur demandé &quot;%1&quot; : %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Impossible de charger le fichier d’interface utilisateur demandé &quot;%1&quot; : %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Impossible d’ouvrir le fichier de licence demandé &quot;%1&quot; : %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -830,62 +858,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>Par déf&amp;aut</translation>
+ <source>Default</source>
+ <translation>Par défaut</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>Sélectionner les composants par défaut dans l&apos;arborescence.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Réinitialiser</translation>
+ <source>Reset</source>
+ <translation>Réinitialiser</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>Réinitialiser tous les composants à leur état de sélection d&apos;origine dans l&apos;arborescence.</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>&amp;Sélectionner tout</translation>
+ <source>Select All</source>
+ <translation>Sélectionner tout</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>Sélectionner tous les composants dans l&apos;arborescence.</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Tout désélectionner</translation>
+ <source>Deselect All</source>
+ <translation>Tout désélectionner</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>Désélectionner tous les composants dans l&apos;arborescence.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Parcourir les fichiers QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>Sélectionner un fichier Qt Board Support Package pour installer du contenu supplémentaire qui n&apos;est pas directement disponible à partir des référentiels en ligne.</translation>
</message>
@@ -918,13 +922,37 @@
<translation>Sélectionnez les composants que vous souhaitez désinstaller.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Sélectionnez les composants à installer. Désélectionnez les composants installés pour les désinstaller. Les composants déjà installés ne seront pas mis à jour.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Sélectionnez les composants à installer. Désélectionnez les composants installés pour les désinstaller.&lt;br&gt;Les composants déjà installés ne seront pas mis à jour.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>Les composants obligatoires doivent d&apos;abord être mis à jour avant de pouvoir sélectionner d&apos;autres composants à mettre à jour.</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>Recherche</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Parcourir les fichiers QBSP</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>Sélectionner</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erreur</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Créer un programme d’installation hors ligne</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>Créer un programme d’installation hors ligne à partir des composants sélectionnés, au lieu d&apos;installer maintenant.</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -941,12 +969,8 @@
<translation>Impossible d’enregistrer la sortie de &quot;%1&quot; dans une valeur clé du programme d’installation vide.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Le fichier &quot;%1&quot; n’existe pas ou n’est pas un objet binaire exécutable.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>L’exécution de &quot;%1&quot; a entraîné un blocage.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>Echec d&apos;exécution de la commande : &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -1087,6 +1111,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>Impossible de créer l’archive &quot;%1&quot; : %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Archive non prise en charge &quot;%1&quot;: pas de gestionnaire enregistré pour les fichiers avec suffixe &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1122,14 +1150,6 @@
<translation>Erreur de téléchargement</translation>
</message>
<message>
- <source>Hash verification while downloading failed. This is a temporary error, please retry.</source>
- <translation>La vérification du hachage lors du téléchargement a échoué. Cette erreur est temporaire, réessayez.</translation>
- </message>
- <message>
- <source>Cannot verify Hash</source>
- <translation>Impossible de vérifier le hachage</translation>
- </message>
- <message>
<source>Cannot download archive %1: %2</source>
<translation>Impossible de télécharger l’archive %1 : %2</translation>
</message>
@@ -1203,6 +1223,28 @@ Erreur lors du chargement de %2</translation>
<source>Total: </source>
<translation>Total: </translation>
</message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>Nombre de tentatives (%1) dépassé</translation>
+ </message>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.
+
+Expected: %1
+Downloaded: %2</source>
+ <translation>La vérification du hachage lors du téléchargement a échoué. Cette erreur est temporaire, réessayez.
+
+Attendu: %1
+Téléchargé: %2</translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash
+Expected: %1
+Downloaded: %2</source>
+ <translation>Impossible de vérifier le hachage
+Attendu: %1
+Téléchargé: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1340,7 +1382,7 @@ Erreur lors du chargement de %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Exécution de l’assistant de %1</translation>
</message>
<message>
@@ -1348,7 +1390,7 @@ Erreur lors du chargement de %2</translation>
<translation>Terminé</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Cliquez sur %1 pour quitter l’assistant de %2.</translation>
</message>
<message>
@@ -1360,7 +1402,7 @@ Erreur lors du chargement de %2</translation>
<translation>Exécutez %1 maintenant.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>L’assistant de %1 a échoué.</translation>
</message>
</context>
@@ -1401,15 +1443,19 @@ Erreur lors du chargement de %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Impossible de créer le répertoire &quot;%1&quot; : %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>Impossible de préparer le fichier de sauvegarder &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Installation - %1</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Bienvenue dans l’assistant d’installation de %1</translation>
</message>
<message>
@@ -1437,10 +1483,6 @@ Erreur lors du chargement de %2</translation>
<translation>Aucune mise à jour disponible.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Seule la gestion des paquetages locaux est disponible.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Quitter</translation>
</message>
@@ -1491,10 +1533,6 @@ Erreur lors du chargement de %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Impossible d’écrire le fichier de licence &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Aucun fichier de licence à supprimer.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1518,10 +1556,6 @@ Erreur lors du chargement de %2</translation>
<translation>Moteur principal du gestionnaire de paquetages manquant.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Préparation du téléchargement des métadonnées...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Décompression des référentiels compressés. Cette opération peut prendre du temps...</translation>
</message>
@@ -1558,14 +1592,6 @@ Erreur lors du chargement de %2</translation>
<translation>Non-concordance des sommes de contrôle détectée pour &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Extraction des métadonnées depuis le référentiel distant... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Extraction des métadonnées depuis le référentiel distant... </translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>Erreur lors de l’extraction de l’archive &quot;%1&quot; : %2</translation>
</message>
@@ -1573,6 +1599,45 @@ Erreur lors du chargement de %2</translation>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>Impossible d’ouvrir le fichier &quot;%1&quot; en lecture : %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Archive non prise en charge &quot;%1&quot;: pas de gestionnaire enregistré pour les fichiers avec suffixe &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>Récuperation des dernières informations de mise a jour...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>Mise à jour du cache local avec %n nouvel élément...</numerusform>
+ <numerusform>Mise à jour du cache local avec %n nouveaux éléments</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>Effacer le répertoire de cache et redémarrer l&apos;application peut résoudre ce problème.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Exception inconnue lors de la mise à jour du cache.</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>Impossible d&apos;ouvrir le fichier extrait &quot;%1&quot; en lecture : %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Impossible d’ouvrir le fichier &quot;%1&quot; en écriture : %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Extraction des informations depuis le référentiels distants...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Extraction des métadonnées depuis le référentiel distant...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1581,10 +1646,8 @@ Erreur lors du chargement de %2</translation>
<translation>Erreur d’écriture de l’outil de maintenance</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Téléchargement des paquetages...</translation>
+ <source>Downloading packages...</source>
+ <translation>Téléchargement des paquetages...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1693,42 +1756,24 @@ Souhaitez-vous continuer ?</translation>
<translation>Impossible de résoudre toutes les dépendances.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Les composants vont être supprimés.</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>Impossible d&apos;installer le composant %1. Le composant est installé uniquement en tant que dépendance automatique à %2.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>Impossible d&apos;installer le composant %1. Le composant est installé uniquement en tant que dépendance automatique à %2.
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>Impossible d&apos;installer le composant %1. Le composant ne peut pas être coché, ce qui signifie que vous devez sélectionner l&apos;un des sous-composants.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>Impossible d&apos;installer le composant %1. Le composant ne peut pas être coché, ce qui signifie que vous devez sélectionner l&apos;un des sous-composants.
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>Composant %1 déjà installé</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>Composant %1 déjà installé
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>Impossible d&apos;installer %1. Le composant est virtuel.</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>Impossible d&apos;installer %1. Le composant est virtuel.
-</translation>
- </message>
- <message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>Impossible d&apos;installer le composant %1. Composant introuvable.
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>Processus en cours trouvés.</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>Impossible d&apos;installer le composant %1. Composant introuvable.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1751,10 +1796,6 @@ Souhaitez-vous continuer ?</translation>
<translation>L’espace disque est insuffisant pour stocker tous les composants sélectionnés ! %1 sont disponibles, alors qu’au moins %2 sont nécessaires.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>L’espace disque est insuffisant pour stocker les fichiers temporaires ! %1 sont disponibles, alors qu’au moins %2 sont nécessaires.</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>Le volume que vous avez sélectionné pour l&apos;installation semble avoir suffisamment d&apos;espace pour l&apos;installation, mais il restera moins de 1% de l&apos;espace du volume disponible par la suite.</translation>
</message>
@@ -1775,18 +1816,40 @@ Souhaitez-vous continuer ?</translation>
<translation>Une saisie par l’utilisateur est requise mais le périphérique de sortie n&apos;est pas associé à un terminal.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>Impossible d&apos;enregistrer le composant&#xa0;! Le composant avec l&apos;identifiant %1 existe déjà.</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>Impossible d&apos;installer le composant %1. Le composant est le descendant d&apos;un composant virtuel %2.</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>Impossible d&apos;installer le composant %1. Le composant est le descendant d&apos;un composant virtuel %2.
-</translation>
+ <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
+ <translation>La taille estimée de l installeur %1 dépasserait la taille limite de l&apos;exécutable prise en charge %2. L&apos;application pourrait ne pas pouvoir s&apos;exécuter.</translation>
</message>
<message>
- <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
- <translation>La taille estimée de l installeur %1 dépasserait la taille limite de l'exécutable prise en charge %2. L'application pourrait ne pas pouvoir s'exécuter.</translation>
+ <source>Components about to be removed:</source>
+ <translation>Composants sur le point d&apos;être supprimés :</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>Impossible d&apos;installer le composant %1. Un problème est survenu lors du chargement de ce composant, il est donc marqué comme instable et ne peut pas être sélectionné.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>L’espace disque est insuffisant pour stocker les fichiers temporaires ! %1 sont disponibles, alors qu’au moins %2 sont nécessaires. Vous pouvez sélectionner un autre emplacement pour les fichiers temporaires en modifiant le chemin du cache local à partir des paramètres du programme d&apos;installation.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Impossible de résoudre les composants à désinstaller.</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>Impossible de sélectionner l&apos;alias %1. Un problème est survenu lors du chargement de cet alaias, il est donc marqué comme instable et ne peut pas être sélectionné</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>Impossible de sélectionner %1. L&apos;alias est marqué virtuel, ce qui signifie qu&apos;il ne peut pas être sélectionné manuellement.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>Le programme d&apos;installation créé utilisera %1 d&apos;espace disque.</translation>
</message>
</context>
<context>
@@ -1904,16 +1967,12 @@ Souhaitez-vous continuer ?</translation>
<translation>Création d’un outil de maintenance</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Installation terminée !</translation>
+ <source>Installation finished!</source>
+ <translation>Installation terminée !</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Installation annulée !</translation>
+ <source>Installation aborted!</source>
+ <translation>Installation annulée !</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1924,16 +1983,12 @@ Installation annulée !</translation>
<translation>Suppression des composants désélectionnés...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Mise à jour terminée !</translation>
+ <source>Update finished!</source>
+ <translation>Mise à jour terminée !</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Mise à jour annulée !</translation>
+ <source>Update aborted!</source>
+ <translation>Mise à jour annulée !</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1976,10 +2031,8 @@ Mise à jour annulée !</translation>
<translation>Génération hors ligne interrompue !</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Installation du composant %1</translation>
+ <source>Installing component %1</source>
+ <translation>Installation du composant %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -2026,10 +2079,6 @@ Installation du composant %1</translation>
<translation>Impossible d’extraire les métadonnées : %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Impossible d’ajouter des informations sur la source de mise à jour temporaire.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Informations introuvables sur la source de mise à jour.</translation>
</message>
@@ -2037,6 +2086,50 @@ Installation du composant %1</translation>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>Cycle de dépendance entre les composants &quot;%1&quot; et &quot;%2&quot; détecté.</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>Préparation du déballage des composants...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%1 opérations sur %2 terminées.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>Déballage des composants...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 des %2 opérations annulées.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>Annulations terminées.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%1 des %2 composants installés.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>Tous les composants sont installés.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>Chargement des scripts du composant...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>L&apos;alias déclare un nom en conflit avec un composant existant : &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>Alias ​​de composants non résolus</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>Dépendance cyclique entre les alias &quot;%1&quot; et &quot;%2&quot; détectée.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2073,7 +2166,7 @@ Installation du composant %1</translation>
<translation>Question %1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Réglages</translation>
</message>
<message>
@@ -2140,6 +2233,18 @@ Copiez le programme d’installation sur un disque local</translation>
<source>Uninstalling</source>
<translation>Désinstallation</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>&amp;Créer un programme d’installation hors ligne</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>Création d&apos;un programme d’installation hors ligne pour %1</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>Création d&apos;un programme d’installation hors ligne</translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2183,7 +2288,7 @@ Copiez le programme d’installation sur un disque local</translation>
<translation>Prêt pour la désinstallation</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Le programme d’installation est maintenant prêt à supprimer %1 de votre ordinateur.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;Le répertoire du programme %2 va être entièrement supprimé&lt;/font&gt;, y compris tout son contenu !</translation>
</message>
<message>
@@ -2195,7 +2300,7 @@ Copiez le programme d’installation sur un disque local</translation>
<translation>Prêt à mettre à jour les paquetages</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>Le programme d’installation est maintenant prêt à mettre à jour votre installation.</translation>
</message>
<message>
@@ -2207,13 +2312,25 @@ Copiez le programme d’installation sur un disque local</translation>
<translation>Prêt pour l’installation</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Le programme d’installation est maintenant prêt à installer %1 sur votre ordinateur.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>Prêt pour la mise à jour</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Créer un programme d’installation hors ligne</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>Prêt pour la création du programme d’installation hors ligne</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>La création du programme d’installation hors ligne pour les composants sélectionnés est maintenant prête.</translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2270,7 +2387,7 @@ Copiez le programme d’installation sur un disque local</translation>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Exécution de l’assistant d’installation de %1</translation>
</message>
</context>
@@ -2493,6 +2610,14 @@ Copiez le programme d’installation sur un disque local</translation>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>Veuillez veiller à ce que l’utilisateur actuel dispose d’un accès en lecture au fichier &amp;quot;%1&amp;quot; ou essayez d’exécuter %2 en tant qu’administrateur.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>Valeur non valide pour &apos;max-concurrent-operations&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>Valeur vide pour l&apos;option &apos;cache-path&apos;.</translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2541,8 +2666,8 @@ Ou acceptez l’élévation des droits d’accès si un message vous y invite.</
<translation>Impossible d’ouvrir le fichier de paramètres %1 en lecture : %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>Sélectionner les catégories</translation>
+ <source>Categories</source>
+ <translation>Catégories</translation>
</message>
</context>
<context>
@@ -2679,6 +2804,30 @@ Ou acceptez l’élévation des droits d’accès si un message vous y invite.</
<source>Deselect All</source>
<translation>Tout désélectionner</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>Cache local</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>Les méta-informations des référentiels distants sont mises en cache sur le disque pour améliorer les temps de chargement. Vous pouvez sélectionner un autre répertoire pour stocker le cache ou effacer le contenu du cache actuel.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>Chemin d&apos;accès au cache :</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>Supprime le contenu du répertoire cache</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>Vider le cache</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>Vidage du cache...</translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2740,8 +2889,8 @@ Ou acceptez l’élévation des droits d’accès si un message vous y invite.</
<translation>Erreur</translation>
</message>
<message>
- <source>Component Information</source>
- <translation>Informations sur les composants</translation>
+ <source>Information</source>
+ <translation>Informations</translation>
</message>
</context>
<context>
@@ -2750,6 +2899,22 @@ Ou acceptez l’élévation des droits d’accès si un message vous y invite.</
<source>Extracting &quot;%1&quot;</source>
<translation>Extraction de &quot;%1&quot;</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Archive non prise en charge &quot;%1&quot;: pas de gestionnaire enregistré pour les fichiers avec suffixe &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Impossible d’ouvrir l’archive &quot;%1&quot; en lecture : %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Erreur lors de la lecture des contenus de l&apos;archive &quot;%1&quot; : %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Suppression des fichiers extraits de &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2769,20 +2934,178 @@ Ou acceptez l’élévation des droits d’accès si un message vous y invite.</
<translation>Impossible d’ouvrir l’archive &quot;%1&quot; en lecture : %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation>Erreur lors de la lecture des contenus de l'archive &quot;%1&quot; : %2</translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Erreur lors de l’extraction de l’archive &quot;%1&quot; : %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation>Impossible de préparer le fichier &quot;%1&quot;</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Impossible d&apos;ouvrir l&apos;archive en lecture : %1</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation>Extraction pour l'archive &quot;%1&quot; annulée.</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>Impossible de lire l&apos;en-tête de l&apos;entrée : %1</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Erreur lors de l’extraction de l’archive &quot;%1&quot; : %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Impossible d&apos;écrire l&apos;entrée &quot;%1&quot; sur disque : %</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Impossible d&apos;ouvrir l&apos;archive en lecture : %1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>Impossible de lire l&apos;en-tête de l&apos;entrée : %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Impossible d&apos;écrire l&apos;entrée &quot;%1&quot; sur le disque : %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Impossible d&apos;ouvrir le fichier &quot;%1&quot; pour l&apos;écriture : %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Impossible d&apos;ouvrir le fichier &quot;%1&quot;en lecture &quot;%2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>Impossible d&apos;écrire l&apos;en-tête d&apos;entrée pour &quot;%1&quot; : %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>Composants désélectionnés :</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>Composants remplacés par &quot;%1&quot; :</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>Suppression de composants virtuels sans dépendances existantes :</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>Dépendance des composants &quot;%1&quot; supprimé:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>Autodépendance des composants &quot;%1&quot; supprimé:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>À propos du programme d&apos;installation %1</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>À propos de l&apos;outil de maintenance %1</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>Impossible d&apos;initialiser le cache avec un chemin vide.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>Impossible de créer le répertoire &quot;%1&quot; pour le cache.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>Impossible d&apos;initialiser le cache : %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>Impossible d&apos;effacer le cache invalidé.</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>Impossible de supprimer le fichier manifeste : %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>Erreur lors de la suppression du cache : %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>Impossible de récupérer les éléments du cache invalidé.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>Impossible de récupérer l&apos;élément du cache invalidé.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>Impossible d&apos;enregistrer l&apos;élément dans le cache invalidé.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>Impossible d&apos;enregistrer un élément nul.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>Impossible d&apos;enregistrer un élément non valide avec la somme de contrôle %1</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>Impossible d&apos;enregistrer l&apos;élément avec la somme de contrôle %1. Un élément avec la même somme de contrôle existe déjà dans le cache.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>Erreur lors de la copie de l&apos;élément vers le chemin &quot;%1&quot; : %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>Impossible de supprimer l&apos;élément du cache invalidé.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>Impossible de supprimer l&apos;élément spécifié par la somme de contrôle %1 : aucun élément de ce type n&apos;existe.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>Erreur lors de la suppression du répertoire &quot;%1&quot; : %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>Erreur lors de l&apos;invalidation du cache : %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>Impossible d&apos;ouvrir le fichier manifeste : %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>Impossible d&apos;écrire le contenu du fichier manifeste : %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>Impossible de synchroniser le cache invalidé.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>Le mode de registre sélectionné est inconnu !</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>Cache vidé avec succès !</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_hr.ts b/src/sdk/translations/ifw_hr.ts
index fe8d8d808..d219b17f6 100644
--- a/src/sdk/translations/ifw_hr.ts
+++ b/src/sdk/translations/ifw_hr.ts
@@ -202,16 +202,40 @@
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished">Odaberi sve</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished">dznači sav odabir</translation>
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QObject</name>
@@ -271,6 +295,14 @@
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller</name>
@@ -382,6 +414,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>BinaryLayout</name>
@@ -442,18 +478,6 @@
<translation>Komponente nemaju podređenih u modusu aktualiziranja.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Nije moguće otvoriti traženu UI datoteku &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Nije moguće učitati traženu UI datoteku &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Nije moguće otvoriti traženu licencnu datoteku &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Greška</translation>
</message>
@@ -474,8 +498,28 @@
<translation type="unfinished"></translation>
</message>
<message>
- <source>There was an error loading the selected component. This component cannot be updated.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nije moguće otvoriti traženu UI datoteku &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nije moguće učitati traženu UI datoteku &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nije moguće otvoriti traženu licencnu datoteku &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -536,12 +580,8 @@
<translation>Izlaz &quot;%1&quot; nije moguće spremiti u praznu vrijednost ključa programa za instaliranje.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Datoteka &quot;%1&quot; ne postoji ili nije izvršna binarna datoteka.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Pokretanje &quot;%1&quot; je prouzročilo urušavanje.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -678,6 +718,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Nije moguće ukloniti mapu &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>Nije moguće stvoriti arhiv &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -742,6 +790,66 @@ Greška prilikom učitavanja %2</translation>
<source>Cannot find component for %1.</source>
<translation>Nije moguće naći komponentu za %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 od %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>Preuzeto: %1.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dan, </numerusform>
+ <numerusform>%n dana, </numerusform>
+ <numerusform>%n dana, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n sat, </numerusform>
+ <numerusform>%n sata, </numerusform>
+ <numerusform>%n sati, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuta</numerusform>
+ <numerusform>%n minute</numerusform>
+ <numerusform>%n minuta</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> – preostaje %1%2%3%4.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> – nepoznato preostalo vrijeme.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -878,20 +986,21 @@ Greška prilikom učitavanja %2</translation>
<source>Extracting &quot;%1&quot;</source>
<translation>Raspakiravanje &quot;%1&quot;</translation>
</message>
-</context>
-<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
<translation>Nije moguće otvoriti arhivu &quot;%1&quot; za učitavanje: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Greška prilikom raspakiravanja arhive &quot;%1&quot;: %2</translation>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Nepoznata iznimka prilikom raspakiravanja &quot;%1&quot;.</translation>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -946,6 +1055,18 @@ Greška prilikom učitavanja %2</translation>
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Nije moguće naći nedostajuću ovisnost &quot;%1&quot; za &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::InstallIconsOperation</name>
@@ -973,6 +1094,10 @@ Greška prilikom učitavanja %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Nije moguće stvoriti mapu &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Lib7z</name>
@@ -1101,10 +1226,6 @@ Greška prilikom učitavanja %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Nije moguće zapisati licencnu datoteku &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Nema licencnih datoteka za brisanje.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1128,10 +1249,6 @@ Greška prilikom učitavanja %2</translation>
<translation>Nedostaje osnovni uređaj upravljača paketa.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Pripremanje preuzimanja meta informacija …</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Raspakiravanje komprimiranih spremišta. Može ponešto potrajati …</translation>
</message>
@@ -1164,29 +1281,57 @@ Greška prilikom učitavanja %2</translation>
<translation>Ustanovljena je neusklađenost kontrolnog zbroja za &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Dohvaćanje meta informacija s udaljenih spremišta … %1/%2 </translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Greška prilikom raspakiravanja arhive &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nije moguće otvoriti datoteku &quot;%1&quot; za učitavanje: %2</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Dohvaćanje meta informacija s udaljenih spremišta … </translation>
+ <source>Metadata download canceled.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Greška prilikom raspakiravanja arhive &quot;%1&quot;: %2</translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Nepoznata iznimka prilikom raspakiravanja &quot;%1&quot;.</translation>
+ <source>Fetching latest update information...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
<message>
- <source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Nije moguće otvoriti datoteku &quot;%1&quot; za učitavanje: %2</translation>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Metadata download canceled.</source>
+ <source>Unknown exception during updating cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Nije moguće otvoriti datoteku &quot;%1&quot; za zapisivanje: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Dohvaćanje informacija s udaljenih spremišta …</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Dohvaćanje meta informacija s udaljenih spremišta …</translation>
+ </message>
</context>
<context>
<name>QInstaller::FileTaskObserver</name>
@@ -1250,10 +1395,8 @@ Greška prilikom učitavanja %2</translation>
<translation>Greška prilikom pisanja u alat za održavanje</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Preuzimanje paketa …</translation>
+ <source>Downloading packages...</source>
+ <translation>Preuzimanje paketa …</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1358,31 +1501,19 @@ Ne preporučujemo instalirati u ovu mapu, jer instaliranje možda neće uspjeti.
<translation>Nije moguće razriješiti sve ovisnosti.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Komponente se uklanjaju.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Component %1 already installed
-</source>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
+ <source>Component %1 already installed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
+ <source>Cannot install %1. Component is virtual.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Running processes found.</source>
+ <source>Cannot install %1. Component not found.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1414,10 +1545,6 @@ Ne preporučujemo instalirati u ovu mapu, jer instaliranje možda neće uspjeti.
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation type="unfinished"></translation>
</message>
@@ -1426,13 +1553,11 @@ Ne preporučujemo instalirati u ovu mapu, jer instaliranje možda neće uspjeti.
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1444,11 +1569,35 @@ Ne preporučujemo instalirati u ovu mapu, jer instaliranje možda neće uspjeti.
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
+ <source>Invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Invalid</source>
+ <source>Components about to be removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1567,16 +1716,12 @@ Ne preporučujemo instalirati u ovu mapu, jer instaliranje možda neće uspjeti.
<translation>Stvaranje alata za održavanje</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Instaliranje je dovršeno!</translation>
+ <source>Installation finished!</source>
+ <translation>Instaliranje je dovršeno!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Instaliranje je prekinuto!</translation>
+ <source>Installation aborted!</source>
+ <translation>Instaliranje je prekinuto!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1587,16 +1732,12 @@ Instaliranje je prekinuto!</translation>
<translation>Uklanjanje neodabranih komponenata …</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Aktualiziranje je dovršeno!</translation>
+ <source>Update finished!</source>
+ <translation>Aktualiziranje je dovršeno!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Aktualiziranje je prekinuto!</translation>
+ <source>Update aborted!</source>
+ <translation>Aktualiziranje je prekinuto!</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
@@ -1631,10 +1772,8 @@ Aktualiziranje je prekinuto!</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Instaliranje komponente %1</translation>
+ <source>Installing component %1</source>
+ <translation>Instaliranje komponente %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1667,10 +1806,6 @@ Instaliranje komponente %1</translation>
<translation>Nije moguće pronaći meta podatke: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Nije moguće dodati privremene podatke izvora nadogradnje.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Nije moguće naći bilo koje podatke izvora nadogradnje.</translation>
</message>
@@ -1699,6 +1834,50 @@ Instaliranje komponente %1</translation>
%1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -1731,7 +1910,7 @@ Instaliranje komponente %1</translation>
<translation>%1 Pitanje</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Postavke</translation>
</message>
<message>
@@ -1756,11 +1935,11 @@ Kopiraj program za instaliranje na računalo</translation>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Postavljanje – %1</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Dobrodošli u čarobnjak postavaka za %1.</translation>
</message>
<message>
@@ -1788,11 +1967,11 @@ Kopiraj program za instaliranje na računalo</translation>
<translation>Nema dostupnih nadogradnja.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Dostupno je samo lokalno upravljanje paketima.</translation>
+ <source>&amp;Quit</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Quit</source>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1827,42 +2006,38 @@ Kopiraj program za instaliranje na računalo</translation>
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>St&amp;andardne</translation>
+ <source>Default</source>
+ <translation>Standardne</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Resetiraj</translation>
+ <source>Reset</source>
+ <translation>Resetiraj</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>Odaberi &amp;sve</translation>
+ <source>Select All</source>
+ <translation>Odaberi sve</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>O&amp;dznači sav odabir</translation>
+ <source>Deselect All</source>
+ <translation>dznači sav odabir</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Pretraži QBSP datoteke</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation type="unfinished"></translation>
</message>
@@ -1891,37 +2066,41 @@ Kopiraj program za instaliranje na računalo</translation>
<translation>Odaberi komponente koje želiš deinstalirati.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Odaberi komponente koje želiš instalirati. Odznači instalirane komponente, kako bi se deinstalirale. Već instalirane komponente neće biti aktualizirane.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Odaberi komponente koje želiš instalirati. Odznači instalirane komponente, kako bi se deinstalirale.&lt;br&gt;Već instalirane komponente neće biti aktualizirane.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Filter the enabled repository categories</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Search</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
+ <source>Browse &amp;QBSP files</source>
+ <translation>&amp;Pretraži QBSP datoteke</translation>
+ </message>
+ <message>
+ <source>Select</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Greška</translation>
+ </message>
</context>
<context>
<name>QInstaller::TargetDirectoryPage</name>
@@ -1973,7 +2152,7 @@ Kopiraj program za instaliranje na računalo</translation>
<translation>Spremno za deinstaliranje</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Postavljanje je sad spremno za uklanjanje %1 s računala.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;Mapa programa %2 će se potpuno izbrisati&lt;/font&gt;, uključujući sav sadržaj mape!</translation>
</message>
<message>
@@ -1985,10 +2164,6 @@ Kopiraj program za instaliranje na računalo</translation>
<translation>Spremno za aktualiziranje paketa</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
- <translation>Postavljanje je sad spremno za aktualiziranje tvoje instalacije.</translation>
- </message>
- <message>
<source>&amp;Install</source>
<translation>&amp;Instaliraj</translation>
</message>
@@ -1997,13 +2172,29 @@ Kopiraj program za instaliranje na računalo</translation>
<translation>Spremno za instaliranje</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Postavljanje je sad spremno za instaliranje %1 na tvoje računalo.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>All required information is now available to begin updating your installation.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PerformInstallationPage</name>
@@ -2043,11 +2234,23 @@ Kopiraj program za instaliranje na računalo</translation>
<source>Uninstalling</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Dovršavanje čarobnjaka %1</translation>
</message>
<message>
@@ -2055,7 +2258,7 @@ Kopiraj program za instaliranje na računalo</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Klikni %1 za izlaženje iz čarobnjaka %2.</translation>
</message>
<message>
@@ -2067,14 +2270,14 @@ Kopiraj program za instaliranje na računalo</translation>
<translation>Sad pokreni %1.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Neuspješno pokretanje čarobnjaka %1.</translation>
</message>
</context>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Dovršavanje čarobnjaka postavaka %1</translation>
</message>
</context>
@@ -2195,7 +2398,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>Nije moguće otvoriti datoteke postavaka %1 za učitavanje: %2</translation>
</message>
<message>
- <source>Select Categories</source>
+ <source>Categories</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2391,6 +2594,10 @@ or accept the elevation of access rights if being asked.</source>
<source>Try again</source>
<translation>Pokušaj ponovo</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -2663,10 +2870,6 @@ or accept the elevation of access rights if being asked.</source>
<translation>Nije moguće čitati &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Greška u obradi u %1 na %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Neočekivani Root element %1, mora biti &quot;Updates&quot;.</translation>
</message>
@@ -2709,7 +2912,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>Greška</translation>
</message>
<message>
- <source>Component Information</source>
+ <source>Information</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2720,4 +2923,189 @@ or accept the elevation of access rights if being asked.</source>
<translation type="unfinished"></translation>
</message>
</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation::Worker</name>
+ <message>
+ <source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Nije moguće otvoriti arhivu &quot;%1&quot; za učitavanje: %2</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Greška prilikom raspakiravanja arhive &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nije moguće otvoriti datoteku &quot;%1&quot; za zapisivanje: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nije moguće otvoriti datoteku &quot;%1&quot; za učitavanje: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
</TS>
diff --git a/src/sdk/translations/ifw_hu.ts b/src/sdk/translations/ifw_hu.ts
new file mode 100644
index 000000000..cd247fd8b
--- /dev/null
+++ b/src/sdk/translations/ifw_hu.ts
@@ -0,0 +1,3081 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="hu">
+<context>
+ <name>AuthenticationRequiredException</name>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 itt: %2</translation>
+ </message>
+ <message>
+ <source>Proxy requires authentication.</source>
+ <translation>Proxy authentikációt igényel.</translation>
+ </message>
+</context>
+<context>
+ <name>BinaryContent</name>
+ <message>
+ <source>Cannot seek to %1 to read the operation data.</source>
+ <translation>Nem kereshető %1, ezért a művelet adata nem beolvasható.</translation>
+ </message>
+ <message>
+ <source>Cannot seek to %1 to read the resource collection block.</source>
+ <translation>Nem kereshető %1, ezért az erőforrásgyűjtési blokk nem beolvasható.</translation>
+ </message>
+ <message>
+ <source>Cannot open meta resource %1.</source>
+ <translation>Nem sikerült megnyitni %1 meta forrást.</translation>
+ </message>
+</context>
+<context>
+ <name>BinaryLayout</name>
+ <message>
+ <source>Cannot seek to %1 to read the embedded meta data count.</source>
+ <translation>Nem kereshető %1, ezért nem tudja beolvasni a beágyazott metaadatok számát.</translation>
+ </message>
+ <message>
+ <source>Cannot seek to %1 to read the resource collection segment.</source>
+ <translation>Nem kereshető %1, ezért nem tudja beolvasni erőforrásgyűjtési szegmenst.</translation>
+ </message>
+ <message>
+ <source>Unexpected mismatch of meta resources. Read %1, expected: %2.</source>
+ <translation>A metaforrások váratlan eltérése. Olvasás %1, elvárt: %2.</translation>
+ </message>
+</context>
+<context>
+ <name>Dialog</name>
+ <message>
+ <source>Http authentication required</source>
+ <translation>Http authentikáció szükséges</translation>
+ </message>
+ <message>
+ <source>You need to supply a Username and Password to access this site.</source>
+ <translation>Az oldal eléréséhez Felhasználónevet és Jelszót kell megadnia.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>Felhasználónév:</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>Jelszó:</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 itt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>DirectoryGuard</name>
+ <message>
+ <source>Path &quot;%1&quot; exists but is not a directory.</source>
+ <translation>&quot;%1&quot; útvonal létezik, de nem egy könyvtárat határoz meg.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat.</translation>
+ </message>
+</context>
+<context>
+ <name>ExtractCallbackImpl</name>
+ <message>
+ <source>Cannot retrieve path of archive item %1.</source>
+ <translation>Nem sikerült lekérni %1 archív elem elérési útját.</translation>
+ </message>
+ <message>
+ <source>Cannot remove already existing symlink %1.</source>
+ <translation>Nem sikerült eltávolítani a létező &quot;%1&quot; szimbólikus linket.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create symlink at &quot;%1&quot;. Another one is already existing.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; szimbólikus linket. Egy másik már létezik.</translation>
+ </message>
+ <message>
+ <source>Cannot read symlink target from file &quot;%1&quot;.</source>
+ <translation>Nem sikerült beolvasni &quot;%1&quot; fájlra mutató szimbólikus linket.</translation>
+ </message>
+ <message>
+ <source>Cannot create symlink at %1: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; szimbólikus linket: %2</translation>
+ </message>
+</context>
+<context>
+ <name>InstallerBase</name>
+ <message>
+ <source>Unable to start installer</source>
+ <translation>Nem sikerült elindítani a telepítőt</translation>
+ </message>
+</context>
+<context>
+ <name>InstallerCalculator</name>
+ <message>
+ <source>Components added as automatic dependencies:</source>
+ <translation>Automatikus függőségekként hozzáadott komponensek:</translation>
+ </message>
+ <message>
+ <source>Components added as dependency for &quot;%1&quot;:</source>
+ <translation>Függőségekként hozzáadott komponensek &quot;%1&quot; számára:</translation>
+ </message>
+ <message>
+ <source>Components that have resolved dependencies:</source>
+ <translation>Komponensek feloldott függőségekkel:</translation>
+ </message>
+ <message>
+ <source>Selected components without dependencies:</source>
+ <translation>Kiválasztott komponensek függőségek nélkül:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component &quot;%1&quot; already added with reason: &quot;%2&quot;</source>
+ <translation>Rekurzió észlelve, &quot;%1&quot; komponens már hozzáadva &quot;%2&quot; okkal.</translation>
+ </message>
+ <message>
+ <source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
+ <translation>Nem található hiányzó &quot;%1&quot; függőség &quot;%2&quot; számára. </translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>Job</name>
+ <message>
+ <source>Canceled</source>
+ <translation>Megszakítva</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::AppendFileOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot find backup file for &quot;%1&quot;.</source>
+ <translation>Nem található biztonsági mentés &quot;%1&quot; fájlhoz.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;.</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::CopyOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;.</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról.</translation>
+ </message>
+ <message>
+ <source>Cannot copy a non-existent file: %1</source>
+ <translation>Nem másolható egy nem létező fájl: %1</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Cannot delete file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült törölni &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file into &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::DeleteOperation</name>
+ <message>
+ <source>Cannot create backup of file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról: %2</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::FileDownloader</name>
+ <message>
+ <source>Download finished.</source>
+ <translation>Letöltés befejeződött.</translation>
+ </message>
+ <message>
+ <source>Cryptographic hashes do not match.</source>
+ <translation>Kriptográfiai hash-ek nem egyeznek.</translation>
+ </message>
+ <message>
+ <source>Download canceled.</source>
+ <translation>Letöltés megszakítva.</translation>
+ </message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 %2-ből</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 letöltve.</translation>
+ </message>
+ <message>
+ <source>(%1/sec)</source>
+ <translation>(%1/másodperc)</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n nap, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n óra, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n perc</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n másodperc</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 maradt.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - ismeretlen idő maradt.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::HttpDownloader</name>
+ <message>
+ <source>Cannot download %1. Writing to file &quot;%2&quot; failed: %3</source>
+ <translation>%1 letöltése nem sikerült. Írás &quot;%2&quot; fájlba nem sikerült: %3</translation>
+ </message>
+ <message>
+ <source>Cannot download %1. Cannot create file &quot;%2&quot;: %3</source>
+ <translation>%1 letöltése nem sikerült. Nem lehet létrehozni &quot;%2&quot; fájlt: %3</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 itt: %2</translation>
+ </message>
+ <message>
+ <source>Authentication request canceled.</source>
+ <translation>Az authentikációs kérelem törölve.</translation>
+ </message>
+ <message>
+ <source>Secure Connection Failed</source>
+ <translation>Biztonságos kapcsolódás sikertelen</translation>
+ </message>
+ <message>
+ <source>There was an error during connection to: %1.</source>
+ <translation>Hiba történt a következőhöz való csatlakozás során: %1.</translation>
+ </message>
+ <message>
+ <source>This could be a problem with the server&apos;s configuration, or it could be someone trying to impersonate the server.</source>
+ <translation>Probléma lehet a szerver konfigurációjával, vagy valaki megpróbálja megszemélyesíteni a szervert.</translation>
+ </message>
+ <message>
+ <source>If you have connected to this server successfully in the past or trust this server, the error may be temporary and you can try again.</source>
+ <translation>Ha a múltban sikeresen csatlakozott ehhez a szerverhez, vagy bízik ebben a szerverben, akkor a hiba átmeneti lehet, és megpróbálhatja újra.</translation>
+ </message>
+ <message>
+ <source>Try again</source>
+ <translation>Próbálja újra</translation>
+ </message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::LocalFileDownloader</name>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Writing to file &quot;%1&quot; failed: %2</source>
+ <translation>Írás &quot;%1&quot; fájlba nem sikerült: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::MkdirOperation</name>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Ismeretlen hiba.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::MoveOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;.</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::PrependFileOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot find backup file for &quot;%1&quot;.</source>
+ <translation>Nem található biztonsági mentés &quot;%1&quot; fájlhoz.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;.</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült visszaállítani &quot;%1&quot; biztonsági mentés fájlt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::ResourceFileDownloader</name>
+ <message>
+ <source>Cannot read resource file &quot;%1&quot;: %2</source>
+ <translation>Nem olvasható &quot;%1&quot; forrásfájl: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::RmdirOperation</name>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>The directory does not exist.</source>
+ <translation>A könyvtár nem létezik.</translation>
+ </message>
+ <message>
+ <source>Cannot recreate directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült újra létrehozni &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::Task</name>
+ <message>
+ <source>%1 started</source>
+ <translation>%1 elindítva</translation>
+ </message>
+ <message>
+ <source>%1 cannot be stopped</source>
+ <translation>%1 nem állítható le</translation>
+ </message>
+ <message>
+ <source>Cannot stop task %1</source>
+ <translation>%1 taszk nem állítható le</translation>
+ </message>
+ <message>
+ <source>%1 cannot be paused</source>
+ <translation>%1 nem szüneteltethető</translation>
+ </message>
+ <message>
+ <source>Cannot pause task %1</source>
+ <translation>%1 taszk nem szüneteltethető</translation>
+ </message>
+ <message>
+ <source>Cannot resume task %1</source>
+ <translation>%1 taszk nem folytatható</translation>
+ </message>
+ <message>
+ <source>%1 done</source>
+ <translation>%1 kész</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::UpdateFinder</name>
+ <message>
+ <source>Cannot access the package information of this application.</source>
+ <translation>Nem érhető el az alkalmazás csomaginformációi.</translation>
+ </message>
+ <message>
+ <source>No package sources set for this application.</source>
+ <translation>Nincs beállítva csomagforrás ehhez az alkalmazáshoz.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n update(s) found.</source>
+ <translation>
+ <numerusform>%n frissítés található.</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Downloading Updates.xml from update sources.</source>
+ <translation>Updates.xml letöltése frissítési forrásokból.</translation>
+ </message>
+ <message>
+ <source>Cannot download package source %1 from &quot;%2&quot;.</source>
+ <translation>Nem lehet letölteni %1 csomagforrást innen: &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Updates.xml file(s) downloaded from update sources.</source>
+ <translation>Updates.xml fájl(ok) letöltve a frissítési forrásokból.</translation>
+ </message>
+ <message>
+ <source>Computing applicable updates.</source>
+ <translation>Vonatkozó frissítések kiszámítása.</translation>
+ </message>
+ <message>
+ <source>Application updates computed.</source>
+ <translation>Alkalmazásfrissítések kiszámítva.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::UpdatesInfoData</name>
+ <message>
+ <source>Updates.xml contains invalid content: %1</source>
+ <translation>Updates.xml érvénytelen tartalommal bír: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; olvasása nem sikerült</translation>
+ </message>
+ <message>
+ <source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
+ <translation>%1 gyökér elem váratlan, &apos;Updates&apos; kell, hogy legyen.</translation>
+ </message>
+ <message>
+ <source>ApplicationName element is missing.</source>
+ <translation>ApplicationName elem hiányzik.</translation>
+ </message>
+ <message>
+ <source>ApplicationVersion element is missing.</source>
+ <translation>ApplicationVersion elem hiányzik.</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without Name</source>
+ <translation>PackageUpdate elem Name nélkül</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without Version</source>
+ <translation>PackageUpdate elem Version nélkül</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without ReleaseDate</source>
+ <translation>PackageUpdate elem ReleaseDate nélkül</translation>
+ </message>
+</context>
+<context>
+ <name>Lib7z</name>
+ <message>
+ <source>Internal code: %1</source>
+ <translation>Belső kód:</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>Nincs elegendő memória</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Hiba: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve property %1 for item %2.</source>
+ <translation>Nem hozható le %1 property %2 elem számára.</translation>
+ </message>
+ <message>
+ <source>Property %1 for item %2 not of type VT_FILETIME but %3.</source>
+ <translation>%1 property %2 elem számára nem VT_FILETIME típussal bír, hanem %3.</translation>
+ </message>
+ <message>
+ <source>Cannot convert UTC file time to system time.</source>
+ <translation>UTC fájl idő nem alakítható át rendszeridőre.</translation>
+ </message>
+ <message>
+ <source>Cannot load codecs.</source>
+ <translation>Kodekek nem tölthetők be.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot;.</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; archívumot.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve number of items in archive.</source>
+ <translation>Nem lehet lekérni az archívumban lévő elemek számát.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve path of archive item &quot;%1&quot;.</source>
+ <translation>Nem lehet lehozni &quot;%1&quot; archívum útvonalát.</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught (%1).</source>
+ <translation>Ismeretlen kivétel történt: (%1).</translation>
+ </message>
+ <message>
+ <source>Cannot create temporary file: %1</source>
+ <translation>Nem sikerült létrehozni az ideiglenes &quot;%1&quot; fájlt.</translation>
+ </message>
+ <message>
+ <source>Unsupported archive type.</source>
+ <translation>Nem támogatott archívum típus.</translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; archívumot.</translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; archívumot: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove old archive &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; régi archívumot: %2</translation>
+ </message>
+ <message>
+ <source>Cannot rename temporary archive &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átnevezni az ideiglenes &quot;%1&quot; archívumot &quot;%2&quot; archívumra: %3</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught (%1)</source>
+ <translation>Ismeretlen kivétel történt: %1</translation>
+ </message>
+</context>
+<context>
+ <name>LocalPackageHub</name>
+ <message>
+ <source>%1 contains invalid content: %2</source>
+ <translation>%1 érvénytelen tartalommal bír: %2</translation>
+ </message>
+ <message>
+ <source>The file %1 does not exist.</source>
+ <translation>%1 fájl nem létezik.</translation>
+ </message>
+ <message>
+ <source>Cannot open %1.</source>
+ <translation>Nem sikerült megnyitni %1 fájlt.</translation>
+ </message>
+ <message>
+ <source>Parse error in %1 at %2, %3: %4</source>
+ <translation>Elemzési hiba %1-ben itt: %2, %3: %4</translation>
+ </message>
+ <message>
+ <source>Root element %1 unexpected, should be &apos;Packages&apos;.</source>
+ <translation>%1 gyökér elem váratlan, &apos;Packages&apos; kell, hogy legyen.</translation>
+ </message>
+</context>
+<context>
+ <name>LockFile</name>
+ <message>
+ <source>Cannot create lock file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet létrehozni &quot;%1&quot; zárolási fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write PID to lock file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet PID-et írni a &quot;%1&quot; fájl zárolásához: %2</translation>
+ </message>
+ <message>
+ <source>Cannot obtain the lock for file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült lezárni a &quot;%1&quot; fájl zárolását: %2</translation>
+ </message>
+ <message>
+ <source>Cannot release the lock for file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet feloldani a &quot;%1&quot; fájl zárolását: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller</name>
+ <message>
+ <source>Invalid content in &quot;%1&quot;.</source>
+ <translation>Érvénytelen tartalom &quot;%1&quot;-nál.</translation>
+ </message>
+ <message>
+ <source>No marker found, stopped after %1.</source>
+ <translation>Nem található jelölés, %1 után leállt. </translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Read failed after %1 bytes: %2</source>
+ <translation>Sikertelen olvasás %1 bájt után: %2</translation>
+ </message>
+ <message>
+ <source>Copy failed: %1</source>
+ <translation>Sikertelen másolás: %1</translation>
+ </message>
+ <message>
+ <source>Write failed after %1 bytes: %2</source>
+ <translation>Sikertelen írás %1 bájt után: %2</translation>
+ </message>
+ <message>
+ <source>bytes</source>
+ <translation>bájtok</translation>
+ </message>
+ <message>
+ <source>KB</source>
+ <translation>KB</translation>
+ </message>
+ <message>
+ <source>MB</source>
+ <translation>MB</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>TB</source>
+ <translation>TB</translation>
+ </message>
+ <message>
+ <source>PB</source>
+ <translation>PB</translation>
+ </message>
+ <message>
+ <source>EB</source>
+ <translation>EB</translation>
+ </message>
+ <message>
+ <source>ZB</source>
+ <translation>ZB</translation>
+ </message>
+ <message>
+ <source>YB</source>
+ <translation>YB</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat.</translation>
+ </message>
+ <message>
+ <source>Cannot copy file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Cannot move file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmozgatni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open temporary file: %1</source>
+ <translation>Ideiglenes fájlt nem lehet megnyitni: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open temporary file for template %1: %2</source>
+ <translation>Nem lehet megnyitni %1 sablon ideiglenes fájlját: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt &quot;%2&quot; fájlba.</translation>
+ </message>
+ <message>
+ <source>The specified module could not be found.</source>
+ <translation>A megadott modul nem található.</translation>
+ </message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Component</name>
+ <message>
+ <source>Components cannot have children in updater mode.</source>
+ <translation>A komponenseknek nem lehetnek gyermekei frissítés módban. </translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hiba</translation>
+ </message>
+ <message>
+ <source>Error: Operation %1 does not exist.</source>
+ <translation>Hiba: %1 művelet nem létezik.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve isDefault in %1</source>
+ <translation>Nem oldható fel az isDefault itt: %1</translation>
+ </message>
+ <message>
+ <source>Update Info: </source>
+ <translation>Frissítési Info: </translation>
+ </message>
+ <message>
+ <source>There was an error loading the selected component. This component cannot be installed.</source>
+ <translation>Hiba történt a kiválasztott komponens betöltésekor. Ez az komponens nem telepíthető.</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nem tudja megnyitni a kért &quot;%1&quot; UI fájlt: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nem tudja betölteni a kért &quot;%1&quot; UI fájlt: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nem lehet megnyitni a kért &quot;%1&quot; licencfájlt: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ComponentModel</name>
+ <message>
+ <source>Component is marked for installation.</source>
+ <translation>Komponens meg van jelölve telepítéshez.</translation>
+ </message>
+ <message>
+ <source>Component is marked for uninstallation.</source>
+ <translation>Komponens meg van jelölve eltávolításhoz.</translation>
+ </message>
+ <message>
+ <source>Component is installed.</source>
+ <translation>Komponens telepítve van.</translation>
+ </message>
+ <message>
+ <source>Component is not installed.</source>
+ <translation>Komponens nincs telepítve.</translation>
+ </message>
+ <message>
+ <source>Component Name</source>
+ <translation>Komponens Név</translation>
+ </message>
+ <message>
+ <source>Action</source>
+ <translation>Tevékenység</translation>
+ </message>
+ <message>
+ <source>Installed Version</source>
+ <translation>Telepített Verzió</translation>
+ </message>
+ <message>
+ <source>New Version</source>
+ <translation>Új Verzió</translation>
+ </message>
+ <message>
+ <source>Release Date</source>
+ <translation>Kiadási Dátum</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>Méret</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ComponentSelectionPage</name>
+ <message>
+ <source>Default</source>
+ <translation>Alapértelmezett</translation>
+ </message>
+ <message>
+ <source>Select default components in the tree view.</source>
+ <translation>Alapértelmezett komponensek kiválasztása a fa nézetben.</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>Visszaállítás</translation>
+ </message>
+ <message>
+ <source>Reset all components to their original selection state in the tree view.</source>
+ <translation>Összes komponens visszaállítása az eredeti kiválasztási állapotba a fa nézetben. </translation>
+ </message>
+ <message>
+ <source>Select All</source>
+ <translation>Mindent kijelöl</translation>
+ </message>
+ <message>
+ <source>Select all components in the tree view.</source>
+ <translation>Minden komponens kijelölése a fa nézetben.</translation>
+ </message>
+ <message>
+ <source>Deselect All</source>
+ <translation>Összes kijelölés megszüntetése</translation>
+ </message>
+ <message>
+ <source>Deselect all components in the tree view.</source>
+ <translation>Minden komponens kijelölésének a megszüntetése a fa nézetben.</translation>
+ </message>
+ <message>
+ <source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
+ <translation>Qt Board támogatási csomagfájl kiválasztása a további tartalom telepítéséhez, amely közvetlenül nem érhető el az online tárolókból.</translation>
+ </message>
+ <message>
+ <source>Filter the enabled repository categories</source>
+ <translation>Az engedélyezett tároló kategóriák szűrése.</translation>
+ </message>
+ <message>
+ <source>This component will occupy approximately %1 on your hard disk drive.</source>
+ <translation>Ez az összetevő körülbelül %1 helyet foglal el a merevlemezen.</translation>
+ </message>
+ <message>
+ <source>Open File</source>
+ <translation>Fájl Megnyitása</translation>
+ </message>
+ <message>
+ <source>Select Components</source>
+ <translation>Komponensek kiválasztása</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to update.</source>
+ <translation>Kérem válassza ki a frissíteni kívánt komponenseket.</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to install.</source>
+ <translation>Kérem válassza ki a telepíteni kívánt komponenseket.</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to uninstall.</source>
+ <translation>Kérem válassza ki az eltávolítani kívánt komponenseket.</translation>
+ </message>
+ <message>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Válassza ki a telepítendő összetevőket. Törölje a telepített összetevők kijelölését az eltávolításhoz.&lt;br&gt;A már telepített összetevők nem frissülnek.</translation>
+ </message>
+ <message>
+ <source>Mandatory components need to be updated first before you can select other components to update.</source>
+ <translation>A kötelező összetevőket először frissíteni kell, mielőtt kiválaszthatja a frissítendő egyéb összetevőket.</translation>
+ </message>
+ <message>
+ <source>Search</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>QBSP fájlok böngészése</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Hiba</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ComponentSelectionPagePrivate</name>
+ <message>
+ <source>Filter</source>
+ <translation>Szűrő</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">Komponens Információ</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hiba</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ConsumeOutputOperation</name>
+ <message>
+ <source>&lt;to be saved installer key name&gt; &lt;executable&gt; [argument1] [argument2] [...]</source>
+ <translation>&lt;elmentendő telepítő kulcs neve&gt; &lt;végrehajtható&gt; [argumentum1] [argumentum2] [...]</translation>
+ </message>
+ <message>
+ <source>Needed installer object in %1 operation is empty.</source>
+ <translation>Szükséges telepítő objektum %1 műveletben üres.</translation>
+ </message>
+ <message>
+ <source>Cannot save the output of &quot;%1&quot; to an empty installer key value.</source>
+ <translation>Nem lehet menteni &quot;%1&quot; kimenetét üres telepítőkulcs értékre.</translation>
+ </message>
+ <message>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CopyDirectoryOperation</name>
+ <message>
+ <source>&lt;source&gt; &lt;target&gt; [&quot;forceOverwrite&quot;]</source>
+ <translation>&lt;forrás&gt; &lt;cél&gt; [&quot;forceOverwrite&quot;]</translation>
+ </message>
+ <message>
+ <source>Invalid argument in %1: Third argument needs to be forceOverwrite, if specified.</source>
+ <translation>Érvénytelen argumentum itt: %1. A harmadik argumentumnak forceOverwrite-nak kell lennie, ha meg van adva.</translation>
+ </message>
+ <message>
+ <source>Invalid argument in %1: Directory &quot;%2&quot; is invalid.</source>
+ <translation>Érvénytelen argumentum itt: %1. &quot;%2&quot; könyvtár érvénytelen.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat.</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;.</source>
+ <translation>Nem sikerült felülírni &quot;%1&quot; fájlt.</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CopyFileTask</name>
+ <message>
+ <source>Invalid task item count.</source>
+ <translation>Érvénytelen feladat-elem szám. </translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Writing to file &quot;%1&quot; failed: %2</source>
+ <translation>Írás &quot;%1&quot; fájlba nem sikerült: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateDesktopEntryOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite file &quot;%1&quot;.</source>
+ <translation>Nem sikerült felülírni &quot;%1&quot; fájlt.</translation>
+ </message>
+ <message>
+ <source>Cannot write desktop entry to &quot;%1&quot;.</source>
+ <translation>Nem írható asztali bejegyzés &quot;%1&quot; fájlhoz.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateLinkOperation</name>
+ <message>
+ <source>Cannot create link from &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>Nem hozható létre &quot;%2&quot; link &quot;%1&quot; fáljra.</translation>
+ </message>
+ <message>
+ <source>Cannot remove link from &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>Nem törölhető &quot;%2&quot; link &quot;%1&quot; fáljról.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateLocalRepositoryOperation</name>
+ <message>
+ <source>Cannot set permissions for file &quot;%1&quot;.</source>
+ <translation>Nem lehet engedélyeket beállítani &quot;%1&quot; fájlhoz.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; archívumot: %2</translation>
+ </message>
+ <message>
+ <source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmozgatni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Installer at &quot;%1&quot; needs to be an offline one.</source>
+ <translation>&quot;%1&quot; telepítőnek offline állapotúnak kell lennie.</translation>
+ </message>
+ <message>
+ <source>Cannot create path &quot;%1&quot;.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; útvonalat.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;.</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; könyvtárat.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading.</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra.</translation>
+ </message>
+ <message>
+ <source>Cannot read file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült beolvasni &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create target directory: &quot;%1&quot;.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; célkönyvtárat.</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught: %1.</source>
+ <translation>Ismeretlen kivétel történt: %1.</translation>
+ </message>
+ <message>
+ <source>Removing file &quot;%1&quot;.</source>
+ <translation>Fájl &quot;%1&quot; eltávolítása.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateShortcutOperation</name>
+ <message>
+ <source>&lt;target&gt; &lt;link location&gt; [target arguments] [&quot;workingDirectory=...&quot;] [&quot;iconPath=...&quot;] [&quot;iconId=...&quot;] [&quot;description=...&quot;]</source>
+ <translation>&lt;target&gt; &lt;link location&gt; [target arguments] [&quot;workingDirectory=...&quot;] [&quot;iconPath=...&quot;] [&quot;iconId=...&quot;] [&quot;description=...&quot;]</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült felülírni &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create link &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; linket: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::DownloadArchivesJob</name>
+ <message>
+ <source>Canceled</source>
+ <translation>Visszavonva</translation>
+ </message>
+ <message>
+ <source>Downloading hash signature failed.</source>
+ <translation>Hash aláírás letöltése nem sikerült.</translation>
+ </message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 %2-ből</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 letöltve.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n nap, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n óra, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n perc</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n másodperc</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation>- %1%2%3%4 maradt.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - ismeretlen hátralévő idő maradt.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation></translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation></translation>
+ </message>
+ <message>
+ <source>Download Error</source>
+ <translation>Letöltési Hiba</translation>
+ </message>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.</source>
+ <translation>Hash ellenőrzés a letöltés során nem sikerült. Ideiglenes hiba, próbálja meg újra. </translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash</source>
+ <translation>Hash nem ellenőrizhető</translation>
+ </message>
+ <message>
+ <source>Cannot download archive %1: %2</source>
+ <translation>Nem sikerült %1 archívum letöltése: %2</translation>
+ </message>
+ <message>
+ <source>Cannot fetch archives: %1
+Error while loading %2</source>
+ <translation>Nem sikerült lekérni az archívumot: %1
+Hiba %2 betöltése közben</translation>
+ </message>
+ <message>
+ <source>Downloading archive &quot;%1&quot; for component %2.</source>
+ <translation>&quot;%1&quot; archívum letöltése %2 komponens számára.</translation>
+ </message>
+ <message>
+ <source>Scheme %1 not supported (URL: %2).</source>
+ <translation>%1 séma nem támogatott (URL: %2).</translation>
+ </message>
+ <message>
+ <source>Cannot find component for %1.</source>
+ <translation>Nem található komponens %1 számára.</translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Downloader</name>
+ <message>
+ <source>Target file &quot;%1&quot; already exists but is not a file.</source>
+ <translation>&quot;%1&quot; célfájl már létezik de az valójában nem is fájl.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <extracomment>%2 is a sentence describing the error</extracomment>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>File &quot;%1&quot; not open for writing: %2</source>
+ <extracomment>%2 is a sentence describing the error.</extracomment>
+ <translation>&quot;%1&quot; fájl nincs megnyitva írásra: %2</translation>
+ </message>
+ <message>
+ <source>Writing to file &quot;%1&quot; failed: %2</source>
+ <extracomment>%2 is a sentence describing the error.</extracomment>
+ <translation>Írás &quot;%1&quot; fájlba nem sikerült: %2</translation>
+ </message>
+ <message>
+ <source>Redirect loop detected for &quot;%1&quot;.</source>
+ <translation>Átirányítási hurok észlelve &quot;%1&quot; számára.</translation>
+ </message>
+ <message>
+ <source>Network error while downloading &apos;%1&apos;: %2.</source>
+ <translation>Hálózati hiba &apos;%1&apos; letöltése közben: %2.</translation>
+ </message>
+ <message>
+ <source>Unknown network error while downloading &quot;%1&quot;.</source>
+ <extracomment>%1 is a sentence describing the error</extracomment>
+ <translation>Ismeretlen hiba &quot;%1&quot; letöltése közben.</translation>
+ </message>
+ <message>
+ <source>Network transfers canceled.</source>
+ <translation>Hálózati átvitel megszakítva. </translation>
+ </message>
+ <message>
+ <source>Pause and resume not supported by network transfers.</source>
+ <translation>Szüneteltetést és folytatást a hálózati átvitel nem támogatja.</translation>
+ </message>
+ <message>
+ <source>Invalid source URL &quot;%1&quot;: %2</source>
+ <extracomment>%2 is a sentence describing the error</extracomment>
+ <translation>Érvénytelen forrás URL &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ElevatedExecuteOperation</name>
+ <message>
+ <source>Cannot start detached: &quot;%1&quot;</source>
+ <translation>Nem lehet elindítani a leválasztást: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot start: &quot;%1&quot;: %2</source>
+ <translation>Nem lehet elindítani: &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Program crashed: &quot;%1&quot;</source>
+ <translation>Program összeomlott: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Execution failed (Unexpected exit code: %1): &quot;%2&quot;</source>
+ <translation>Végrehajtás nem sikerült (Váratlan kilépési kód: %1): &quot;%2&quot;</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation</name>
+ <message>
+ <source>Extracting &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; kibontása</translation>
+ </message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; archívumot olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Hiba a &quot;%1&quot; archívum olvasása közben: %2 </translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation::Worker</name>
+ <message>
+ <source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
+ <translation>Nem sikerült létrehozni kezelő objektumot &quot;%1&quot; archívumhoz: &quot;%2&quot;. </translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; archívumot olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Hiba &quot;%1&quot; archívum kibontása közben: %2 </translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::FakeStopProcessForUpdateOperation</name>
+ <message>
+ <source>Cannot get package manager core.</source>
+ <translation>Nem sikerült lehozni a csomagkezelő magját.</translation>
+ </message>
+ <message>
+ <source>This process should be stopped before continuing: %1</source>
+ <translation>Ezt a folyamatot le kell állítani a folytatás előtt: %1</translation>
+ </message>
+ <message>
+ <source>These processes should be stopped before continuing: %1</source>
+ <translation>Ezeket a folyamatokat le kell állítani a folytatás előtt: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::FileTaskObserver</name>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 %2-ből</translation>
+ </message>
+ <message>
+ <source>%1 received.</source>
+ <translation>érkezett %1.</translation>
+ </message>
+ <message>
+ <source>(%1/sec)</source>
+ <translation>(%1/másodperc)</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n nap, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n óra, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n perc</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n másodperc</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation>- %1%2%3%4 maradt.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - ismeretlen hátralévő idő.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::FinishedPage</name>
+ <message>
+ <source>Finished the %1 Setup</source>
+ <translation>%1 varázsló befejezése</translation>
+ </message>
+ <message>
+ <source>Finished</source>
+ <translation>Befejezett</translation>
+ </message>
+ <message>
+ <source>Click %1 to exit the %2 Setup.</source>
+ <translation>Kattintson %1 gombra %2 varázslóból való kilépéshez.</translation>
+ </message>
+ <message>
+ <source>Restart</source>
+ <translation>Újraindítás</translation>
+ </message>
+ <message>
+ <source>Run %1 now.</source>
+ <translation>Futtassa most %1-et.</translation>
+ </message>
+ <message>
+ <source>The %1 Setup failed.</source>
+ <translation>%1 varázsló elbukott.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::GlobalSettingsOperation</name>
+ <message>
+ <source>Settings are not writable.</source>
+ <translation>Beálítások nem írhatók.</translation>
+ </message>
+ <message>
+ <source>Failed to write settings.</source>
+ <translation>Nem sikerült írni a beállításokat.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::InstallIconsOperation</name>
+ <message>
+ <source>&lt;source path&gt; [vendor prefix]</source>
+ <translation>&lt;forrás útvonal&gt; [eladó előtagja]</translation>
+ </message>
+ <message>
+ <source>Invalid Argument: source directory must not be empty.</source>
+ <translation>Érvénytelen Argumentum: forrás könyvtár nem lehet üres.</translation>
+ </message>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Nem lehet biztonsági mentést készíteni &quot;%1&quot; fájlról: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült felülírni &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Failed to copy file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült átmásolni &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat: %2</translation>
+ </message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::IntroductionPage</name>
+ <message>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 Setup.</source>
+ <translation>Üdvözöljük a %1 telepítő varázslóban.</translation>
+ </message>
+ <message>
+ <source>&amp;Add or remove components</source>
+ <translation>Komponensek hozzáadása vagy eltávolítása</translation>
+ </message>
+ <message>
+ <source>&amp;Update components</source>
+ <translation>Komponensek frissítése</translation>
+ </message>
+ <message>
+ <source>&amp;Remove all components</source>
+ <translation>Összes komponens eltávolítása</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote installation sources...</source>
+ <translation>Információk lekérése távoli telepítési forrásokból...</translation>
+ </message>
+ <message>
+ <source>At least one valid and enabled repository required for this action to succeed.</source>
+ <translation>A művelet sikeres végrehajtásához legalább egy érvényes és engedélyezett tároló szükséges. </translation>
+ </message>
+ <message>
+ <source>No updates available.</source>
+ <translation>Nincs elérhető frissítés.</translation>
+ </message>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>Egy fontos frissítés áll rendelkezésre. Kérjük, válassza előbb &apos;%1&apos; -t</translation>
+ </message>
+ <message>
+ <source>&amp;Quit</source>
+ <translation>&amp;Kilépés</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LicenseAgreementPage</name>
+ <message>
+ <source>License Agreement</source>
+ <translation>Licencszerződés</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <comment>Agree license</comment>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Please read the following license agreement. You must accept the terms contained in this agreement before continuing with the installation.</source>
+ <translation>Kérjük, olvassa el az alábbi licencszerződést. A telepítés folytatása előtt el kell fogadnia a jelen szerződésben foglalt feltételeket.</translation>
+ </message>
+ <message>
+ <source>I accept the license.</source>
+ <translation>Elfogadom a licencet.</translation>
+ </message>
+ <message>
+ <source>Please read the following license agreements. You must accept the terms contained in these agreements before continuing with the installation.</source>
+ <translation>Kérjük, olvassa el az alábbi licencszerződéseket. A telepítés folytatása előtt el kell fogadnia a jelen szerződésekben foglalt feltételeket.</translation>
+ </message>
+ <message>
+ <source>I accept the licenses.</source>
+ <translation>Elfogadom a licenceket.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LicenseOperation</name>
+ <message>
+ <source>No license files found to copy.</source>
+ <translation>Nem található másolható licencfájl.</translation>
+ </message>
+ <message>
+ <source>Needed installer object in %1 operation is empty.</source>
+ <translation>Szükséges telepítő objektum %1 műveletben üres.</translation>
+ </message>
+ <message>
+ <source>Can not write license file &quot;%1&quot;.</source>
+ <translation>Nem lehet írni &quot;%1&quot; licencfájlt.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LineReplaceOperation</name>
+ <message>
+ <source>Invalid argument in %1: Empty search argument is not supported.</source>
+ <translation>Érvénytelen argumentum itt: %1: Üres keresési argumentum nem támogatott. </translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::MetadataJob</name>
+ <message>
+ <source>Missing package manager core engine.</source>
+ <translation>Hiányzik a csomagkezelő alapmotorja.</translation>
+ </message>
+ <message>
+ <source>Unpacking compressed repositories. This may take a while...</source>
+ <translation>A tömörített tárolók kicsomagolása. Ez eltarthat egy ideig...</translation>
+ </message>
+ <message>
+ <source>Metadata download canceled.</source>
+ <translation>A metaadatok letöltése megszakítva.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during extracting.</source>
+ <translation>Ismeretlen kivétel történt kibontás közben.</translation>
+ </message>
+ <message>
+ <source>Missing proxy credentials.</source>
+ <translation>Hiányzó proxy hitelesítő adatok.</translation>
+ </message>
+ <message>
+ <source>Authentication failed.</source>
+ <translation>Sikertelen volt az authentikáció.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during download.</source>
+ <translation>Ismeretlen kivétel történt letöltés közben.</translation>
+ </message>
+ <message>
+ <source>Failure to fetch repositories.</source>
+ <translation>Nem sikerült lekérni a tárolókat.</translation>
+ </message>
+ <message>
+ <source>Extracting meta information...</source>
+ <translation>Meta információk kibontása...</translation>
+ </message>
+ <message>
+ <source>Checksum mismatch detected for &quot;%1&quot;.</source>
+ <translation>Ellenőrző összeg eltérést észlelt &quot;%1&quot; fájlnál.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Hiba &quot;%1&quot; archívum kibontása közben: %2</translation>
+ </message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Információk lekérése távoli tárolóból...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Metainformációk lekérése távoli tárolóból...</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PackageManagerCore</name>
+ <message>
+ <source>Error writing Maintenance Tool</source>
+ <translation>Hiba a karbantartó eszköz írásakor</translation>
+ </message>
+ <message>
+ <source>Downloading packages...</source>
+ <translation>Csomagok letöltése...</translation>
+ </message>
+ <message>
+ <source>Installation canceled by user.</source>
+ <translation>Telepítést a felhasználó megszakította.</translation>
+ </message>
+ <message>
+ <source>All downloads finished.</source>
+ <translation>Minden letöltés befejeződött.</translation>
+ </message>
+ <message>
+ <source>Canceling the Installer</source>
+ <translation>Telepítés Megszakítása</translation>
+ </message>
+ <message>
+ <source>Authentication Error</source>
+ <translation>Authentikációs Hiba</translation>
+ </message>
+ <message>
+ <source>Some components could not be removed completely because administrative rights could not be acquired: %1.</source>
+ <translation>Egyes összetevőket nem sikerült teljesen eltávolítani, mert nem sikerült megszerezni a rendszergazdai jogokat: %1.</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Ismeretlen hiba.</translation>
+ </message>
+ <message>
+ <source>Some components could not be removed completely because an unknown error happened.</source>
+ <translation>Bizonyos komponenseket nem lehetett teljesen eltávolítani, mert ismeretlen hiba történt.</translation>
+ </message>
+ <message>
+ <source>User input is required but the output device is not associated with a terminal.</source>
+ <translation>Felhasználói bevitel szükséges, de a kimeneti eszköz nincs terminálhoz társítva.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hiba</translation>
+ </message>
+ <message>
+ <source>The directory you selected already exists and contains an installation. Choose a different target for installation.</source>
+ <translation>A kiválasztott könyvtár már létezik, és tartalmaz egy telepítést. Válasszon másik célt a telepítéshez.</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Figyelmeztetés</translation>
+ </message>
+ <message>
+ <source>You have selected an existing, non-empty directory for installation.
+Note that it will be completely wiped on uninstallation of this application.
+It is not advisable to install into this directory as installation might fail.
+Do you want to continue?</source>
+ <translation>Meglévő, nem üres könyvtárat választott ki a telepítéshez.
+Ne feledje, hogy az alkalmazás eltávolításakor teljesen törlődik.
+Nem tanácsos ebbe a könyvtárba telepíteni, mert a telepítés sikertelen lehet.
+Kívánja folytatni?</translation>
+ </message>
+ <message>
+ <source>You have selected an existing file or symlink, please choose a different target for installation.</source>
+ <translation>Létező fájlt vagy szimbólikus linket választott, adjon meg egy másik telepítési célt. </translation>
+ </message>
+ <message>
+ <source>The installation path cannot be empty, please specify a valid directory.</source>
+ <translation>A telepítési útvonal nem lehet üres, adjon meg egy érvényes könyvtárat.</translation>
+ </message>
+ <message>
+ <source>The installation path cannot be relative, please specify an absolute path.</source>
+ <translation>A telepítési útvonal nem lehet relatív, adjon meg egy abszolút elérési utat.</translation>
+ </message>
+ <message>
+ <source>The path or installation directory contains non ASCII characters. This is currently not supported! Please choose a different path or installation directory.</source>
+ <translation>Az útvonal vagy a telepítési könyvtár nem ASCII karaktereket tartalmaz. Ez jelenleg nem támogatott! Válasszon másik elérési utat vagy telepítési könyvtárat.</translation>
+ </message>
+ <message>
+ <source>As the install directory is completely deleted, installing in %1 is forbidden.</source>
+ <translation>Mivel a telepítési könyvtár teljesen törlődik, tilos %1 könyvtárban telepíteni.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is too long, please make sure to specify a valid path.</source>
+ <translation>A megadott útvonal túl hosszú. Ügyeljen arra, hogy érvényes útvonalat adjon meg.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is not valid, please make sure to specify a valid target.</source>
+ <translation>A megadott útvonal érvénytelen. Ügyeljen arra, hogy érvényes célt adjon meg.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is not valid, please make sure to specify a valid drive.</source>
+ <translation>A megadott útvonal érvénytelen. Ügyeljen arra, hogy érvényes meghajtót adjon meg.</translation>
+ </message>
+ <message>
+ <source>The installation path must not end with &apos;.&apos;, please specify a valid directory.</source>
+ <translation>A telepítési útvonal nem végződhet &apos;.&apos; -al. Adjon meg egy érvényes könyvtárat.</translation>
+ </message>
+ <message>
+ <source>The installation path must not contain &quot;%1&quot;, please specify a valid directory.</source>
+ <translation>A telepítési útvonal nem tartalmazhat &quot;%1&quot; értéket. Adjon meg egy érvényes könyvtárat.</translation>
+ </message>
+ <message>
+ <source>Application not running in Package Manager mode.</source>
+ <translation>Az alkalmazás nem fut csomagkezelő módban.</translation>
+ </message>
+ <message>
+ <source>No installed packages found.</source>
+ <translation>Nem található telepített csomag.</translation>
+ </message>
+ <message>
+ <source>Application running in Uninstaller mode.</source>
+ <translation>Az alkalmazás eltávolítás (uninstall) módban fut.</translation>
+ </message>
+ <message>
+ <source>There is an important update available, please run the updater first.</source>
+ <translation>Van egy fontos frissítés, először futtassa a frissítőt.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve all dependencies.</source>
+ <translation>Nem lehet minden függőséget feloldani.</translation>
+ </message>
+ <message>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>%1 telepítése nem sikerült. A komponens nem található.</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>Nem sikerült telepíteni %1 komponenst. A komponens csak %2 automatikus függőségeként van telepítve. </translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>Nem sikerült telepíteni %1 komponenst. A komponens nem válaszható ki, vagyis kell választania az egyik alkomponenst.</translation>
+ </message>
+ <message>
+ <source>Component %1 already installed</source>
+ <translation>%1 komponens már telepítve van.</translation>
+ </message>
+ <message>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>%1 telepítése nem sikerült. A komponens %2 virtuális komponens leszármazottja. </translation>
+ </message>
+ <message>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>%1 telepítése nem sikerült. A komponens virtuális.</translation>
+ </message>
+ <message>
+ <source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
+ <translation>A parancssorból történő futtatás során nem növelhetők a hozzáférési jogok. Indítsa újra az alkalmazást rendszergazdaként.</translation>
+ </message>
+ <message>
+ <source>Error while elevating access rights.</source>
+ <translation>Hiba a hozzáférési jogok növelésekor.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files and the installation. %1 are available, while the minimum required is %2.</source>
+ <translation>Nincs elég lemezterület az ideiglenes fájlok és a telepítés tárolására. %1 elérhető, miközben minimum %2 szükséges.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
+ <translation>Nincs elég lemezterület az összes kiválasztott komponens tárolásához! %1 elérhető, miközben minimum %2 szükséges.</translation>
+ </message>
+ <message>
+ <source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
+ <translation>Úgy tűnik, hogy a telepítéshez kiválasztott kötet elegendő helyet biztosít a telepítéshez, de a kötet helyének kevesebb mint 1%-a áll majd rendelkezésre a telepítés befejeztével.</translation>
+ </message>
+ <message>
+ <source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 100 MB available afterwards.</source>
+ <translation>Úgy tűnik, hogy a telepítéshez kiválasztott kötet elegendő helyet biztosít a telepítéshez, de később kevesebb mint 100 MB áll rendelkezésre.</translation>
+ </message>
+ <message>
+ <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
+ <translation>A becsült telepítőméret %1 meghaladná a támogatott futtatható mérethatárt %2. Előfordulhat, hogy az alkalmazás nem fog elindulni.</translation>
+ </message>
+ <message>
+ <source>Installation will use %1 of disk space.</source>
+ <translation>Telepítés %1 lemezterületet fog igénybe venni.</translation>
+ </message>
+ <message>
+ <source>Invalid</source>
+ <translation>Érvénytelen</translation>
+ </message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PackageManagerCorePrivate</name>
+ <message>
+ <source>Unresolved dependencies</source>
+ <translation>Feloldatlan függőségek</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hiba</translation>
+ </message>
+ <message>
+ <source>Access error</source>
+ <translation>Hozzáférési hiba</translation>
+ </message>
+ <message>
+ <source>Format error</source>
+ <translation>Formázási hiba</translation>
+ </message>
+ <message>
+ <source>Cannot write installer configuration to %1: %2</source>
+ <translation>Telepítő konfigurációja nem írható a következőre: %1: %2</translation>
+ </message>
+ <message>
+ <source>Stop Processes</source>
+ <translation>Folyamatok leállítása</translation>
+ </message>
+ <message>
+ <source>These processes should be stopped to continue:
+
+%1</source>
+ <translation>Ezeket a folyamatokat le kell állítani a folytatáshoz: %1</translation>
+ </message>
+ <message>
+ <source>Installation canceled by user</source>
+ <translation>Telepítést a felhasználó megszakította</translation>
+ </message>
+ <message>
+ <source>Retry count exceeded</source>
+ <translation>Újrapróbálkozások száma túllépve</translation>
+ </message>
+ <message>
+ <source>Writing maintenance tool.</source>
+ <translation>Karbantartó eszköz írása.</translation>
+ </message>
+ <message>
+ <source>Failed to seek in file %1: %2</source>
+ <translation>Nem sikerült keresni %1 fájlban: %2</translation>
+ </message>
+ <message>
+ <source>Maintenance tool is not a bundle</source>
+ <translation>Karbantartó eszköz nem egy csomag</translation>
+ </message>
+ <message>
+ <source>Cannot remove data file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; adatfájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool data to %1: %2</source>
+ <translation>Nem lehet írni a karbantartó eszköz adatait %1 fájlba: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool to &quot;%1&quot;: %2</source>
+ <translation>Karbantartó eszközt nem lehet írni &quot;%1&quot; fájlba: %2 </translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani az ideiglenes &quot;%1&quot; adatfájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool binary data to %1: %2</source>
+ <translation>A karbantartó eszköz bináris adatai nem írhatók %1 fájlba: %2</translation>
+ </message>
+ <message>
+ <source>Writing offline base binary.</source>
+ <translation>Offline alap bináris írása.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Nem sikerült létrehozni &quot;%1&quot; könyvtárat.</translation>
+ </message>
+ <message>
+ <source>Cannot write offline binary to &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült az offline bináris írása &quot;%1&quot; fájlba: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary file &quot;%1&quot;: %2</source>
+ <translation>Nem sikerült eltávolítani az ideiglenes &quot;%1&quot; fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Variable &apos;TargetDir&apos; not set.</source>
+ <translation>&apos;TargetDir&apos; változó nincs beállítva.</translation>
+ </message>
+ <message>
+ <source>Preparing the installation...</source>
+ <translation>Telepítés előkészítése...</translation>
+ </message>
+ <message>
+ <source>It is not possible to install from network location</source>
+ <translation>Telepítés nem lehetséges hálózati helyről</translation>
+ </message>
+ <message>
+ <source>Creating local repository</source>
+ <translation>Helyi tároló létrehozása</translation>
+ </message>
+ <message>
+ <source>Creating Maintenance Tool</source>
+ <translation>Karbantartó eszköz létrehozása</translation>
+ </message>
+ <message>
+ <source>Installation finished!</source>
+ <translation>Telepítés befejeződött!</translation>
+ </message>
+ <message>
+ <source>Installation aborted!</source>
+ <translation>Telepítés megszakítva!</translation>
+ </message>
+ <message>
+ <source>It is not possible to run that operation from a network location</source>
+ <translation>Ezt a műveletet nem lehet hálózati helyről futtatni</translation>
+ </message>
+ <message>
+ <source>Removing deselected components...</source>
+ <translation>Kijelölt összetevők eltávolítása...</translation>
+ </message>
+ <message>
+ <source>Update finished!</source>
+ <translation>Frissítés befejeződött!</translation>
+ </message>
+ <message>
+ <source>Update aborted!</source>
+ <translation>Frissítés megszakítva!</translation>
+ </message>
+ <message>
+ <source>Removal completed successfully.</source>
+ <translation>Eltávolítás sikeresen befejeződött.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>Eltávolítás megszakítva.</translation>
+ </message>
+ <message>
+ <source>Cannot create target directory for installer.</source>
+ <translation>Nem lehet létrehozni a célkönyvtárat a telepítő számára.</translation>
+ </message>
+ <message>
+ <source>Preparing offline generation...</source>
+ <translation>Offline generáció előkészítése...</translation>
+ </message>
+ <message>
+ <source>Preparing installer configuration...</source>
+ <translation>Telepítő konfigurációjának előkészítése...</translation>
+ </message>
+ <message>
+ <source>Creating the installer...</source>
+ <translation>Telepítő létrehozása...</translation>
+ </message>
+ <message>
+ <source>Failed to create offline installer. %1</source>
+ <translation>Nem sikerült létrehozni az offline telepítőt. %1</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary directory &quot;%1&quot;.</source>
+ <translation>Nem sikerült eltávolítani az ideiglenes &quot;%1&quot; fájlt.</translation>
+ </message>
+ <message>
+ <source>Offline generation completed successfully.</source>
+ <translation>Offline generálás sikeresen befejeződött.</translation>
+ </message>
+ <message>
+ <source>Offline generation aborted!</source>
+ <translation>Offline generáció megszakítva!</translation>
+ </message>
+ <message>
+ <source>Installing component %1</source>
+ <translation>%1 összetevő telepítése</translation>
+ </message>
+ <message>
+ <source>Installer Error</source>
+ <translation>Telepítői Hiba</translation>
+ </message>
+ <message>
+ <source>Error during installation process (%1):
+%2</source>
+ <translation>Hiba a telepítési folyamat során (%1):
+%2 </translation>
+ </message>
+ <message>
+ <source>Done</source>
+ <translation>Kész</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>Nem lehet előkészíteni az eltávolítást</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>Nem lehet elindítani az eltávolítást</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>Hiba az eltávolítási folyamat során:
+%1</translation>
+ </message>
+ <message>
+ <source>Unknown error</source>
+ <translation>Ismeretlen hiba</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve remote tree %1.</source>
+ <translation>Nem sikerült lekérni %1 távoli fát.</translation>
+ </message>
+ <message>
+ <source>Failure to read packages from %1.</source>
+ <translation>Nem sikerült beolvasni a csomagokat %1-ből.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve meta information: %1</source>
+ <translation>Nem sikerült lekérni metaadatokat: %1</translation>
+ </message>
+ <message>
+ <source>Cannot find any update source information.</source>
+ <translation>Nem található frissítési forrás információ.</translation>
+ </message>
+ <message>
+ <source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>Függőségi ciklus észlelve &quot;%1&quot; és &quot;%2&quot; összetevők között.</translation>
+ </message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PackageManagerGui</name>
+ <message>
+ <source>%1 Setup</source>
+ <translation>%1 beállítása</translation>
+ </message>
+ <message>
+ <source>Maintain %1</source>
+ <translation>%1 karbantartása</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the installation process?</source>
+ <translation>Meg akarja szakítani a telepítési folyamatot?</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>Meg akarja szakítani az eltávolítási folyamatot?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the installer application?</source>
+ <translation>Kilép a telepítő alkalmazásból?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the uninstaller application?</source>
+ <translation>Kilép az eltávolító alkalmazásból?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the maintenance application?</source>
+ <translation>Kilép a karbantartó alkalmazásból?</translation>
+ </message>
+ <message>
+ <source>%1 Question</source>
+ <translation>%1 kérdés</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>Beállítások</translation>
+ </message>
+ <message>
+ <source>Specify proxy settings and configure repositories for add-on components.</source>
+ <translation>Adja meg a proxybeállításokat, és konfigurálja a tárolókat a kiegészítő komponensekhez.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hiba</translation>
+ </message>
+ <message>
+ <source>It is not possible to install from network location.
+Please copy the installer to a local drive</source>
+ <translation>A telepítés nem lehetséges hálózati helyről.
+Másolja a telepítőt egy helyi meghajtóra</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PerformInstallationForm</name>
+ <message>
+ <source>&amp;Show Details</source>
+ <translation>Részletek megjeleníté&amp;se</translation>
+ </message>
+ <message>
+ <source>&amp;Hide Details</source>
+ <translation>Részletek el&amp;rejtése</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PerformInstallationPage</name>
+ <message>
+ <source>U&amp;ninstall</source>
+ <translation>&amp;Eltávolítás</translation>
+ </message>
+ <message>
+ <source>Uninstalling %1</source>
+ <translation>%1 eltávolítása</translation>
+ </message>
+ <message>
+ <source>&amp;Update</source>
+ <translation>&amp;Frissítés</translation>
+ </message>
+ <message>
+ <source>Updating components of %1</source>
+ <translation>%1 komponenseinek frissítése </translation>
+ </message>
+ <message>
+ <source>&amp;Install</source>
+ <translation>&amp;Telepítés</translation>
+ </message>
+ <message>
+ <source>Installing %1</source>
+ <translation>%1 telepítése</translation>
+ </message>
+ <message>
+ <source>Installing</source>
+ <translation>Telepítés</translation>
+ </message>
+ <message>
+ <source>Updating</source>
+ <translation>Frissítés</translation>
+ </message>
+ <message>
+ <source>Uninstalling</source>
+ <translation>Eltávolítás</translation>
+ </message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ProxyCredentialsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialógus</translation>
+ </message>
+ <message>
+ <source>The proxy %1 requires a username and password.</source>
+ <translation>%1 proxy felhasználónevet és jelszót igényel.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>Felhasználónév:</translation>
+ </message>
+ <message>
+ <source>Username</source>
+ <translation>Felhasználónév</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>Jelszó:</translation>
+ </message>
+ <message>
+ <source>Password</source>
+ <translation>Jelszó</translation>
+ </message>
+ <message>
+ <source>Proxy Credentials</source>
+ <translation>Proxy Hitelesítések</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::QFileDialogProxy</name>
+ <message>
+ <source>User input is required but the output device is not associated with a terminal.</source>
+ <translation>Felhasználói bevitel szükséges, de a kimeneti eszköz nincs terminálhoz társítva.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ReadyForInstallationPage</name>
+ <message>
+ <source>U&amp;ninstall</source>
+ <translation>&amp;Eltávolítás</translation>
+ </message>
+ <message>
+ <source>Ready to Uninstall</source>
+ <translation>Eltávolításra kész</translation>
+ </message>
+ <message>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <translation>A telepítő készen áll %1 eltávolítására a számítógépről.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;%2 programkönyvtár teljesen törlődik&lt;/font&gt;, beleértve a könyvtár teljes tartalmát!</translation>
+ </message>
+ <message>
+ <source>U&amp;pdate</source>
+ <translation>&amp;Frissítés</translation>
+ </message>
+ <message>
+ <source>Ready to Update Packages</source>
+ <translation>Készen áll a csomagok frissítésére</translation>
+ </message>
+ <message>
+ <source>All required information is now available to begin updating your installation.</source>
+ <translation>A telepítő készen áll a telepítés frissítésére.</translation>
+ </message>
+ <message>
+ <source>&amp;Install</source>
+ <translation>&amp;Telepítés</translation>
+ </message>
+ <message>
+ <source>Ready to Install</source>
+ <translation>Telepítésre készen</translation>
+ </message>
+ <message>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
+ <translation>Telepítő készen áll %1 számítógépre történő telepítésére.</translation>
+ </message>
+ <message>
+ <source>Ready to Update</source>
+ <translation>Frissítésre kész</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RegisterFileTypeOperation</name>
+ <message>
+ <source>Registering file types is only supported on Windows.</source>
+ <translation>A fájltípusok regisztrálása csak Windows rendszeren támogatott.</translation>
+ </message>
+ <message>
+ <source>Register File Type: Invalid arguments</source>
+ <translation>Regisztrációs fájl típusa: Érvénytelen argumentumok</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RemoteObject</name>
+ <message>
+ <source>Cannot read all data after sending command: %1. Bytes expected: %2, Bytes received: %3. Error: %4</source>
+ <translation>Nem lehet elolvasni az összes adatot a parancs elküldése után: %1. Várható bájtok: %2, fogadott bájtok: %3. Hiba: %4</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ReplaceOperation</name>
+ <message>
+ <source>Current search argument calling &quot;%1&quot; with empty search argument is not supported.</source>
+ <translation>A jelenlegi keresési &quot;%1&quot; argumentum üres keresési argumentummal nem támogatott.</translation>
+ </message>
+ <message>
+ <source>Current mode argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use string or regex.</source>
+ <translation>Az aktuális mód &quot;%1&quot; argumentuma &quot;%2&quot; argumentumokkal nem támogatott. Kérjük, használjon string vagy regex kifejezést.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Resource</name>
+ <message>
+ <source>Cannot open resource %1 for reading.</source>
+ <translation>Nem sikerült megnyitni %1 forrást olvasásra.</translation>
+ </message>
+ <message>
+ <source>Read failed after %1 bytes: %2</source>
+ <translation>Sikertelen olvasás %1 bájt után: %2</translation>
+ </message>
+ <message>
+ <source>Write failed after %1 bytes: %2</source>
+ <translation>Sikertelen írás %1 bájt után: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RestartPage</name>
+ <message>
+ <source>Finished the %1 Setup</source>
+ <translation>%1 telepítő varázsló befejezése</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ScriptEngine</name>
+ <message>
+ <source>Cannot open script file at %1: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; szkript fájlt: %2</translation>
+ </message>
+ <message>
+ <source>Exception while loading the component script &quot;%1&quot;: %2</source>
+ <translation>Kivétel a komponens &quot;%1&quot; szkript betöltése közben: %2</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Ismeretlen hiba.</translation>
+ </message>
+ <message>
+ <source>on line number: </source>
+ <translation>sorszámon: </translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::SelfRestartOperation</name>
+ <message>
+ <source>Installer object needed in operation %1 is empty.</source>
+ <translation>%1 művelethez szükséges telepítő objektum üres.</translation>
+ </message>
+ <message>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>Önindítás: Csak frissítő vagy csomagkezelő módban érvényes.</translation>
+ </message>
+ <message>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>Önindítás: Érvénytelen argumentumok</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ServerAuthenticationDialog</name>
+ <message>
+ <source>Server Requires Authentication</source>
+ <translation>Szerver Authentikációt Igényel</translation>
+ </message>
+ <message>
+ <source>You need to supply a username and password to access this site.</source>
+ <translation>Az oldal eléréséhez felhasználónevet és jelszót kell megadnia.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>Felhasználónév:</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>Jelszó:</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 itt: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::SettingsOperation</name>
+ <message>
+ <source>Missing argument(s) &quot;%1&quot; calling %2 with arguments &quot;%3&quot;.</source>
+ <translation>Hiányzó &quot;%1&quot; argumentum(ok) %2 hívása &quot;%3&quot; argumentumokkal.</translation>
+ </message>
+ <message>
+ <source>Current method argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use set, remove, add_array_value, or remove_array_value.</source>
+ <translation>A jelenlegi metódus argumentum &quot;%1&quot; hívása &quot;%2&quot; argumentumokkal nem támogatott. Kérjük, használja a set, remove, add_array_value vagy remove_array_value értéket.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::SimpleMoveFileOperation</name>
+ <message>
+ <source>None of the arguments can be empty: source &quot;%1&quot;, target &quot;%2&quot;.</source>
+ <translation>Egyik argumentum sem lehet üres: forrás &quot;%1&quot;, cél &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot move file from &quot;%1&quot; to &quot;%2&quot;, because the target path exists and is not removable.</source>
+ <translation>Nem sikerült átmozgatni &quot;%1&quot; fájlt &quot;%2&quot; fájlba, mert a célútvonal létezik és nem eltávolítható.</translation>
+ </message>
+ <message>
+ <source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Nem sikerült átmozgatni &quot;%1&quot; fájlt &quot;%2&quot; fájlba: %3</translation>
+ </message>
+ <message>
+ <source>Moving file &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot; fájl áthelyezése &quot;%2&quot; fájlba.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::StartMenuDirectoryPage</name>
+ <message>
+ <source>Start Menu shortcuts</source>
+ <translation>Startmenü parancsikonok</translation>
+ </message>
+ <message>
+ <source>Select the Start Menu in which you would like to create the program&apos;s shortcuts. You can also enter a name to create a new directory.</source>
+ <translation>Válassza ki a Start menüt, amelyben a program parancsikonjait szeretné létrehozni. Új könyvtár létrehozásához nevet is megadhat.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::TargetDirectoryPage</name>
+ <message>
+ <source>Installation Folder</source>
+ <translation>Telepítési mappa</translation>
+ </message>
+ <message>
+ <source>Please specify the directory where %1 will be installed.</source>
+ <translation>Kérem adja meg azt a könyvtárat, ahová %1 telepítésre kerül.</translation>
+ </message>
+ <message>
+ <source>Alt+R</source>
+ <comment>Browse file system to choose a file</comment>
+ <translation>Alt+R</translation>
+ </message>
+ <message>
+ <source>B&amp;rowse...</source>
+ <translation>&amp;Böngészés...</translation>
+ </message>
+ <message>
+ <source>Browse file system to choose the installation directory.</source>
+ <translation>A fájlrendszer tallózásával válassza ki a telepítési könyvtárat.</translation>
+ </message>
+ <message>
+ <source>Select Installation Folder</source>
+ <translation>Telepítési Mappa Kiválasztása</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::TestRepository</name>
+ <message>
+ <source>Missing package manager core engine.</source>
+ <translation>Hiányzik a csomagkezelő alapmotorja.</translation>
+ </message>
+ <message>
+ <source>Empty repository URL.</source>
+ <translation>Üres tároló URL.</translation>
+ </message>
+ <message>
+ <source>Download canceled.</source>
+ <translation>Letöltés megszakítva.</translation>
+ </message>
+ <message>
+ <source>Timeout while testing repository &quot;%1&quot;.</source>
+ <translation>Időtúllépés &quot;%1&quot; tároló tesztelése közben.</translation>
+ </message>
+ <message>
+ <source>Cannot parse Updates.xml: %1</source>
+ <translation>Updates.xml elemzése nem sikerült: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open Updates.xml for reading: %1</source>
+ <translation>Nem sikerült megnyitni Updates.xml fájlt olvasásra: %1</translation>
+ </message>
+ <message>
+ <source>Authentication failed.</source>
+ <translation>Sikertelen volt az authentikáció.</translation>
+ </message>
+ <message>
+ <source>Unknown error while testing repository &quot;%1&quot;.</source>
+ <translation>Ismeretlen hiba &quot;%1&quot; tároló tesztelése közben.</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Error acquiring admin rights</source>
+ <translation>Hiba történt az adminisztrátori jogok megszerzése során</translation>
+ </message>
+ <message>
+ <source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
+ <translation>Győződjön meg arról, hogy a jelenlegi felhasználó olvasási hozzáféréssel rendelkezik a &quot;%1&quot; fájlhoz, vagy futtassa %2 -t rendszergazdaként. </translation>
+ </message>
+ <message>
+ <source>Another %1 instance is already running. Wait until it finishes, close it, or restart your system.</source>
+ <translation>Egy másik %1 példány már fut. Várjon, amíg befejeződik, zárja be vagy indítsa újra a rendszert.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as updater.</source>
+ <translation>Nem lehet elindítani a telepítőt csomagfrissítésként.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as package manager.</source>
+ <translation>Nem lehet elindítani a telepítőt csomagkezelőként.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as uninstaller.</source>
+ <translation>Nem lehet elindítani a telepítőt csomageltávolítóként.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;addRepository&apos;.</source>
+ <translation>Üres tárolólista az &apos;addRepository&apos; opcióhoz.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;addTempRepository&apos;.</source>
+ <translation>Üres tárolólista az &apos;addTempRepository&apos; opcióhoz.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;setTempRepository&apos;.</source>
+ <translation>Üres tárolólista az &apos;setTempRepository&apos; opcióhoz.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
+ <translation>Üres tárolólista az &apos;installCompressedRepository&apos; opcióhoz.</translation>
+ </message>
+ <message>
+ <source>The file %1 does not exist.</source>
+ <translation>%1 fájl nem létezik.</translation>
+ </message>
+ <message>
+ <source>Arguments missing for option %1</source>
+ <translation>Hiányzó argumentumok %1 opcióhoz</translation>
+ </message>
+ <message>
+ <source>Invalid button value %1 </source>
+ <translation>Érvénytelen nyomógomb érték %1 </translation>
+ </message>
+ <message>
+ <source>Incorrect arguments for %1</source>
+ <translation>Hibás argumentumok %1-hez</translation>
+ </message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>RemoteClient</name>
+ <message>
+ <source>Cannot get authorization.</source>
+ <translation>Nem lehet authorizációt kérni.</translation>
+ </message>
+ <message>
+ <source>Cannot get authorization that is needed for continuing the installation.
+
+Please start the setup program as a user with the appropriate rights,
+or accept the elevation of access rights if being asked.</source>
+ <translation>Nem szerezhető be a telepítés folytatásához szükséges engedély.
+
+Kérem indítsa el a telepítőprogramot a megfelelő jogokkal rendelkező felhasználóként,
+vagy fogadja el a hozzáférési jogok emelését, ha kérik.</translation>
+ </message>
+ <message>
+ <source>Cannot get authorization that is needed for continuing the installation.
+ Either abort the installation or use the fallback solution by running
+
+%1
+
+as a user with the appropriate rights and then clicking OK.</source>
+ <translation>Nem szerezhető be a telepítés folytatásához szükséges engedély.
+ Vagy szakítsa meg a telepítést, vagy futtassa a tartalék megoldást
+
+%1
+
+a megfelelő jogokkal rendelkező felhasználóként, majd kattintson az OK gombra.</translation>
+ </message>
+</context>
+<context>
+ <name>ResourceCollectionManager</name>
+ <message>
+ <source>Cannot open resource %1: %2</source>
+ <translation>Nem sikerült megnyitni %1 forrást: %2</translation>
+ </message>
+</context>
+<context>
+ <name>Settings</name>
+ <message>
+ <source>Cannot open settings file %1 for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; beállítás fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Categories</source>
+ <translation type="unfinished">Válasszon Kategóriákat</translation>
+ </message>
+</context>
+<context>
+ <name>SettingsDialog</name>
+ <message>
+ <source>Settings</source>
+ <translation>Beállítások</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Hálózat</translation>
+ </message>
+ <message>
+ <source>No proxy</source>
+ <translation>Nincs proxy</translation>
+ </message>
+ <message>
+ <source>System proxy settings</source>
+ <translation>Rendszer proxy beállítások</translation>
+ </message>
+ <message>
+ <source>Manual proxy configuration</source>
+ <translation>Manuális proxy beállítások</translation>
+ </message>
+ <message>
+ <source>HTTP proxy:</source>
+ <translation>HTTP proxy:</translation>
+ </message>
+ <message>
+ <source>Port:</source>
+ <translation>Port:</translation>
+ </message>
+ <message>
+ <source>FTP proxy:</source>
+ <translation>FTP proxy:</translation>
+ </message>
+ <message>
+ <source>Repositories</source>
+ <translation>Tárolók</translation>
+ </message>
+ <message>
+ <source>Add Username and Password for authentication if needed.</source>
+ <translation>Adjon meg felhasználónevet és jelszót az authentikációhoz ha szükséges.</translation>
+ </message>
+ <message>
+ <source>Use temporary repositories only</source>
+ <translation>Csak ideiglenes tárolókat használjon</translation>
+ </message>
+ <message>
+ <source>Add</source>
+ <translation>Hozzáad</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Eltávolít</translation>
+ </message>
+ <message>
+ <source>Test</source>
+ <translation>Tesztel</translation>
+ </message>
+ <message>
+ <source>Select All</source>
+ <translation>Mindent kijelöl</translation>
+ </message>
+ <message>
+ <source>Deselect All</source>
+ <translation>Összes kijelölés megszüntetése</translation>
+ </message>
+ <message>
+ <source>Show Passwords</source>
+ <translation>Jelszavak megjelenítése</translation>
+ </message>
+ <message>
+ <source>Check this to use repository during fetch.</source>
+ <translation>Jelölje meg ezt a tároló használatához a letöltéshez.</translation>
+ </message>
+ <message>
+ <source>Add the username to authenticate on the server.</source>
+ <translation>Adja meg a felhasználónevet a szerver authentikációhoz.</translation>
+ </message>
+ <message>
+ <source>Add the password to authenticate on the server.</source>
+ <translation>Adja meg a jelszót a szerver authentikációhoz.</translation>
+ </message>
+ <message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>A szerver URL címe, amely érvényes tárolót tartalmaz.</translation>
+ </message>
+ <message>
+ <source>An error occurred while testing this repository.</source>
+ <translation>Hiba történt a tároló tesztelése közben.</translation>
+ </message>
+ <message>
+ <source>The repository was tested successfully.</source>
+ <translation>A tároló sikeresen letesztelve.</translation>
+ </message>
+ <message>
+ <source>Do you want to disable the repository?</source>
+ <translation>Kívánja a tárolót kikapcsolni?</translation>
+ </message>
+ <message>
+ <source>Do you want to enable the repository?</source>
+ <translation>Kívánja a tárolót bekapcsolni?</translation>
+ </message>
+ <message>
+ <source>Hide Passwords</source>
+ <translation>Jelszavak Elrejtése</translation>
+ </message>
+ <message>
+ <source>Use</source>
+ <translation>Használ</translation>
+ </message>
+ <message>
+ <source>Username</source>
+ <translation>Felhasználónév</translation>
+ </message>
+ <message>
+ <source>Password</source>
+ <translation>Jelszó</translation>
+ </message>
+ <message>
+ <source>Repository</source>
+ <translation>Tároló</translation>
+ </message>
+ <message>
+ <source>Default repositories</source>
+ <translation>Alapértelmezett tárolók</translation>
+ </message>
+ <message>
+ <source>Temporary repositories</source>
+ <translation>Ideiglenes tárolók</translation>
+ </message>
+ <message>
+ <source>User defined repositories</source>
+ <translation>Felhasználó által megadott tárolók</translation>
+ </message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UpdateOperation</name>
+ <message>
+ <source>Cannot write to registry path %1.</source>
+ <translation>Nem lehet írni %1 regisztrációs útvonalra.</translation>
+ </message>
+ <message>
+ <source>Registry path %1 is not writable.</source>
+ <translation>%1 regisztrációs útvonal nem írható.</translation>
+ </message>
+ <message>
+ <source>exactly %1</source>
+ <translation>pontosan %1</translation>
+ </message>
+ <message>
+ <source>at least %1</source>
+ <translation>legalább %1</translation>
+ </message>
+ <message>
+ <source>not more than %1</source>
+ <translation>nem több mint %1</translation>
+ </message>
+ <message>
+ <source>%1 or %2</source>
+ <translation>%1 vagy %2</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 %2-be</translation>
+ </message>
+ <message numerus="yes">
+ <source>Invalid arguments in %1: %n arguments given, %2 arguments expected.</source>
+ <translation>
+ <numerusform>Érvénytelen argumentumok %1-ban: %n argumentum adott, %2 argumentum elvárt.</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Invalid arguments in %1: %n arguments given, %2 arguments expected in the form: %3.</source>
+ <translation>
+ <numerusform>Érvénytelen argumentumok %1-ban: %n argumentum adott, %2 argumentum elvárt a következő formában: %3.</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Renaming file &quot;%1&quot; to &quot;%2&quot; failed: %3</source>
+ <translation>&quot;%1&quot; fájl átnevezése &quot;%2&quot; fájlra nem sikerült: %3</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt írásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nem sikerült megnyitni &quot;%1&quot; fájlt olvasásra: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/src/sdk/translations/ifw_it.ts b/src/sdk/translations/ifw_it.ts
index 4cb0841b7..5f08dc1a7 100644
--- a/src/sdk/translations/ifw_it.ts
+++ b/src/sdk/translations/ifw_it.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Impossibile trovare la dipendenza mancante &quot;%1&quot; per &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -306,6 +318,10 @@
<source>Try again</source>
<translation>Riprova</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -489,10 +505,6 @@
<translation>Impossibile leggere &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Errore di analisi in %1 a %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Elemento radice %1 imprevisto, dovrebbe essere &quot;Updates&quot;.</translation>
</message>
@@ -744,6 +756,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -752,18 +768,6 @@
<translation>I componenti non possono avere figli in modalità updater.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Impossibile aprire il file di interfaccia utente richiesto &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Impossibile caricare il file di interfaccia utente richiesto &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Impossibile aprire il file di licenza richiesto &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Errore</translation>
</message>
@@ -784,8 +788,28 @@
<translation type="unfinished"></translation>
</message>
<message>
- <source>There was an error loading the selected component. This component cannot be updated.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Impossibile aprire il file di interfaccia utente richiesto &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Impossibile caricare il file di interfaccia utente richiesto &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Impossibile aprire il file di licenza richiesto &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -834,42 +858,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>&amp;Predefinito</translation>
+ <source>Default</source>
+ <translation>Predefinito</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Reimposta</translation>
+ <source>Reset</source>
+ <translation>Reimposta</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>&amp;Seleziona tutto</translation>
+ <source>Select All</source>
+ <translation>Seleziona tutto</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Deseleziona tutto</translation>
+ <source>Deselect All</source>
+ <translation>Deseleziona tutto</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Sfoglia file QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation type="unfinished"></translation>
</message>
@@ -898,37 +918,41 @@
<translation>Selezionare i componenti che si desidera disinstallare.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Selezionare i componenti da installare. Deselezionare i componenti installati per disinstallarli. I componenti già installati non verranno aggiornati.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Selezionare i componenti da installare. Deselezionare i componenti installati per disinstallarli.&lt;br&gt;I componenti già installati non verranno aggiornati.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Filter the enabled repository categories</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+F</translation>
+ <source>Search</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>&amp;Sfoglia file QBSP</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
+ <source>Select</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Errore</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -945,12 +969,8 @@
<translation>Impossibile salvare l&apos;output di &quot;%1” in un valore chiave del programma di installazione vuoto.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Il file &quot;%1&quot; non esiste o non è un file binario eseguibile.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>L&apos;esecuzione di &quot;%1&quot; ha causato un arresto anomalo.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -1087,6 +1107,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Impossibile rimuovere la directory &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>Impossibile creare l&apos;archivio &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1151,6 +1179,62 @@ Errore durante il caricamento di %2</translation>
<source>Cannot find component for %1.</source>
<translation>Impossibile trovare il componente per %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 di %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 scaricato.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n giorno/i, </numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n ora/e, </numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuto/i</numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n secondo/i</numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 rimanente.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - tempo rimanente sconosciuto.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1220,21 +1304,6 @@ Errore durante il caricamento di %2</translation>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <message>
- <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
- <translation>Impossibile aprire l’archivio &quot;%1&quot; per la lettura: %2</translation>
- </message>
- <message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Errore durante l&apos;estrazione dell&apos;archivio &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Rilevata eccezione sconosciuta durante l&apos;estrazione di &quot;%1&quot;.</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1303,7 +1372,7 @@ Errore durante il caricamento di %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Completamento della procedura guidata %1</translation>
</message>
<message>
@@ -1311,7 +1380,7 @@ Errore durante il caricamento di %2</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Fare clic su %1 per uscire dalla procedura guidata %2.</translation>
</message>
<message>
@@ -1323,7 +1392,7 @@ Errore durante il caricamento di %2</translation>
<translation>Eseguire %1 ora.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Procedura guidata %1 non riuscita.</translation>
</message>
</context>
@@ -1364,15 +1433,19 @@ Errore durante il caricamento di %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Impossibile creare la directory &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Installazione - %1</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Installazione guidata di %1.</translation>
</message>
<message>
@@ -1400,13 +1473,13 @@ Errore durante il caricamento di %2</translation>
<translation>Nessun aggiornamento disponibile.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Disponibile solo gestione pacchetto locale.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Esci</translation>
</message>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1450,10 +1523,6 @@ Errore durante il caricamento di %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Impossibile scrivere il file di licenza &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Nessun file di licenza da eliminare trovato.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1477,10 +1546,6 @@ Errore durante il caricamento di %2</translation>
<translation>Motore core di gestione pacchetti mancante.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Preparazione del download delle informazioni sui metadati...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Decompressione repository compressi. Potrebbe volerci qualche momento...</translation>
</message>
@@ -1513,29 +1578,56 @@ Errore durante il caricamento di %2</translation>
<translation>Rilevata mancata corrispondenza checksum per &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Recupero delle informazioni sui metadati dal repository remoto in corso... %1/%2 </translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Errore durante l&apos;estrazione dell&apos;archivio &quot;%1&quot;: %2</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Recupero delle informazioni sui metadati dal repository remoto in corso... </translation>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Impossibile aprire il file &quot;%1&quot; per la lettura: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Errore durante l&apos;estrazione dell&apos;archivio &quot;%1&quot;: %2</translation>
+ <source>Metadata download canceled.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Rilevata eccezione sconosciuta durante l&apos;estrazione dell&apos;archivio &quot;%1&quot;.</translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Impossibile aprire il file &quot;%1&quot; per la lettura: %2</translation>
+ <source>Fetching latest update information...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
<message>
- <source>Metadata download canceled.</source>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Impossibile aprire il file &quot;%1&quot; per la scrittura: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Recupero di informazioni da repository remoti in corso...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Recupero delle informazioni sui metadati dal repository remoto in corso...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1544,10 +1636,8 @@ Errore durante il caricamento di %2</translation>
<translation>Errore durante la scrittura dello strumento di manutenzione</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Download pacchetti in corso...</translation>
+ <source>Downloading packages...</source>
+ <translation>Download pacchetti in corso...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1652,31 +1742,19 @@ Continuare?</translation>
<translation>Impossibile risolvere tutte le dipendenze.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Componenti che si sta per rimuovere.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Component %1 already installed
-</source>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
+ <source>Component %1 already installed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
+ <source>Cannot install %1. Component is virtual.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Running processes found.</source>
+ <source>Cannot install %1. Component not found.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1708,10 +1786,6 @@ Continuare?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation type="unfinished"></translation>
</message>
@@ -1720,13 +1794,11 @@ Continuare?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1738,11 +1810,35 @@ Continuare?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
+ <source>Invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Invalid</source>
+ <source>Components about to be removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1861,16 +1957,12 @@ Continuare?</translation>
<translation>Creazione strumento di manutenzione</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Installazione completata.</translation>
+ <source>Installation finished!</source>
+ <translation>Installazione completata.</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Installazione annullata.</translation>
+ <source>Installation aborted!</source>
+ <translation>Installazione annullata.</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1881,16 +1973,12 @@ Installazione annullata.</translation>
<translation>Rimozione dei componenti deselezionati in corso...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Aggiornamento completato.</translation>
+ <source>Update finished!</source>
+ <translation>Aggiornamento completato.</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Aggiornamento annullato.</translation>
+ <source>Update aborted!</source>
+ <translation>Aggiornamento annullato.</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
@@ -1925,10 +2013,8 @@ Aggiornamento annullato.</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Installazione componente %1</translation>
+ <source>Installing component %1</source>
+ <translation>Installazione componente %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1961,10 +2047,6 @@ Installazione componente %1</translation>
<translation>Impossibile recuperare le meta informazioni: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Impossibile aggiungere informazioni sull&apos;origine di aggiornamento temporanea.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Impossibile trovare informazioni sull&apos;origine di aggiornamento.</translation>
</message>
@@ -1993,6 +2075,50 @@ Installazione componente %1</translation>
%1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2025,7 +2151,7 @@ Installazione componente %1</translation>
<translation>%1 Domanda</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Impostazioni</translation>
</message>
<message>
@@ -2096,6 +2222,18 @@ Copiare il programma di installazione in un&apos;unità locale</translation>
<source>Uninstalling</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2139,7 +2277,7 @@ Copiare il programma di installazione in un&apos;unità locale</translation>
<translation>Pronto alla disinstallazione</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Si è ora pronti per iniziare la rimozione di %1 dal computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;La directory del programma %2 verrà eliminata completamente&lt;/font&gt;, incluso tutto il contenuto di tale directory!</translation>
</message>
<message>
@@ -2151,7 +2289,7 @@ Copiare il programma di installazione in un&apos;unità locale</translation>
<translation>Pronto all&apos;aggiornamento dei pacchetti</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>Si è ora pronti per iniziare l&apos;installazione.</translation>
</message>
<message>
@@ -2163,13 +2301,25 @@ Copiare il programma di installazione in un&apos;unità locale</translation>
<translation>Pronto all&apos;installazione</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Si è ora pronti per iniziare l&apos;installazione di %1 nel computer.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2226,7 +2376,7 @@ Copiare il programma di installazione in un&apos;unità locale</translation>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Completamento dell&apos;installazione guidata di %1</translation>
</message>
</context>
@@ -2449,6 +2599,14 @@ Copiare il programma di installazione in un&apos;unità locale</translation>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2492,7 +2650,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>Impossibile aprire il file di impostazioni %1 per la lettura: %2</translation>
</message>
<message>
- <source>Select Categories</source>
+ <source>Categories</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2620,16 +2778,40 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished">Seleziona tutto</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation type="unfinished">Deseleziona tutto</translation>
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2691,7 +2873,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>Errore</translation>
</message>
<message>
- <source>Component Information</source>
+ <source>Information</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2701,6 +2883,22 @@ or accept the elevation of access rights if being asked.</source>
<source>Extracting &quot;%1&quot;</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished">Impossibile aprire l’archivio &quot;%1&quot; per la lettura: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2709,4 +2907,189 @@ or accept the elevation of access rights if being asked.</source>
<translation type="unfinished"></translation>
</message>
</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation::Worker</name>
+ <message>
+ <source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Impossibile aprire l’archivio &quot;%1&quot; per la lettura: %2</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Errore durante l&apos;estrazione dell&apos;archivio &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Impossibile aprire il file &quot;%1&quot; per la scrittura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Impossibile aprire il file &quot;%1&quot; per la lettura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
</TS>
diff --git a/src/sdk/translations/ifw_ja.ts b/src/sdk/translations/ifw_ja.ts
index 565704866..5152944d3 100644
--- a/src/sdk/translations/ifw_ja.ts
+++ b/src/sdk/translations/ifw_ja.ts
@@ -16,11 +16,11 @@
<name>BinaryContent</name>
<message>
<source>Cannot seek to %1 to read the operation data.</source>
- <translation>操作データを読み取るための %1 のシークができません。</translation>
+ <translation>操作データを読み取るための %1 とうファイルポジションに移動できません。</translation>
</message>
<message>
<source>Cannot seek to %1 to read the resource collection block.</source>
- <translation>リソース コレクション ブロックを読み取るための %1 のシークができません。</translation>
+ <translation>リソース コレクション ブロックを読み取るため%1 とうファイルポジションに移動できません。</translation>
</message>
<message>
<source>Cannot open meta resource %1.</source>
@@ -31,11 +31,11 @@
<name>BinaryLayout</name>
<message>
<source>Cannot seek to %1 to read the embedded meta data count.</source>
- <translation>埋め込みメタ データ数を読み取るための %1 のシークができません。</translation>
+ <translation>埋め込みメタ データ数を読み取るため%1 とうファイルポジションに移動できません。</translation>
</message>
<message>
<source>Cannot seek to %1 to read the resource collection segment.</source>
- <translation>リソース コレクション セグメントを読み取るための %1 のシークができません。</translation>
+ <translation>リソース コレクション セグメントを読み取るため %1 とうファイルポジションに移動できません。</translation>
</message>
<message>
<source>Unexpected mismatch of meta resources. Read %1, expected: %2.</source>
@@ -136,12 +136,24 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>&quot;%2&quot; の欠落した依存関係 &quot;%1&quot; が見つかりません。</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>不可能な依存関係が検出されました。強制にインストールされる&quot;%1&quot;コンポーネントは、&quot;%1&quot;に依存する &quot;%2&quot;がアンインストールの対象ですので、アンインストールされます。&quot;%2&quot;のアンインストレーション理由は: &quot;%3&quot;。</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>エイリアス &quot;%1&quot; によって選択されたコンポーネント:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>再帰が検出されました。コンポーネント エイリアス &quot;%1&quot; がすでに追加されています。</translation>
+ </message>
</context>
<context>
<name>Job</name>
<message>
<source>Canceled</source>
- <translation>キャンセル</translation>
+ <translation>キャンセルされました</translation>
</message>
</context>
<context>
@@ -209,7 +221,7 @@
<name>KDUpdater::FileDownloader</name>
<message>
<source>Download finished.</source>
- <translation>ダウンロードが終了しました。</translation>
+ <translation>ダウンロードが完了しました。</translation>
</message>
<message>
<source>Cryptographic hashes do not match.</source>
@@ -284,7 +296,7 @@
</message>
<message>
<source>Secure Connection Failed</source>
- <translation>セキュリティで保護された接続に失敗しました</translation>
+ <translation>セキュアな接続が失敗しました</translation>
</message>
<message>
<source>There was an error during connection to: %1.</source>
@@ -292,7 +304,7 @@
</message>
<message>
<source>This could be a problem with the server&apos;s configuration, or it could be someone trying to impersonate the server.</source>
- <translation>サーバーの構成に問題があるか、誰かがサーバーを偽装しようとした可能性があります。</translation>
+ <translation>サーバーの構成に問題があるか、誰かがサーバーを偽装しようとしている可能性があります。</translation>
</message>
<message>
<source>If you have connected to this server successfully in the past or trust this server, the error may be temporary and you can try again.</source>
@@ -302,6 +314,10 @@
<source>Try again</source>
<translation>再試行</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>%1をダウンロードできません。&quot;%2&quot;のためディレクトリを作成することができません。</translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -421,11 +437,11 @@
</message>
<message>
<source>%1 cannot be paused</source>
- <translation>%1 を解析できません</translation>
+ <translation>%1 を一時停止できません</translation>
</message>
<message>
<source>Cannot pause task %1</source>
- <translation>タスク %1 を解析できません</translation>
+ <translation>タスク&#x3000;%1 を一時停止できません</translation>
</message>
<message>
<source>Cannot resume task %1</source>
@@ -484,10 +500,6 @@
<translation>&quot;%1&quot; を読み取れません</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>%2、%3 で %1 のエラーを解析します: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>ルート エレメント %1 は予期しないものです。&quot;Updates&quot; でなければなりません。</translation>
</message>
@@ -739,6 +751,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>&quot;%1&quot; に無効なコンテンツがあります。</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>以下のキャッシュを削除した上でアプリケーションを再起動することで問題が解決することもあります。</translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -747,18 +763,6 @@
<translation>コンポーネントは、アップデーター モードで子を持つことができません。</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>要求された UI ファイル &quot;%1&quot; を開けません: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>要求された UI ファイル &quot;%1&quot; を読み込めません: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>要求されたライセンス ファイル &quot;%1&quot; を開けません: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>エラー</translation>
</message>
@@ -778,6 +782,30 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>選択したコンポーネントの読み込み中にエラーが発生しました。このコンポーネントをインストールできません。</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>要求された UI ファイル &quot;%1&quot; を開けません: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>要求された UI ファイル &quot;%1&quot; を読み込めません: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>要求されたライセンス ファイル &quot;%1&quot; を開けません: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -825,62 +853,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt + A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>デフォルト (&amp;A)</translation>
+ <source>Default</source>
+ <translation>デフォルト</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>ツリー表示でデフォルトのコンポーネントを選択します。</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt + R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>リセット(&amp;R)</translation>
+ <source>Reset</source>
+ <translation>リセット</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>ツリー表示ですべてのコンポーネントを元の選択状態にリセットします。</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt + S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>すべて選択(&amp;S)</translation>
+ <source>Select All</source>
+ <translation>すべて選択</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>ツリー表示ですべてのコンポーネントを選択します。</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt + D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>すべて選択解除 (&amp;D)</translation>
+ <source>Deselect All</source>
+ <translation>すべて選択解除</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>ツリー表示ですべてのコンポーネントの選択を解除します。</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>QBSP ファイルの参照 (&amp;B)</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>Qt Board Support Packageファイルを選択し、オンラインリポジトリから直接取得できない追加のコンテンツをインストールします。</translation>
</message>
@@ -913,13 +917,37 @@
<translation>アンインストールするコンポーネントを選択してください。</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
<translation>インストールするコンポーネントを選択します。 コンポーネントをアンインストールするには、インストール済みのコンポーネントを選択解除します。 すでにインストールされているコンポーネントは更新されません。</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>更新したい他のコンポーネントを選択する前に必須コンポーネントを更新する必要があります。</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>検索</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>QBSPファイルを検索</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>選択</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>オフラインインストーラーの作成</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>今すぐインストールするのではなく、選択したコンポーネントでオフライン インストーラーを作成します。</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -936,12 +964,8 @@
<translation>&quot;%1&quot; の出力を空のインストーラー キー値に保存できません。</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>ファイル &quot;%1&quot; は存在しないか、実行可能なバイナリ ファイルではありません。</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>&quot;%1&quot; を実行した結果、クラッシュが発生しました。</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>コマンド&quot;%1&quot;の実行に失敗しました。: %2</translation>
</message>
</context>
<context>
@@ -1082,6 +1106,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>アーカイブ &quot;%1&quot; を作成できません: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot; は非サポートのアーカイブです。拡張子 &quot;%2&quot; ファイルのハンドラが登録されていません</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1188,11 +1216,15 @@ Error while loading %2</source>
</message>
<message>
<source>Archive: </source>
- <translation type="unfinished"></translation>
+ <translation>アーカイブ</translation>
</message>
<message>
<source>Total: </source>
- <translation type="unfinished"></translation>
+ <translation>合計</translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>再試行回数 (%1) を超えました</translation>
</message>
</context>
<context>
@@ -1327,7 +1359,7 @@ Error while loading %2</source>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>%1 ウィザードを完了しています</translation>
</message>
<message>
@@ -1335,7 +1367,7 @@ Error while loading %2</source>
<translation>終了</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>%2 ウィザードを終了するには、%1 をクリックします。</translation>
</message>
<message>
@@ -1347,7 +1379,7 @@ Error while loading %2</source>
<translation>今すぐ %1 を実行します。</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>%1 ウィザードが正常に実行されませんでした。</translation>
</message>
</context>
@@ -1388,15 +1420,19 @@ Error while loading %2</source>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>ディレクトリ &quot;%1&quot; を作成できません: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>バックアップのファイル &quot;%1&quot; を準備できません: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>設定 - %1</translation>
+ <source>Welcome</source>
+ <translation>ようこそ</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>%1 設定ウィザードへようこそ。</translation>
</message>
<message>
@@ -1424,16 +1460,12 @@ Error while loading %2</source>
<translation>利用できる更新はありません。</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation>ローカル パッケージ管理のみ利用可能です。</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>中止</translation>
</message>
<message>
<source>There is an important update available. Please select &apos;%1&apos; first</source>
- <translation type="unfinished"></translation>
+ <translation>重要な更新が見つかりました。まず&apos;%1&apos; を選択してください</translation>
</message>
</context>
<context>
@@ -1478,10 +1510,6 @@ Error while loading %2</source>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>ライセンス ファイル &quot;%1&quot; に書き込めません</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>削除対象のライセンス ファイルが見つかりません。</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1505,10 +1533,6 @@ Error while loading %2</source>
<translation>パッケージ マネージャー コア エンジンが見つかりません。</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>メタ情報のダウンロードを準備しています...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>圧縮されたリポジトリを解凍しています。 しばらくお待ちください...</translation>
</message>
@@ -1545,14 +1569,6 @@ Error while loading %2</source>
<translation>&quot;%1&quot; でチェックサムの不一致が検出されました。</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>リモート リポジトリからメタ情報を取得しています... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>リモート リポジトリからメタ情報を取得しています... </translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>アーカイブ &quot;%1&quot; の抽出中にエラーが発生しました: %2</translation>
</message>
@@ -1560,6 +1576,44 @@ Error while loading %2</source>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>読み取り用のファイル &quot;%1&quot; を開けません: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot; は非サポートのアーカイブです。拡張子 &quot;%2&quot; ファイルのハンドラが登録されていません</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>最新の更新情報を取得しています...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>%n 個の新しいアイテムでローカル キャッシュを更新しています...</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>キャッシュディレクトリを空にしてアプリケーションを再起動すると、この問題が解決する場合があります。</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>キャッシュの更新中に不明な例外が発生しました。</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>読み取り用の、解凍されたファイル &quot;%1&quot; を開けません:%2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>書き込み用の、ファイル &quot;%1&quot; を開けません:%2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>リモート リポジトリから情報を取得しています...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>リモート リポジトリからメタ情報を取得しています... </translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1568,10 +1622,8 @@ Error while loading %2</source>
<translation>保守ツールへの書き込み中にエラーが発生しました</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-パッケージをダウンロードしています...</translation>
+ <source>Downloading packages...</source>
+ <translation>パッケージをダウンロードしています...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1680,42 +1732,24 @@ Do you want to continue?</source>
<translation>一部の依存関係を解決できません。</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>コンポーネントを削除しようとしています。</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>コンポーネント %1 をインストールできません。コンポーネントは %2 への自動依存性としてのみインストールされます。</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>コンポーネント %1 をインストールできません。コンポーネントは %2 への自動依存性としてのみインストールされます。
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>コンポーネント %1 をインストールできません。コンポーネントはチェックできないため、サブコンポーネントの一つを選択する必要があります。</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>コンポーネント %1 をインストールできません。コンポーネントはチェックできないため、サブコンポーネントの一つを選択する必要があります。
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>コンポーネント %1 はすでにインストールされています</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>コンポーネント %1 はすでにインストールされています
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>%1 をインストールできません。コンポーネントは仮想です。</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>%1 をインストールできません。コンポーネントは仮想です。
-</translation>
- </message>
- <message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>%1 をインストールできません。コンポーネントが見つかりません。
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>実行中のプロセスが見つかりました。</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>%1 をインストールできません。コンポーネントが見つかりません。</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1738,10 +1772,6 @@ Do you want to continue?</source>
<translation>十分なディスク空き容量がないため、選択された一部のコンポーネントを格納できません。 %2 が最低限必要な場合は、%1 を利用できます。</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>十分なディスク空き容量がないため、一時ファイルを格納できません。 %2 が最低限必要な場合は、%1 を利用できます。</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>インストール用に選択されたボリュームにはインストールに十分な空き容量があるようですが、後から使用可能な空き容量はボリュームの 1% 未満です。</translation>
</message>
@@ -1762,18 +1792,40 @@ Do you want to continue?</source>
<translation>ユーザー入力が必要ですが、出力デバイスが端末に関連づけられていません。</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>コンポーネントを登録できません!識別子 %1 のコンポーネントはすでに存在します。</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>%1 をインストールできません。コンポーネントは仮想コンポーネント %2 を継承しています。</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>%1 をインストールできません。コンポーネントは仮想コンポーネント %2 を継承しています。
-</translation>
+ <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
+ <translation>インストーラの推定サイズ %1 は、実行可能ファイルのサイズ制限 %2 を超えています。アプリケーションが実行できない場合があります。</translation>
</message>
<message>
- <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>削除されるコンポーネント: </translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>コンポーネント %1をインストールできません。このコンポーネントのロードに問題があったため、不安定と記され、選択できません。</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>時ファイルを保存するのに十分なディスク容量がありません!&#x3000;%1 が利用可能ですが、必要な最小値は %2 です。 インストーラー設定からローカル キャッシュ パスを変更することにより、一時ファイルの別の場所を選択できます。</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>アンインストール対象のコンポーネントを解決できません。</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>エイリアス %1 を選択できません。エイリアスのロード中に問題が発生したため、不安定と記され、選択できません。</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>%1を選択できません。エイリアスは仮想として記され、手動で選択できません。</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>作成されるインストーラーはディスク容量の %1 を使用します。</translation>
</message>
</context>
<context>
@@ -1891,16 +1943,12 @@ Do you want to continue?</source>
<translation>保守ツールを作成しています</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-インストールが終了しました。</translation>
+ <source>Installation finished!</source>
+ <translation>インストールが終了しました。</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-インストールが中止されました。</translation>
+ <source>Installation aborted!</source>
+ <translation>インストールが中止されました。</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1911,16 +1959,12 @@ Installation aborted!</source>
<translation>選択解除したコンポーネントを削除しています...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-更新が終了しました。</translation>
+ <source>Update finished!</source>
+ <translation>更新が終了しました。</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-更新が中止されました。</translation>
+ <source>Update aborted!</source>
+ <translation>更新が中止されました。</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1963,10 +2007,8 @@ Update aborted!</source>
<translation>オフライン生成が中止されました!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-コンポーネント %1 をインストールしています</translation>
+ <source>Installing component %1</source>
+ <translation>コンポーネント %1 をインストールしています</translation>
</message>
<message>
<source>Installer Error</source>
@@ -2013,10 +2055,6 @@ Installing component %1</source>
<translation>メタ情報を取得できません: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>一時的な更新ソース情報を追加できません。</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>更新ソース情報が見つかりません。</translation>
</message>
@@ -2024,6 +2062,50 @@ Installing component %1</source>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>コンポーネント &quot;%1&quot; と &quot;%2&quot; との依存サイクルが検出されました。</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>コンポーネントを開梱する準備をしています。</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%2 中 %1 の操作が完了しました。</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>コンポーネントを開梱しています。</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%2 中 %1 の操作がロールバックされました。</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>ロールバックが完了しました。</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%2 中 %1のコンポーネントがインストールされました。</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>すべてのコンポーネントがインストールされました。</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>コンポーネント スクリプトを読み込んでいます...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>エイリアスの名前が既存のコンポーネント &quot;%1&quot;&#x3000;の名前と対立しまていす。</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>コンポーネントエイリアスが未解決です</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>エイリアス &quot;%1&quot; と &quot;%2&quot;&#x3000;の間の循環依存関係が検出されました。</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2060,7 +2142,7 @@ Installing component %1</source>
<translation>%1 質問</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>設定</translation>
</message>
<message>
@@ -2127,6 +2209,18 @@ Please copy the installer to a local drive</source>
<source>Uninstalling</source>
<translation>アンインストールしています</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>&amp;オフラインインストーラーを作成</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>%1 のオフラインインストーラーを作成しています</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>オフラインインストーラーを作成しています</translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2170,7 +2264,7 @@ Please copy the installer to a local drive</source>
<translation>アンインストールの準備ができました</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>コンピューターから %1 を削除する準備が整っています。&lt;br&gt;&lt;font color=&quot;red&quot;&gt;プログラム ディレクトリ %2 が完全に削除されます&lt;/font&gt;。このディレクトリ内のコンテンツもすべて削除されます。</translation>
</message>
<message>
@@ -2182,7 +2276,7 @@ Please copy the installer to a local drive</source>
<translation>パッケージを更新する準備ができました</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>インストールを更新する準備が整っています。</translation>
</message>
<message>
@@ -2194,13 +2288,25 @@ Please copy the installer to a local drive</source>
<translation>インストールの準備ができました</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>コンピューターに %1 をインストールする準備が整っています。</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>更新の準備ができました</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>オフラインインストーラーを作成</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>オフラインインストーラーの準備ができました</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>選択したコンポーネントのオフラインインストーラーを作成するために準備が整っています</translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2257,7 +2363,7 @@ Please copy the installer to a local drive</source>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>%1 設定ウィザードを完了しています</translation>
</message>
</context>
@@ -2480,6 +2586,14 @@ Please copy the installer to a local drive</source>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>現在のユーザーがファイル &amp;quot;%1&amp;quot; への読み取りアクセス権限を持っていることを確認するか、管理者として %2 を実行してください。</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>&apos;max-concurrent-operations&apos;の値が無効です。</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>オプション &apos;cache-path&apos; の値が空です。</translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2526,7 +2640,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>読み取り用の設定ファイル %1 を開けません: %2</translation>
</message>
<message>
- <source>Select Categories</source>
+ <source>Categories</source>
<translation>カテゴリを選択</translation>
</message>
</context>
@@ -2664,6 +2778,30 @@ or accept the elevation of access rights if being asked.</source>
<source>Deselect All</source>
<translation>すべての選択を解除</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>ローカル キャッシュ</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>読み込み時間を改善するために、リモートリポジトリからのメタ情報がディスクにキャッシュされます。別のディレクトリを選択してキャッシュを保存する、または現在のキャッシュの内容を消去することができます。</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>キャッシュのパス:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>キャッシュ ディレクトリの内容を削除します</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>キャッシュの消去</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>キャッシュを消去しています…</translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2723,7 +2861,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>エラー</translation>
</message>
<message>
- <source>Component Information</source>
+ <source>Information</source>
<translation>コンポーネント情報</translation>
</message>
</context>
@@ -2733,6 +2871,22 @@ or accept the elevation of access rights if being asked.</source>
<source>Extracting &quot;%1&quot;</source>
<translation>&quot;%1&quot; を抽出しています</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot; は非サポートのアーカイブです。拡張子 &quot;%2&quot; ファイルのハンドラが登録されていません。</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>読み取り用のアーカイブ &quot;%1&quot; を開けません。: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>アーカイブ&quot;%1&quot;のコンテンツを読みこんでいる際にエラーが発生しました。:&#x3000;%2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>&quot;%1&quot;から解凍されたファイルを削除します。</translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2745,27 +2899,185 @@ or accept the elevation of access rights if being asked.</source>
<name>QInstaller::ExtractArchiveOperation::Worker</name>
<message>
<source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>アーカイブ &quot;%1&quot; のハンドラ オブジェクトを作成できませんでした: &quot;%2&quot;。</translation>
</message>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
<translation>読み取り用のアーカイブ &quot;%1&quot; を開けません: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>アーカイブ &quot;%1&quot; の抽出中にエラーが発生しました: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>読み取り用のアーカイブを開くことができません。: %1</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>エントリヘッダーを読み取れません。: %1</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>アーカイブ &quot;%1&quot; の抽出中にエラーが発生しました: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>エントリ&quot;%1&quot;をディスクに書き込めません。: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>読み取り用にアーカイブを開くことができません。: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>エントリヘッダーを読み取れません。: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>エントリ&quot;%1&quot;をディスクへ書き込めません。: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>書き込み用のファイル &quot;%1&quot; を開けません。: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>読み取り用のファイル &quot;%1&quot; を開けません。: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;のエントリーヘッダーを書き込めません。: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>選択解除されたコンポーネント:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>コンポーネントが&quot;%1&quot;に置き換えられました。:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>既存の依存関係のない仮想コンポーネントの削除:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>コンポーネントの依存関係&quot;%1&quot;削除:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>コンポーネントの自動依存性&quot;%1&quot;削除:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>%1 インストーラについて</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>%1メンテナンスツールについて</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>空のパスでキャッシュを初期化できません。</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>キャッシュ用のディレクトリ &quot;%1&quot; を作成できません。</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>キャッシュを初期化できません: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>無効化されたキャッシュを消去できません。</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>マニフェストファイルを削除できません: %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>キャッシュを空にしている際にエラーが発生しました: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>無効化されたキャッシュからアイテムを取得できません。</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>無効化されたキャッシュからアイテムを取得できません。</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>無効化されたキャッシュにアイテムを登録できません。</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>空のアイテムは登録できません。</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>チェックサム %1 で無効なアイテムを登録できません</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>チェックサム %1 でアイテムを登録できません。同じチェックサムを持つアイテムが既にキャッシュに存在します。</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>アイテムをパス &quot;%1&quot; にコピー中にエラーが発生しました: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>無効化されたキャッシュからアイテムを削除できません。</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>チェックサム %1 で指定されたアイテムを削除できません: そのようなアイテムは存在しません。</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>ディレクトリ &quot;%1&quot; の削除中にエラーが発生しました: %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>キャッシュの無効化中にエラーが発生しました: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>マニフェストファイルを開けません: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>マニフェストファイルの内容を書き込めません: %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>無効化されたキャッシュを同期できません。</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>不明な登録モードが選択されました!</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>キャッシュが正常に消去されました!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_ko.ts b/src/sdk/translations/ifw_ko.ts
index a2db492de..2fc5cce29 100644
--- a/src/sdk/translations/ifw_ko.ts
+++ b/src/sdk/translations/ifw_ko.ts
@@ -5,7 +5,7 @@
<name>QInstaller::ProxyCredentialsDialog</name>
<message>
<source>Dialog</source>
- <translation>다이얼로그</translation>
+ <translation>대화창</translation>
</message>
<message>
<source>The proxy %1 requires a username and password.</source>
@@ -114,7 +114,7 @@
</message>
<message>
<source>Repositories</source>
- <translation>리포지토리</translation>
+ <translation>저장소</translation>
</message>
<message>
<source>Add Username and Password for authentication if needed.</source>
@@ -122,7 +122,7 @@
</message>
<message>
<source>Use temporary repositories only</source>
- <translation>임시 리포지토리만 사용</translation>
+ <translation>임시 저장소만 사용</translation>
</message>
<message>
<source>Add</source>
@@ -150,7 +150,7 @@
</message>
<message>
<source>Check this to use repository during fetch.</source>
- <translation>가져오는 중에 리포지토리를 사용하려면 확인하십시오.</translation>
+ <translation>가져오는 중에 저장소를 사용하려면 확인하십시오.</translation>
</message>
<message>
<source>Add the username to authenticate on the server.</source>
@@ -162,23 +162,23 @@
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
- <translation>유효한 리포지토리가 포함되어 있는 서버 URL입니다.</translation>
+ <translation>유효한 저장소가 포함되어 있는 서버 URL입니다.</translation>
</message>
<message>
<source>An error occurred while testing this repository.</source>
- <translation>이 리포지토리를 테스트하는 중에 오류가 발생했습니다.</translation>
+ <translation>이 저장소를 테스트하는 중에 오류가 발생했습니다.</translation>
</message>
<message>
<source>The repository was tested successfully.</source>
- <translation>리포지토리를 성공적으로 테스트했습니다.</translation>
+ <translation>저장소를 성공적으로 테스트했습니다.</translation>
</message>
<message>
<source>Do you want to disable the repository?</source>
- <translation>이 리포지토리를 비활성화하시겠습니까?</translation>
+ <translation>이 저장소를 비활성화하시겠습니까?</translation>
</message>
<message>
<source>Do you want to enable the repository?</source>
- <translation>이 리포지토리를 활성화하시겠습니까?</translation>
+ <translation>이 저장소를 활성화하시겠습니까?</translation>
</message>
<message>
<source>Hide Passwords</source>
@@ -198,19 +198,43 @@
</message>
<message>
<source>Repository</source>
- <translation>리포지토리</translation>
+ <translation>저장소</translation>
</message>
<message>
<source>Default repositories</source>
- <translation>기본 리포지토리</translation>
+ <translation>기본 저장소</translation>
</message>
<message>
<source>Temporary repositories</source>
- <translation>임시 리포지토리</translation>
+ <translation>임시 저장소</translation>
</message>
<message>
<source>User defined repositories</source>
- <translation>사용자 정의 리포지토리</translation>
+ <translation>사용자 정의 저장소</translation>
+ </message>
+ <message>
+ <source>Local cache</source>
+ <translation>로컬 캐시</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>로딩 시간을 줄이기 위해 원격 저장소 메타 정보가 디스크에 캐시(임시 저장)됩니다. 캐시를 저장하기 위해 다른 디렉터리를 선택하거나 현재 캐시를 지울 수 있습니다.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>캐시를 위한 경로</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>캐시 디렉터리 내용 삭제</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>캐시 모두 삭제</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>캐시 삭제 중...</translation>
</message>
</context>
<context>
@@ -285,11 +309,11 @@
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;: %2</source>
- <translation>&quot;1%&quot; 디렉토리를 제거할 수 없음: %2</translation>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없음: %2</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation>&quot;1%&quot; 디렉토리를 생성할 수 없습니다.</translation>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
</message>
<message>
<source>Cannot copy file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
@@ -301,7 +325,7 @@
</message>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
- <translation>&quot;%1&quot; 디렉토리를 생성할 수 없음: %2</translation>
+ <translation>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
</message>
<message>
<source>Cannot open temporary file: %1</source>
@@ -323,6 +347,10 @@
<source>The specified module could not be found.</source>
<translation>지정된 모듈을 찾을 수 없습니다.</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>캐시를 삭제한 후에 애플리케이션을 재시작하면 해결될 수 있습니다.</translation>
+ </message>
</context>
<context>
<name>QObject</name>
@@ -348,19 +376,19 @@
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation>옵션 &apos;addRepository&apos;에 대한 리포지토리 목록이 비어있습니다.</translation>
+ <translation>옵션 &apos;addRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation>옵션 &apos;addTempRepository&apos;에 대한 리포지토리 목록이 비어있습니다.</translation>
+ <translation>옵션 &apos;addTempRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation>옵션 &apos;setTempRepository&apos;에 대한 리포지토리 목록이 비어있습니다.</translation>
+ <translation>옵션 &apos;setTempRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation>옵션 &apos;installCompressedRepository&apos;에 대한 리포지토리 목록이 비어있습니다.</translation>
+ <translation>옵션 &apos;installCompressedRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -382,6 +410,14 @@
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>현재 사용자가 &amp;quot;%1&amp;quot; 파일에 대한 접근 권한이 있는지 확인하거나 관리자 권한으로 %2 파일을 실행해 보십시오.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>&apos;최대 동시 작업&apos;값이 올바르지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>&apos;cache-path&apos; 옵션의 값이 비어 있습니다.</translation>
+ </message>
</context>
<context>
<name>BinaryLayout</name>
@@ -442,18 +478,6 @@
<translation>업데이터 모드에서는 구성요소에 하위 요소가 있으면 안 됩니다.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>요청된 UI 파일(&quot;%1&quot;)을 열 수 없음: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>요청된 UI 파일(&quot;%1&quot;)을 로드할 수 없음: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>요청된 라이선스 파일(&quot;%1&quot;)을 열 수 없음: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>오류</translation>
</message>
@@ -473,6 +497,30 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>선택한 구성요소를 로드하는 중에 오류가 발생했습니다. 이 구성요소를 설치할 수 없습니다.</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>요청된 UI 파일(&quot;%1&quot;)을 열 수 없음: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>요청된 UI 파일(&quot;%1&quot;)을 로드할 수 없음: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>요청된 라이선스 파일(&quot;%1&quot;)을 열 수 없음: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -520,68 +568,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>기본(&amp;A):</translation>
+ <source>Default</source>
+ <translation>기본:</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>트리 보기에서 기본 구성요소를 선택합니다.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>재설정(&amp;R)</translation>
+ <source>Reset</source>
+ <translation>재설정</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>트리 보기에서 모든 구성요소를 원래 선택된 상태로 재설정합니다.</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>모두 선택(&amp;S)</translation>
+ <source>Select All</source>
+ <translation>모두 선택</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>트리 보기에서 모든 구성요소를 선택합니다.</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>모두 선택 해제(&amp;D)</translation>
+ <source>Deselect All</source>
+ <translation>모두 선택 해제</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>트리 보기에서 모든 구성요소를 선택 해제합니다.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>QBSP 파일 탐색(&amp;B)</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
- <translation>QBSP(Qt Board Support Package) 파일을 선택하여 온라인 리포지토리에서 직접 사용할 수 없는 추가 콘텐츠를 설치합니다.</translation>
+ <translation>QBSP(Qt Board Support Package) 파일을 선택하여 온라인 저장소에서 직접 사용할 수 없는 추가 콘텐츠를 설치합니다.</translation>
</message>
<message>
<source>Filter the enabled repository categories</source>
- <translation>활성화된 리포지토리 범주를 필터링합니다.</translation>
+ <translation>활성화된 저장소 범주를 필터링합니다.</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -608,13 +632,37 @@
<translation>설치 제거하려는 구성요소를 선택하십시오.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
<translation>설치할 구성요소를 선택하십시오. 설치 제거할 설치된 구성요소를 선택 해제하십시오. 이미 설치된 모든 구성요소는 업데이트되지 않습니다.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>필수 구성요소를 먼저 업데이트해야 다른 구성요소를 업데이트하기 위해 선택할 수 있습니다.</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>검색</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>QBSP 파일 탐색(&amp;Q)</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>선택</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>오류</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>오프라인 설치 프로그램 생성합니다.</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>지금 설치하지 않고 선택된 구성요소들로 부터 오프라인 설치 프로그램을 생성합니다.</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentSelectionPagePrivate</name>
@@ -623,8 +671,8 @@
<translation>필터</translation>
</message>
<message>
- <source>Component Information</source>
- <translation>구성요소 정보</translation>
+ <source>Information</source>
+ <translation type="unfinished">구성요소 정보</translation>
</message>
<message>
<source>Error</source>
@@ -646,12 +694,8 @@
<translation>빈 설치 관리자 키 값에 &quot;%1&quot;의 출력을 저장할 수 없습니다.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>&quot;%1&quot; 파일이 없거나 실행 가능한 바이너리가 아닙니다.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>&quot;%1&quot; 실행 중에 충돌이 발생했습니다.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>명령을 수행할 수 없습니다.: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -666,11 +710,11 @@
</message>
<message>
<source>Invalid argument in %1: Directory &quot;%2&quot; is invalid.</source>
- <translation>%1에 유효하지 않은 인수: &quot;%2&quot; 디렉토리가 유효하지 않습니다.</translation>
+ <translation>%1에 유효하지 않은 인수: &quot;%2&quot; 디렉터리가 유효하지 않습니다.</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation>&quot;1%&quot; 디렉토리를 생성할 수 없습니다.</translation>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
</message>
<message>
<source>Failed to overwrite &quot;%1&quot;.</source>
@@ -754,7 +798,7 @@
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation>&quot;1%&quot; 디렉토리를 제거할 수 없습니다.</translation>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없습니다.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -770,7 +814,7 @@
</message>
<message>
<source>Cannot create target directory: &quot;%1&quot;.</source>
- <translation>대상 디렉토리를 생성할 수 없음: &quot;%1&quot;.</translation>
+ <translation>대상 디렉터리를 생성할 수 없음: &quot;%1&quot;.</translation>
</message>
<message>
<source>Unknown exception caught: %1.</source>
@@ -786,12 +830,16 @@
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;: %2</source>
- <translation>&quot;1%&quot; 디렉토리를 제거할 수 없음: %2</translation>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없음: %2</translation>
</message>
<message>
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>&quot;%1&quot; 아카이브를 생성할 수 없음: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>지원되지 않는 &quot;%1&quot; 아카이브: &quot;%2&quot; 파일 접미사를 위해 등록된 핸들러가 없습니다.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -801,7 +849,7 @@
</message>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
- <translation>&quot;%1&quot; 디렉토리를 생성할 수 없음: %2</translation>
+ <translation>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
</message>
<message>
<source>Failed to overwrite &quot;%1&quot;: %2</source>
@@ -898,11 +946,15 @@ Error while loading %2</source>
</message>
<message>
<source>Archive: </source>
- <translation type="unfinished"></translation>
+ <translation>아카이브:</translation>
</message>
<message>
<source>Total: </source>
- <translation type="unfinished"></translation>
+ <translation>총계:</translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>재시도 회수(%1) 초과</translation>
</message>
</context>
<context>
@@ -1036,6 +1088,22 @@ Error while loading %2</source>
<source>Extracting &quot;%1&quot;</source>
<translation>&quot;%1&quot; 추출 중</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>지원되지 않는 &quot;%1&quot; 아카이브: &quot;%2&quot; 파일을 위해 등록된 핸들러가 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>&quot;%1&quot; 아카이브를 읽기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 아카이브의 내용을 읽는 중 오류 발생: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; 로부터 추출된 파일들을 삭제 중입니다.</translation>
+ </message>
</context>
<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
@@ -1089,6 +1157,18 @@ Error while loading %2</source>
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>&quot;%2&quot;에 대한 누락된 종속성 &quot;%1&quot;을(를) 찾을 수 없습니다.</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>해결할 수 없는 종속성 문제가 발생. 설치된 구성 요소 &quot;%1&quot;이(가) 종속성 &quot;%2&quot;(으)로 설정되어 제거됩니다.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>별칭 &quot;%1&quot;으로 선택된 구성요소.</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>반복이 감지됨, 별칭 &quot;%1&quot;가 이미 추가됨.</translation>
+ </message>
</context>
<context>
<name>QInstaller::InstallIconsOperation</name>
@@ -1098,7 +1178,7 @@ Error while loading %2</source>
</message>
<message>
<source>Invalid Argument: source directory must not be empty.</source>
- <translation>유효하지 않은 인수: 소스 디렉토리를 입력해야 합니다.</translation>
+ <translation>유효하지 않은 인수: 소스 디렉터리를 입력해야 합니다.</translation>
</message>
<message>
<source>Cannot backup file &quot;%1&quot;: %2</source>
@@ -1114,7 +1194,11 @@ Error while loading %2</source>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
- <translation>&quot;%1&quot; 디렉토리를 생성할 수 없음: %2</translation>
+ <translation>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일 백업을 준비할 수 없음: %2</translation>
</message>
</context>
<context>
@@ -1196,11 +1280,11 @@ Error while loading %2</source>
<name>DirectoryGuard</name>
<message>
<source>Path &quot;%1&quot; exists but is not a directory.</source>
- <translation>&quot;%1&quot; 경로가 존재하지만 디렉토리가 아닙니다.</translation>
+ <translation>&quot;%1&quot; 경로가 존재하지만 디렉터리가 아닙니다.</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation>&quot;1%&quot; 디렉토리를 생성할 수 없습니다.</translation>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
</message>
</context>
<context>
@@ -1244,10 +1328,6 @@ Error while loading %2</source>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>&quot;%1&quot; 라이선스 파일을 쓸 수 없습니다.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>삭제할 라이선스 파일을 찾을 수 없습니다.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1271,12 +1351,8 @@ Error while loading %2</source>
<translation>패키지 관리자 코어 엔진이 누락되었습니다.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>메타 정보 다운로드 준비 중...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
- <translation>압축된 리포지토리의 압축을 해제합니다. 약간의 시간이 걸릴 수 있습니다...</translation>
+ <translation>압축된 저장소의 압축을 해제합니다. 약간의 시간이 걸릴 수 있습니다...</translation>
</message>
<message>
<source>Metadata download canceled.</source>
@@ -1300,7 +1376,7 @@ Error while loading %2</source>
</message>
<message>
<source>Failure to fetch repositories.</source>
- <translation>리포지토리를 가져올 수 없습니다.</translation>
+ <translation>저장소를 가져올 수 없습니다.</translation>
</message>
<message>
<source>Extracting meta information...</source>
@@ -1311,21 +1387,51 @@ Error while loading %2</source>
<translation>&quot;%1&quot;에 대한 체크섬 불일치가 감지되었습니다.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>원격 리포지토리에서 메타 정보 검색 중... %1/%2 </translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>자료 보관소 &quot;%1&quot; 추출 중에 오류 발생: %2</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>원격 리포지토리에서 메타 정보 검색 중... </translation>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>&quot;%1&quot; 파일을 읽기 위해 열 수 없음: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>아카이브 &quot;%1&quot; 추출 중에 오류 발생: %2</translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>지원되지 않는 &quot;%1&quot; 아카이브: &quot;%2&quot; 파일 접미사를 위해 등록된 핸들러가 없습니다.</translation>
</message>
<message>
- <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <source>Fetching latest update information...</source>
+ <translation>최신 업데이트 정보를 가져오는 중...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>로컬캐시에 새 항목 %n개를 업데이트하는 중...</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>캐시 디렉터리를 모두 삭제하고 애플리케이션을 다시 시작하면 문제를 해결할 수 있습니다.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>캐시 업데이트 도중 알수 없는 예외 발생</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
<translation>&quot;%1&quot; 파일을 읽기 위해 열 수 없음: %2</translation>
</message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>&quot;%1&quot; 파일을 쓰기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>원격 저장소에서 정보를 검색하는 중...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>원격 저장소에서 메타 정보 검색 중...</translation>
+ </message>
</context>
<context>
<name>QInstaller::FileTaskObserver</name>
@@ -1381,10 +1487,8 @@ Error while loading %2</source>
<translation>유지 보수 도구를 쓰는 중에 오류 발생</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-패키지 다운로드 중...</translation>
+ <source>Downloading packages...</source>
+ <translation>패키지 다운로드 중...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1424,7 +1528,7 @@ Downloading packages...</source>
</message>
<message>
<source>The directory you selected already exists and contains an installation. Choose a different target for installation.</source>
- <translation>선택한 디렉토리가 이미 존재하며 설치 항목도 포함되어 있습니다. 설치하려면 다른 디렉토리를 선택하십시오.</translation>
+ <translation>선택한 디렉터리가 이미 존재하며 설치 항목도 포함되어 있습니다. 설치하려면 다른 디렉토리를 선택하십시오.</translation>
</message>
<message>
<source>Warning</source>
@@ -1435,7 +1539,7 @@ Downloading packages...</source>
Note that it will be completely wiped on uninstallation of this application.
It is not advisable to install into this directory as installation might fail.
Do you want to continue?</source>
- <translation>파일이 이미 있는 기존 디렉토리를 설치 디렉토리로 선택하셨습니다.
+ <translation>파일이 이미 있는 기존 디렉터리를 설치 디렉토리로 선택하셨습니다.
이 애플리케이션을 제거할 때 디렉토리가 완전히 삭제되오니 유의하십시오.
설치가 실패할 수 있으므로 이 디렉토리에 설치하는 것은 권장하지 않습니다.
계속하시겠습니까?</translation>
@@ -1446,7 +1550,7 @@ Do you want to continue?</source>
</message>
<message>
<source>The installation path cannot be empty, please specify a valid directory.</source>
- <translation>설치 경로가 비어 있으면 안 됩니다. 유효한 디렉토리를 선택하십시오.</translation>
+ <translation>설치 경로가 비어 있으면 안 됩니다. 유효한 디렉터리를 선택하십시오.</translation>
</message>
<message>
<source>The installation path cannot be relative, please specify an absolute path.</source>
@@ -1454,7 +1558,7 @@ Do you want to continue?</source>
</message>
<message>
<source>The path or installation directory contains non ASCII characters. This is currently not supported! Please choose a different path or installation directory.</source>
- <translation>설치 경로 또는 디렉토리에 ASCII 문자가 아닌 문자가 포함되어 있습니다. 현재 이는 지원되지 않습니다! 다른 설치 경로나 디렉토리를 선택하십시오.</translation>
+ <translation>설치 경로 또는 디렉터리에 ASCII 문자가 아닌 문자가 포함되어 있습니다. 현재 이는 지원되지 않습니다! 다른 설치 경로나 디렉토리를 선택하십시오.</translation>
</message>
<message>
<source>As the install directory is completely deleted, installing in %1 is forbidden.</source>
@@ -1474,11 +1578,11 @@ Do you want to continue?</source>
</message>
<message>
<source>The installation path must not end with &apos;.&apos;, please specify a valid directory.</source>
- <translation>설치 경로가 &apos;.&apos; 문자로 끝나면 안 됩니다. 유효한 디렉토리를 지정하십시오.</translation>
+ <translation>설치 경로가 &apos;.&apos; 문자로 끝나면 안 됩니다. 유효한 디렉터리를 지정하십시오.</translation>
</message>
<message>
<source>The installation path must not contain &quot;%1&quot;, please specify a valid directory.</source>
- <translation>설치 경로에 &quot;%1&quot; 문자가 포함되면 안 됩니다. 유효한 디렉토리를 지정하십시오.</translation>
+ <translation>설치 경로에 &quot;%1&quot; 문자가 포함되면 안 됩니다. 유효한 디렉터리를 지정하십시오.</translation>
</message>
<message>
<source>Application not running in Package Manager mode.</source>
@@ -1489,10 +1593,6 @@ Do you want to continue?</source>
<translation>설치된 패키지를 찾을 수 없습니다.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>구성요소를 등록할 수 없습니다! %1 식별자가 있는 구성 요소가 이미 존재합니다.</translation>
- </message>
- <message>
<source>Application running in Uninstaller mode.</source>
<translation>애플리케이션이 설치 제거 관리자 모드로 실행 중입니다.</translation>
</message>
@@ -1505,48 +1605,28 @@ Do you want to continue?</source>
<translation>모든 종속성을 해결할 수 없습니다.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>구성요소가 제거됩니다.</translation>
- </message>
- <message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>%1을(를) 설치할 수 없습니다. 구성요소를 찾을 수 없습니다.
-</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>%1을(를) 설치할 수 없습니다. 구성요소를 찾을 수 없습니다.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>%1 구성요소를 설치할 수 없습니다. %2에 대한 자동 종속성으로만 구성요소가 설치됩니다.
-</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>%1 구성요소를 설치할 수 없습니다. %2에 대한 자동 종속성으로만 구성요소가 설치됩니다.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>%1 구성요소를 설치할 수 없습니다. 구성요소를 확인할 수 없어 하위 구성요소 중 하나를 설치해야 합니다.
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>%1 구성요소를 설치할 수 없습니다. 구성요소를 확인할 수 없어 하위 구성요소 중 하나를 설치해야 합니다.</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>%1 구성요소가 이미 설치됨
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>%1 구성요소가 이미 설치됨</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>%1을(를) 설치할 수 없습니다. 구성요소가 가상 구성요소 %2의 하위 항목입니다.
-</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>%1을(를) 설치할 수 없습니다. 구성요소가 가상 구성요소 %2의 하위 항목입니다.</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>%1을(를) 설치할 수 없습니다. 가상 구성요소입니다.
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>실행 중인 프로세스를 찾았습니다.</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>%1을(를) 설치할 수 없습니다. 가상 구성요소입니다.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1565,10 +1645,6 @@ Do you want to continue?</source>
<translation>디스크 공간이 부족하여 선택한 구성요소를 모두 저장할 수 없습니다! %1은(는) 사용 가능하지만 최소한 %2이(가) 필요합니다.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>디스크 공간이 부족하여 임시 파일을 저장할 수 없습니다! %1은(는) 사용 가능하지만 최소한 %2이(가) 필요합니다.</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>설치를 위해 선택한 볼륨은 설치 공간이 충분한 것으로 보이지만, 설치 후에 남은 공간이 볼륨 공간의 %1 미만일 것으로 예상됩니다.</translation>
</message>
@@ -1588,6 +1664,34 @@ Do you want to continue?</source>
<source>Invalid</source>
<translation>유효하지 않음</translation>
</message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>구성요소들이 제거됩니다.</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>%1 구성요소를 설치할 수 없습니다. 해당 구성요소를 불러오는 중 문제가 발생했으므로 불안정한 것으로 표시되었으며 선택할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>디스크 공간이 부족하여 임시 파일을 저장할 수 없습니다. %1은(는) 사용 가능하지만 최소한 %2이(가) 필요합니다. 설치 프로그램 설정에서 로컬 캐시 경로를 수정하여 임시 파일의 다른 위치를 선택할 수 있습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>구성 요소들의 설치 제거를 해결 할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>별칭 %1을 선택할 수 없습니다. 이 명칭을 불러오는 데 문제가 발생해 불안정한 것으로 설정되며 선택할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>%1을 선택할 수 없습니다. 명칭이 가상(virtual)로 설정되어 있으며 이는 수동으로 선택될 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>생성된 설치 프로그램이 %1 디스크 공간을 사용할 것입니다.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCorePrivate</name>
@@ -1657,7 +1761,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation>임시 디렉토리 &quot;%1&quot; 제거가 불가능합니다. %2</translation>
+ <translation>임시 디렉터리 &quot;%1&quot; 제거가 불가능합니다. %2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1673,7 +1777,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation>&quot;1%&quot; 디렉토리를 생성할 수 없습니다.</translation>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
@@ -1681,7 +1785,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation>임시 디렉토리 &quot;%1&quot; 제거가 불가능합니다. %2</translation>
+ <translation>임시 디렉터리 &quot;%1&quot; 제거가 불가능합니다. %2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1697,23 +1801,19 @@ Do you want to continue?</source>
</message>
<message>
<source>Creating local repository</source>
- <translation>로컬 리포지토리 생성 중</translation>
+ <translation>로컬 저장소 생성 중</translation>
</message>
<message>
<source>Creating Maintenance Tool</source>
<translation>유지 보수 도구 생성 중</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-설치가 완료되었습니다!</translation>
+ <source>Installation finished!</source>
+ <translation>설치가 완료되었습니다!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-설치가 중단되었습니다!</translation>
+ <source>Installation aborted!</source>
+ <translation>설치가 중단되었습니다!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1724,16 +1824,12 @@ Installation aborted!</source>
<translation>선택 취소한 구성요소 제거 중...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-업데이트가 완료되었습니다!</translation>
+ <source>Update finished!</source>
+ <translation>업데이트가 완료되었습니다!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-업데이트가 중단되었습니다!</translation>
+ <source>Update aborted!</source>
+ <translation>업데이트가 중단되었습니다!</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1745,7 +1841,7 @@ Update aborted!</source>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation>설치 관리자에 사용할 대상 디렉토리를 생성할 수 없습니다.</translation>
+ <translation>설치 관리자에 사용할 대상 디렉터리를 생성할 수 없습니다.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
@@ -1765,7 +1861,7 @@ Update aborted!</source>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation>임시 디렉토리 &quot;%1&quot; 제거에 실패했습니다.</translation>
+ <translation>임시 디렉터리 &quot;%1&quot; 제거에 실패했습니다.</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
@@ -1776,10 +1872,8 @@ Update aborted!</source>
<translation>오프라인 생성이 중단되었습니다!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-구성요소 %1 설치 중</translation>
+ <source>Installing component %1</source>
+ <translation>구성요소 %1 설치 중</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1826,10 +1920,6 @@ Installing component %1</source>
<translation>메타 정보를 검색할 수 없음: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>임시 업데이트 소스 정보를 추가할 수 없습니다.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>어떠한 업데이트 소스 정보도 추가할 수 없습니다.</translation>
</message>
@@ -1837,6 +1927,50 @@ Installing component %1</source>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>구성요소 &quot;%1&quot; 및 &quot;%2&quot; 간의 종속성 사이클이 감지되었습니다.</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>구성요소들의 압축해제를 준비합니다.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%2 의 %1 작업들을 완료했습니다.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>구성요소들의 압축해제를 준비합니다.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%2 의 %1 작업들을 되돌렸습니다.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>롤백(되돌리기) 작업들을 완료했습니다.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%2 의 %1 구성요소들을 설치했습니다.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>모든 구성요소들을 설치했습니다.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>구성요소 스크립트를 불러오는 중...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>별칭이 존재하는 구성요소 &quot;%1&quot;와 충돌하는 이름을 정의합니다.</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>해결되지 않은 구성 요소 별칭들</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>별칭들 &quot;%1&quot;와 &quot;%2&quot; 사이에 순환 의존성 발견됨.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -1873,12 +2007,12 @@ Installing component %1</source>
<translation>%1 질문</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>설정</translation>
</message>
<message>
<source>Specify proxy settings and configure repositories for add-on components.</source>
- <translation>애드온 구성요소를 위한 프록시 설정과 구성 리포지토리를 지정하십시오.</translation>
+ <translation>애드온 구성요소를 위한 프록시 설정과 구성 저장소를 지정하십시오.</translation>
</message>
<message>
<source>Error</source>
@@ -1894,11 +2028,11 @@ Please copy the installer to a local drive</source>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>설정 - %1</translation>
+ <source>Welcome</source>
+ <translation>환영</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>%1 설정 마법사에 오신 것을 환영합니다.</translation>
</message>
<message>
@@ -1919,23 +2053,19 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>At least one valid and enabled repository required for this action to succeed.</source>
- <translation>이 작업을 성공적으로 수행하려면 최소 1개의 유효하고 활성화된 리포지토리가 필요합니다.</translation>
+ <translation>이 작업을 성공적으로 수행하려면 최소 1개의 유효하고 활성화된 저장소가 필요합니다.</translation>
</message>
<message>
<source>No updates available.</source>
<translation>사용 가능한 업데이트가 없습니다.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> 로컬 패키지 관리만 가능합니다.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>종료(&amp;Q)</translation>
</message>
<message>
<source>There is an important update available. Please select &apos;%1&apos; first</source>
- <translation type="unfinished"></translation>
+ <translation>중요한 업데이트가 있습니다. 먼저 &amp;apos;%1&amp;apos; 을(를) 선택해 주십시오.</translation>
</message>
</context>
<context>
@@ -1974,7 +2104,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Please specify the directory where %1 will be installed.</source>
- <translation>%1이(가) 설치될 디렉토리를 지정하십시오.</translation>
+ <translation>%1이(가) 설치될 디렉터리를 지정하십시오.</translation>
</message>
<message>
<source>Alt+R</source>
@@ -1987,7 +2117,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation>파일 시스템을 탐색하여 설치 디렉토리를 선택합니다.</translation>
+ <translation>파일 시스템을 탐색하여 설치 디렉터리를 선택합니다.</translation>
</message>
<message>
<source>Select Installation Folder</source>
@@ -2002,7 +2132,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Select the Start Menu in which you would like to create the program&apos;s shortcuts. You can also enter a name to create a new directory.</source>
- <translation>프로그램 바로 가기를 생성하려는 시작 메뉴를 선택합니다. 이름을 직접 입력하여 새 디렉토리를 생성할 수도 있습니다.</translation>
+ <translation>프로그램 바로 가기를 생성하려는 시작 메뉴를 선택합니다. 이름을 직접 입력하여 새 디렉터리를 생성할 수도 있습니다.</translation>
</message>
</context>
<context>
@@ -2016,8 +2146,8 @@ Please copy the installer to a local drive</source>
<translation>설치 제거 준비 완료</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
- <translation>컴퓨터에 %1 제거를 시작할 준비가 되었습니다.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;%2 프로그램 디렉토리는 모두 삭제되며&lt;/font&gt;, 해당 디렉토리에 포함된 모든 콘텐츠도 삭제됩니다!</translation>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <translation>컴퓨터에 %1 제거를 시작할 준비가 되었습니다.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;%2 프로그램 디렉터리는 모두 삭제되며&lt;/font&gt;, 해당 디렉토리에 포함된 모든 콘텐츠도 삭제됩니다!</translation>
</message>
<message>
<source>U&amp;pdate</source>
@@ -2028,7 +2158,7 @@ Please copy the installer to a local drive</source>
<translation>패키지 업데이트 준비 완료</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>이제 설치 업데이트를 시작할 준비가 되었습니다.</translation>
</message>
<message>
@@ -2040,13 +2170,25 @@ Please copy the installer to a local drive</source>
<translation>설치 준비 완료</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>컴퓨터에 %1 설치를 시작할 준비가 되었습니다.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>업데이트 준비 완료</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>오프라인 설치 프로그램을 생성합니다.</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>오프라인 설치 프로그램을 생성하기 위해 준비합니다.</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>선택된 구성요소들에 대한 오프라인 설치 프로그램을 생성하기 위한 모든 필요한 정보가 사용 가능합니다</translation>
+ </message>
</context>
<context>
<name>QInstaller::PerformInstallationPage</name>
@@ -2086,11 +2228,23 @@ Please copy the installer to a local drive</source>
<source>Uninstalling</source>
<translation>설치 제거 중</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>오프라인 설치 프로그램을 생성합니다.</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>%1에 대한 오프라인 설치 프로그램을 생성하는 중</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>오프라인 설치 프로그램을 생성하는 중</translation>
+ </message>
</context>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>%1 마법사 완료 중</translation>
</message>
<message>
@@ -2098,7 +2252,7 @@ Please copy the installer to a local drive</source>
<translation>완료됨</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>%2 마법사를 종료하려면 %1을(를) 클릭하십시오.</translation>
</message>
<message>
@@ -2110,14 +2264,14 @@ Please copy the installer to a local drive</source>
<translation>지금 %1을(를) 실행하십시오.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>%1 마법사가 실패했습니다.</translation>
</message>
</context>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>%1 설정 마법사 완료 중</translation>
</message>
</context>
@@ -2248,8 +2402,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>설정 파일 &quot;%1&quot;을(를) 읽기 위해 열 수 없음: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>범주 선택</translation>
+ <source>Categories</source>
+ <translation type="unfinished">범주 선택</translation>
</message>
</context>
<context>
@@ -2290,7 +2444,7 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Empty repository URL.</source>
- <translation>리포지토리 URL이 비었습니다.</translation>
+ <translation>저장소 URL이 비었습니다.</translation>
</message>
<message>
<source>Download canceled.</source>
@@ -2298,7 +2452,7 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Timeout while testing repository &quot;%1&quot;.</source>
- <translation>&quot;%1&quot; 리포지토리를 테스트하는 중에 시간이 초과되었습니다.</translation>
+ <translation>&quot;%1&quot; 저장소를 테스트하는 중에 시간이 초과되었습니다.</translation>
</message>
<message>
<source>Cannot parse Updates.xml: %1</source>
@@ -2314,7 +2468,7 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Unknown error while testing repository &quot;%1&quot;.</source>
- <translation>&quot;%1&quot; 리포지토리를 테스트하는 중에 알 수 없는 오류가 발생했습니다.</translation>
+ <translation>&quot;%1&quot; 저장소를 테스트하는 중에 알 수 없는 오류가 발생했습니다.</translation>
</message>
</context>
<context>
@@ -2436,6 +2590,10 @@ or accept the elevation of access rights if being asked.</source>
<source>Try again</source>
<translation>다시 시도하기</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>%1을(를) 다운로드 할 수 없음. &quot;%2&quot;을(를) 위한 디렉터리를 생성할 수 없음.</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -2619,7 +2777,7 @@ or accept the elevation of access rights if being asked.</source>
<name>KDUpdater::MkdirOperation</name>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
- <translation>&quot;%1&quot; 디렉토리를 생성할 수 없음: %2</translation>
+ <translation>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
</message>
<message>
<source>Unknown error.</source>
@@ -2627,22 +2785,22 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;: %2</source>
- <translation>&quot;1%&quot; 디렉토리를 제거할 수 없음: %2</translation>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없음: %2</translation>
</message>
</context>
<context>
<name>KDUpdater::RmdirOperation</name>
<message>
<source>Cannot remove directory &quot;%1&quot;: %2</source>
- <translation>&quot;1%&quot; 디렉토리를 제거할 수 없음: %2</translation>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없음: %2</translation>
</message>
<message>
<source>The directory does not exist.</source>
- <translation>이 디렉토리가 존재하지 않습니다.</translation>
+ <translation>이 디렉터리가 존재하지 않습니다.</translation>
</message>
<message>
<source>Cannot recreate directory &quot;%1&quot;: %2</source>
- <translation>&quot;1%&quot; 디렉토리를 다시 생성할 수 없습니다. %2</translation>
+ <translation>&quot;1%&quot; 디렉터리를 다시 생성할 수 없습니다. %2</translation>
</message>
</context>
<context>
@@ -2706,10 +2864,6 @@ or accept the elevation of access rights if being asked.</source>
<translation>&quot;%1&quot;을(를) 읽을 수 없음</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>%2의 %1에서 파싱 오류 발생, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>%1 루트 요소는 예상하지 못했습니다. &apos;Updates&apos;여야 합니다.</translation>
</message>
@@ -2745,27 +2899,185 @@ or accept the elevation of access rights if being asked.</source>
<name>QInstaller::ExtractArchiveOperation::Worker</name>
<message>
<source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>&quot;%1&quot; 아카이브를 위한 핸들러 객체를 만들지 못함: &quot;%2&quot;.</translation>
</message>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
<translation>&quot;%1&quot; 아카이브를 읽기 위해 열 수 없음: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>아카이브 &quot;%1&quot; 추출 중에 오류 발생: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>아카이브를 읽기 위해 열 수 없음: %1</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>항목 헤더를 읽을 수 없음: %1</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>아카이브 &quot;%1&quot; 추출 중에 오류 발생: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>&quot;%1&quot; 항목을 디스크에 쓸 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>아카이브를 읽기 위해 열 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>항목 헤더를 읽을 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>&quot;%1&quot; 항목을 디스크에 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>&quot;%1&quot; 파일을 쓰기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>&quot;%1&quot; 파일을 읽기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;에 대한 항목 헤더를 쓸 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>선택 해제된 구성요소들</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>&quot;%1&quot; 에 의해 대체된 구성요소들</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>의존성이 존재하지 않는 가상 구성요소들을 삭제하는 중</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>삭제된 &quot;%1&quot; 구성요소 종속성</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>삭제된 &quot;%1&quot; 구성요소 자동 종속성</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>%1 설치 관리자에 대하여</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>%1 유지 보수 도구에 대하여</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>빈 경로에 캐시를 초기화할 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>캐시 디렉터리 &quot;%1&quot;를 만들 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>캐시를 초기화할 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>무효화한 캐시를 삭제할 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>매니페스트 파일을 삭제할 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>캐시를 모두 삭제하는 중 오류 발생: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>무효화한 캐시에서 아이템들을 가져올 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>무효화한 캐시에서 아이템을 가져올 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>무효화한 캐시에 아이템을 등록할 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>빈 아이템을 등록할 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>체크섬 %1 무효한 아이템을 등록할 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>체크섬 %1 무효한 아이템을 등록할 수 없음. 같은 체크섬을 가진 아이템이 캐시에 있습니다.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>아이템을 &quot;%1&quot;경로에 복사하는 중 오류 발생: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>무효화한 캐시에서 아이템을 지울 수 없음.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>체크섬 %1 아이템을 지울 수 없음: 해당 아이템이 없음.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 디렉터리를 지우는 중 오류 발생: %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>캐시를 무효화하는 중 오류 발생: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>매니페스트 파일을 열 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>매니페스트 파일 내용을 쓸 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>무효화된 캐시를 동기화할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>알 수 없는 등록 방법이 사용됨!</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>캐시 삭제를 성공했습니다!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_pl.ts b/src/sdk/translations/ifw_pl.ts
index 82be662dc..572ea5ddc 100644
--- a/src/sdk/translations/ifw_pl.ts
+++ b/src/sdk/translations/ifw_pl.ts
@@ -16,7 +16,7 @@
<name>BinaryContent</name>
<message>
<source>Cannot seek to %1 to read the operation data.</source>
- <translation>Nie można przejść do %1 w celu odczytania danych operacji.</translation>
+ <translation>Nie można przejść do %1 w celu odczytania danych operacji</translation>
</message>
<message>
<source>Cannot seek to %1 to read the resource collection block.</source>
@@ -107,7 +107,7 @@
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można uruchomić instalatora</translation>
</message>
</context>
<context>
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Nie można znaleźć brakującej zależności &quot;%1&quot; dla &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -310,6 +322,10 @@
<source>Try again</source>
<translation>Spróbuj ponownie</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -494,10 +510,6 @@
<translation>Nie można odczytać &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Błąd analizy w %1 przy %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Nieoczekiwany element główny %1, powinno być &quot;Aktualizacje&quot;.</translation>
</message>
@@ -590,11 +602,11 @@
</message>
<message>
<source>Internal code: %1</source>
- <translation type="unfinished"></translation>
+ <translation>Kod wewnętrzny: %1</translation>
</message>
<message>
<source>Not enough memory</source>
- <translation type="unfinished"></translation>
+ <translation>Za mało pamięci</translation>
</message>
</context>
<context>
@@ -739,7 +751,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można skopiować pliku &quot;%1&quot; do &quot;%2&quot;.</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -747,6 +759,10 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
+ <translation>Nieprawidłowa zawartość w &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -757,18 +773,6 @@
<translation>Elementy nie mogą mieć elementów podrzędnych w trybie programu aktualizującego.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Nie można otworzyć żądanego pliku interfejsu użytkownika &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Nie można wczytać żądanego pliku interfejsu użytkownika &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Nie można otworzyć żądanego pliku licencji &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Błąd</translation>
</message>
@@ -786,7 +790,31 @@
</message>
<message>
<source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></translation>
+ <translation>Podczas ładowania wybranego komponentu wystąpił błąd. Nie można zainstalować tego składnika.</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nie można otworzyć żądanego pliku interfejsu użytkownika &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nie można wczytać żądanego pliku interfejsu użytkownika &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Nie można otworzyć żądanego pliku licencji &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -835,44 +863,40 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>&amp;Domyślne</translation>
+ <source>Default</source>
+ <translation>Domyślne</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
- <translation type="unfinished"></translation>
+ <translation>Zaznacz domyślne komponenty.</translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Resetuj</translation>
+ <source>Reset</source>
+ <translation>Resetuj</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
- <translation type="unfinished"></translation>
+ <translation>Zresetuj wszystkie komponenty do ich pierwotnego stanu zaznaczenia.</translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>&amp;Zaznacz wszystkie</translation>
+ <source>Select All</source>
+ <translation>Zaznacz wszystkie</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
- <translation type="unfinished"></translation>
+ <translation>Zaznacz wszystkie komponenty.</translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Usuń zaznaczenie wszystkich</translation>
+ <source>Deselect All</source>
+ <translation>Usuń zaznaczenie wszystkich</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Znajdź pliki QBSP</translation>
+ <translation>Odznacz wszystkie komponenty.</translation>
</message>
<message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
- <translation type="unfinished"></translation>
+ <translation>Wybierz plik Qt Board Support Package, aby zainstalować dodatkową zawartość, która nie jest bezpośrednio dostępna w repozytoriach online.</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -899,37 +923,41 @@
<translation>Wybierz elementy, które chcesz odinstalować.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Wybierz elementy do zainstalowania. Anuluj zaznaczenie zainstalowanych elementów, aby je dezinstalować. Elementy, które są już zainstalowane, nie zostaną zaktualizowane.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Wybierz elementy do zainstalowania. Anuluj zaznaczenie zainstalowanych elementów, aby je dezinstalować.&lt;br&gt;Elementy, które są już zainstalowane, nie zostaną zaktualizowane.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
- <translation type="unfinished"></translation>
+ <translation>Wymagane komponenty muszą zostać zaktualizowane, zanim będzie można wybrać inne komponenty do aktualizacji</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Filter the enabled repository categories</source>
+ <translation>Filtruj włączone kategorie repozytorium</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Search</source>
+ <translation>Szukaj</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
+ <source>Browse &amp;QBSP files</source>
+ <translation>&amp;Znajdź pliki QBSP</translation>
+ </message>
+ <message>
+ <source>Select</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Błąd</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -946,12 +974,8 @@
<translation>Nie można zapisać danych wynikowych &quot;%1&quot; do pustej wartości klucza instalacyjnego.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Plik &quot;%1&quot; nie istnieje lub nie jest wykonywalnym plikiem binarnym.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Uruchamianie &quot;%1&quot; spowodowało awarię.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>Nie udało się uruchomić polecenia: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -1050,11 +1074,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można utworzyć ścieżki &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można usunąć katalogu &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1092,6 +1116,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>Nie można utworzyć archiwum &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Nieobsługiwane archiwum &quot;%1&quot;: nie zarejestrowano uchwytu dla pliku z rozszerzeniem &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1162,7 +1190,7 @@ Błąd podczas wczytywania %2</translation>
</message>
<message>
<source>%1 downloaded.</source>
- <translation type="unfinished">Liczba pobranych: %1.</translation>
+ <translation>Pobrano: %1.</translation>
</message>
<message numerus="yes">
<source>%n day(s), </source>
@@ -1202,6 +1230,18 @@ Błąd podczas wczytywania %2</translation>
</message>
<message>
<source> - unknown time remaining.</source>
+ <translation> - nieznany czas do ukończenia.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>Archiwum: </translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation>Razem: </translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1345,7 +1385,7 @@ Błąd podczas wczytywania %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Wykonywanie Kreatora %1</translation>
</message>
<message>
@@ -1353,7 +1393,7 @@ Błąd podczas wczytywania %2</translation>
<translation>Zakończone</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Kliknij pozycję %1, aby zamknąć Kreator %2.</translation>
</message>
<message>
@@ -1365,7 +1405,7 @@ Błąd podczas wczytywania %2</translation>
<translation>Uruchom %1 teraz.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Działanie Kreatora %1 nie powiodło się.</translation>
</message>
</context>
@@ -1406,15 +1446,19 @@ Błąd podczas wczytywania %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Nie można utworzyć katalogu &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>Nie można utworzyć kopii zapasowej pliku&quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Konfiguracja - %1</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Witamy w Kreatorze konfiguracji %1.</translation>
</message>
<message>
@@ -1442,16 +1486,12 @@ Błąd podczas wczytywania %2</translation>
<translation>Brak dostępnych aktualizacji.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Dostępne jedynie lokalne zarządzanie pakietami.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Zakończ</translation>
</message>
<message>
<source>There is an important update available. Please select &apos;%1&apos; first</source>
- <translation type="unfinished"></translation>
+ <translation>Dostępna jest ważna aktualizacja. Wybierz najpierw &apos;%1&apos; </translation>
</message>
</context>
<context>
@@ -1479,7 +1519,7 @@ Błąd podczas wczytywania %2</translation>
<message>
<source>Alt+A</source>
<comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
+ <translation>Alt+A</translation>
</message>
</context>
<context>
@@ -1496,16 +1536,12 @@ Błąd podczas wczytywania %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Nie można zapisać pliku licencji: &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Nie znaleziono plików licencji do usunięcia.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>Nieprawidłowy argument w %1: Pusty argument wyszukiwania nie jest obsługiwany</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1523,10 +1559,6 @@ Błąd podczas wczytywania %2</translation>
<translation>Brak podstawowego mechanizmu menedżera pakietów.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Przygotowanie metainformacji do pobrania...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Rozpakowywanie skompresowanych repozytoriów. Może to chwilę potrwać...</translation>
</message>
@@ -1559,14 +1591,6 @@ Błąd podczas wczytywania %2</translation>
<translation>Wykryto niezgodność sumy kontrolnej dla &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Pobieranie metainformacji z repozytorium zdalnego... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Pobieranie metainformacji z repozytorium zdalnego... </translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>Błąd podczas wyodrębniania archiwum &quot;%1&quot;: %2</translation>
</message>
@@ -1576,8 +1600,48 @@ Błąd podczas wczytywania %2</translation>
</message>
<message>
<source>Metadata download canceled.</source>
+ <translation>Anulowano pobieranie metadanych.</translation>
+ </message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Nieznane archiwum &quot;%1&quot;: brak zarejestrowanego uchwytu dla pliku z rozszerzeniem &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
<translation type="unfinished"></translation>
</message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Nie można otworzyć pliku &quot;%1&quot; do zapisu: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Pobieranie informacji ze zdalnych repozytoriów...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Pobieranie metainformacji z repozytorium zdalnego...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1586,10 +1650,8 @@ Błąd podczas wczytywania %2</translation>
<translation>Błąd zapisu w narzędziu konserwacji</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Pobieranie pakietów...</translation>
+ <source>Downloading packages...</source>
+ <translation>Pobieranie pakietów...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1694,36 +1756,24 @@ Czy chcesz kontynuować?</translation>
<translation>Nie można rozwiązać wszystkich zależności.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Elementy mają zostać usunięte.</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>Nie można zainstalować komponentu %1. Komponent jest instalowany tylko jako automatyczna zależność od %2.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>Komponent %1 jest już zainstalowany</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>Nie można zainstalować %1. Komponent jest wirtualny.</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>Nie można zainstalować %1. Komponent nieznaleziony.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można podnieść praw dostępu podczas uruchamiania z wiersza poleceń. Uruchom ponownie aplikację jako administrator.</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1735,11 +1785,11 @@ Czy chcesz kontynuować?</translation>
</message>
<message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
- <translation type="unfinished"></translation>
+ <translation>Wolumin wybrany do instalacji wydaje się mieć wystarczającą ilość miejsca do instalacji, ale później będzie dostępne mniej niż 1% miejsca na wolumenie.</translation>
</message>
<message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 100 MB available afterwards.</source>
- <translation type="unfinished"></translation>
+ <translation>Wolumin wybrany do instalacji wydaje się mieć wystarczającą ilość miejsca do instalacji, ale później będzie dostępne mniej niż 100 MB.</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
@@ -1747,44 +1797,62 @@ Czy chcesz kontynuować?</translation>
</message>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
+ <translation>Wymagane jest wprowadzenie danych przez użytkownika, ale urządzenie wyjściowe nie jest powiązane z terminalem.</translation>
</message>
<message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
- <translation type="unfinished"></translation>
+ <translation>Szacowany rozmiar instalatora %1 przekroczyłby obsługiwany limit rozmiaru pliku wykonywalnego %2. Aplikacja może nie działać.</translation>
</message>
<message>
<source>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <translation>Anulowanie instalacji</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>Nie można zainstalować składnika %1. Komponent nie jest dostępny, co oznacza, że ​​musisz wybrać jeden z podkomponentów.</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>Nie można zainstalować %1. Komponent jest potomkiem komponentu wirtualnego %2.</translation>
</message>
<message>
<source>Not enough disk space to store temporary files and the installation. %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <translation>Za mało miejsca na dysku do zapisu plików tymczasowych i instalacji. %1 jest dostępnych, podczas gdy wymagane minimum to %2.</translation>
</message>
<message>
<source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
+ <translation>Za mało miejsca na dysku do zapisu wszystkich wybranych komponentów! %1 jest dostępnych, podczas gdy wymagane minimum to %2.</translation>
+ </message>
+ <message>
+ <source>Invalid</source>
+ <translation>Nieprawidłowy</translation>
+ </message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>Komponenty do usunięcia</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>Nie można zainstalować komponentu %1. Wystąpił problem z jego załadowaniem, został oznaczony jako niestabilny i nie można go wybrać</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
+ <source>Cannot resolve components to uninstall.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Invalid</source>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1819,7 +1887,7 @@ Czy chcesz kontynuować?</translation>
%1</source>
<translation>Poniższe procesy powinny być zatrzymane, aby kontynuować:
-
+
%1</translation>
</message>
<message>
@@ -1828,7 +1896,7 @@ Czy chcesz kontynuować?</translation>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>Przekroczono liczbę ponownych prób</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
@@ -1856,7 +1924,7 @@ Czy chcesz kontynuować?</translation>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można usunąć pliku tymczasowego &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1864,7 +1932,7 @@ Czy chcesz kontynuować?</translation>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>Zapisywanie instalatora offline.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1876,11 +1944,11 @@ Czy chcesz kontynuować?</translation>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można zapisać installatora offline &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można usunąć pliku tymczasowego &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1903,16 +1971,12 @@ Czy chcesz kontynuować?</translation>
<translation>Tworzenie narzędzia konserwacji</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Ukończono instalację!</translation>
+ <source>Installation finished!</source>
+ <translation>Ukończono instalację!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Przerwano instalację!</translation>
+ <source>Installation aborted!</source>
+ <translation>Przerwano instalację!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1923,54 +1987,48 @@ Przerwano instalację!</translation>
<translation>Trwa usuwanie elementów, których zaznaczenie wyłączono...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Aktualizacja zakończona!</translation>
+ <source>Update finished!</source>
+ <translation>Aktualizacja zakończona!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Aktualizację przerwano!</translation>
+ <source>Update aborted!</source>
+ <translation>Aktualizację przerwano!</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można utworzyć docelowego katalogu instalacji.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>Przygotowywanie instalatora offline...</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>Konfigurowanie instalatora...</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>Tworzenie instalatora...</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>Nie udało się utworzyć instalatora offline. %1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można usunąć katalogu tymczasowego &quot;%1&quot;.</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>Tworzenie instalatora offline zakończone sukcesem.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></translation>
+ <translation>Przerwano generowanie instalatora offline</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Trwa instalowanie elementu %1</translation>
+ <source>Installing component %1</source>
+ <translation>Trwa instalowanie elementu %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1984,7 +2042,7 @@ Trwa instalowanie elementu %1</translation>
</message>
<message>
<source>Done</source>
- <translation type="unfinished"></translation>
+ <translation>Zrobione</translation>
</message>
<message>
<source>Unknown error</source>
@@ -2003,10 +2061,6 @@ Trwa instalowanie elementu %1</translation>
<translation>Nie można pobrać metainformacji: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Nie można dodać informacji o tymczasowym źródle aktualizacji.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Nie można znaleźć żadnych informacji o źródle aktualizacji.</translation>
</message>
@@ -2016,23 +2070,68 @@ Trwa instalowanie elementu %1</translation>
</message>
<message>
<source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>Usuwanie zakończone pomyślnie.</translation>
</message>
<message>
<source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <translation>Usuwanie przerwane.</translation>
</message>
<message>
<source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można przygotować usunięcia</translation>
</message>
<message>
<source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można rozpocząć usuwania</translation>
</message>
<message>
<source>Error during removal process:
%1</source>
+ <translation>Błąd podczas procesu usuwania:
+%1</translation>
+ </message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>Przygotowanie do usunięcia komponentów...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>Ukończono %1 z %2 operacji.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>Rozpakowywanie komponentów...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>Wycofano %1 z %2 operacji.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>Wycofywanie zakończone.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>Zainstalowano %1 z %2 komponentów.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>Wszystkie komponenty zostały zainstalowane</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2067,12 +2166,12 @@ Trwa instalowanie elementu %1</translation>
<translation>Pytanie: %1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Parametry</translation>
</message>
<message>
<source>Specify proxy settings and configure repositories for add-on components.</source>
- <translation type="unfinished"></translation>
+ <translation>Ustaw proxy i skonfiguruj repozytoria dla komponentów dodatkowych.</translation>
</message>
<message>
<source>Error</source>
@@ -2086,7 +2185,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></translation>
+ <translation>Przerwać proces usuwania?</translation>
</message>
</context>
<context>
@@ -2132,10 +2231,22 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>Aktualizowanie</translation>
</message>
<message>
<source>Uninstalling</source>
+ <translation>Odinstalowywanie</translation>
+ </message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2181,7 +2292,7 @@ Please copy the installer to a local drive</source>
<translation>Gotowy do dezinstalacji</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Instalator jest już gotowy, aby rozpocząć usuwanie %1 z komputera.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;Katalog programu %2 zostanie w całości usunięty&lt;/font&gt;, włącznie z całą zawartością!</translation>
</message>
<message>
@@ -2193,7 +2304,7 @@ Please copy the installer to a local drive</source>
<translation>Gotowy do aktualizacji pakietów</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>Instalator jest już gotowy do rozpoczęcia aktualizowania instalacji.</translation>
</message>
<message>
@@ -2205,11 +2316,23 @@ Please copy the installer to a local drive</source>
<translation>Gotowy do instalacji</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Instalator jest gotowy do rozpoczęcia instalacji %1 na komputerze.</translation>
</message>
<message>
<source>Ready to Update</source>
+ <translation>Gotowy do aktualizacji</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2235,11 +2358,11 @@ Please copy the installer to a local drive</source>
<name>QInstaller::ReplaceOperation</name>
<message>
<source>Current search argument calling &quot;%1&quot; with empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>Argument &quot;%1&quot; nie możbe być pusty.</translation>
</message>
<message>
<source>Current mode argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use string or regex.</source>
- <translation type="unfinished"></translation>
+ <translation>Wybrany tryb wyszukiwania &quot;%1&quot; z argumentami &quot;%2&quot; nie jest wspierany. Użyj string lub regex.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2268,7 +2391,7 @@ Please copy the installer to a local drive</source>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Wykonywanie Kreatora instalacji %1</translation>
</message>
</context>
@@ -2303,7 +2426,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <translation>Self Restart: Działa tylko w trybie aktualizacji lub menedżera pakietów.</translation>
</message>
</context>
<context>
@@ -2337,7 +2460,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Current method argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use set, remove, add_array_value, or remove_array_value.</source>
- <translation type="unfinished"></translation>
+ <translation>Wywołanie metody &quot;%1&quot; z argumentami &quot;%2&quot; nie jest wspierane. Użyj: set, remove, add_array_value, or remove_array_value.</translation>
</message>
</context>
<context>
@@ -2386,7 +2509,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>Przeglądaj system plików i wybierz katalog instalacji.</translation>
</message>
<message>
<source>Select Installation Folder</source>
@@ -2395,7 +2518,7 @@ Please copy the installer to a local drive</source>
<message>
<source>Alt+R</source>
<comment>Browse file system to choose a file</comment>
- <translation type="unfinished">Alt+R</translation>
+ <translation>Alt+R</translation>
</message>
</context>
<context>
@@ -2441,35 +2564,35 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Another %1 instance is already running. Wait until it finishes, close it, or restart your system.</source>
- <translation>Inna instancja %1 już działa. Poczekaj, aż zakończy działanie, i zamknij ją lub uruchom ponownie system.</translation>
+ <translation>Inna instancja %1 już działa. Poczekaj, aż zakończy działanie i zamknij ją lub uruchom ponownie system.</translation>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można uruchomić instalatora w trybie aktualizacji.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można uruchomić instalatora w trybie menedżera pakietów.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można uruchomić instalatora w trybie deinstalacji.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Pusta lista repozytoriów dla opcji &apos;addRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Pusta lista repozytoriów dla opcji &apos;addTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Pusta lista repozytoriów dla opcji &apos;setTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Pusta lista repozytoriów dla opcji &apos;installCompressedRepository&apos;.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2477,18 +2600,26 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>Brakuje argumentów dla opcji %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>Nieprawidłowa wartość przycisku %1 </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>Nieprawidłowe argumenty dla %1</translation>
</message>
<message>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
+ <translation>Upewnij się, że bieżący użytkownik ma uprawnienia do odczytu pliku &quot;%1&quot; lub spróbuj uruchomić %2 jako administrator.</translation>
+ </message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>Nieprawidłowa wartość dla &apos;max-concurrent-operations&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2517,7 +2648,10 @@ jako użytkownik z odpowiednimi prawami, a następnie kliknij przycisk OK.</tran
Please start the setup program as a user with the appropriate rights,
or accept the elevation of access rights if being asked.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można uzyskać autoryzacji potrzebnej do kontynuowania instalacji.
+
+ Uruchom program instalacyjny jako użytkownik z odpowiednimi uprawnieniami
+ lub zaakceptuj podniesienie praw dostępu, jeśli zostaniesz o to poproszony.</translation>
</message>
</context>
<context>
@@ -2534,8 +2668,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>Nie można otworzyć pliku ustawień %1 do odczytu: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>Kategorie</translation>
</message>
</context>
<context>
@@ -2662,14 +2796,38 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation>Zaznacz wszystko</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation>Odznacz wszysto</translation>
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>Adres URL serwera, który zawiera prawidłowe repozytorium.</translation>
+ </message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2728,56 +2886,230 @@ or accept the elevation of access rights if being asked.</source>
<name>QInstaller::ComponentSelectionPagePrivate</name>
<message>
<source>Filter</source>
- <translation type="unfinished"></translation>
+ <translation>Filtr</translation>
</message>
<message>
<source>Error</source>
<translation>Błąd</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Informacja</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation</name>
<message>
<source>Extracting &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <translation>Rozpakowywanie &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Niewspierane archiwum &quot;%1&quot;: nie zarejestrowano obsługi pliku: &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Nie można otworzyć archiwum &quot;%1&quot; do odczytu: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Błąd podczas odczytu archiwum &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Usuwanie plików wypakowanych z &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>Wymagane jest wprowadzenie danych przez użytkownika, ale urządzenie wyjściowe nie jest powiązane z terminalem.</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation::Worker</name>
<message>
<source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Nie można utworzyć uchwytu dla archiwum &quot;%1&quot;: &quot;%2&quot;.</translation>
</message>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
- <translation type="unfinished">Nie można otworzyć archiwum &quot;%1&quot; do odczytu: %2</translation>
+ <translation>Nie można otworzyć archiwum &quot;%1&quot; do odczytu: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Błąd podczas rozpakowywania archiwum &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>O instalatorze %1</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>O narzędziu do konserwacji %1</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Nie można otworzyć archiwum: %1 do odczytu</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>Nie można odczytać nagłówka: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Nie można utworzyć wpisu &quot;%1&quot; na dysku: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Nie można otworzyć archiwum: %1 do odczytu</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>Nie można odczytać nagłówka: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Nie można utworzyć wpisu &quot;%1&quot; na dysku: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Nie można otworzyć pliku &quot;%1&quot; do zapisu: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Nie można otworzyć pliku &quot;%1&quot; do odczytu: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>Nie można zapisać nagłówka dla &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>Odznaczone komponenty:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>Komponenty zastąpione przez &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>Usuwanie wirtualnych komponentów nie posiadających zależności:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>Usunięte zależności komponentu &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>Usunięte automatyczne zależności komponentu &quot;%1&quot;:</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
+ <source>Cannot initialize cache: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation type="unfinished">Błąd podczas wyodrębniania archiwum &quot;%1&quot;: %2</translation>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_pt.ts b/src/sdk/translations/ifw_pt.ts
index a616a5b56..13b491af8 100644
--- a/src/sdk/translations/ifw_pt.ts
+++ b/src/sdk/translations/ifw_pt.ts
@@ -212,6 +212,30 @@
<source>Deselect All</source>
<translation>Deselecionar Todos</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>Cache local</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>As informações meta de repositórios remotos são armazenadas em cache no disco para melhorar os tempos de carregamento. Você pode selecionar outro diretório para armazenar o cache ou limpar o conteúdo do cache atual.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>Caminho para o cache:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>Exclui o conteúdo do diretório de cache</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>Limpar cache</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>Limpando cache...</translation>
+ </message>
</context>
<context>
<name>QObject</name>
@@ -271,6 +295,14 @@
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>Por favor verique que o utilizador atual tem permissões de leitura ao ficheiro &amp;quot;%1&amp;quot; ou execute %2 como administrador.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>O valor de &apos;max-concurrent-operations&apos; não é válido.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>Valor vazio para a opção &apos;cache-path&apos;.</translation>
+ </message>
</context>
<context>
<name>QInstaller</name>
@@ -292,7 +324,7 @@
</message>
<message>
<source>Copy failed: %1</source>
- <translation>Ocorreu um erro na cópia: %1</translation>
+ <translation>Ocorreu um erro a copiar: %1</translation>
</message>
<message>
<source>Write failed after %1 bytes: %2</source>
@@ -382,6 +414,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>O conteúdo em &quot;%1&quot; é inválido.</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>Esta situação pode ficar resolvida se reiniciar a aplicação após limpar a cache:</translation>
+ </message>
</context>
<context>
<name>BinaryLayout</name>
@@ -442,18 +478,6 @@
<translation>Em modo de atualização os componentes não podem descendentes.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Ocorreu um erro a abrir o ficheiro da interface &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Ocorreu um erro a carregar o ficheiro da interface do utilizador &quot;%1&quot;:%2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Ocorreu um erro a abrir o ficheiro de licença &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Erro</translation>
</message>
@@ -473,6 +497,30 @@
<source>There was an error loading the selected component. This component cannot be installed.</source>
<translation>Ocorreu um erro ao carregar o componente selecionado. Este componente não pode ser instalado.</translation>
</message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Ocorreu um erro a abrir o ficheiro da interface &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Ocorreu um erro a carregar o ficheiro da interface do utilizador &quot;%1&quot;:%2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Ocorreu um erro a abrir o ficheiro de licença &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::ComponentModel</name>
@@ -532,12 +580,8 @@
<translation>Não é possível guardar o retorno de &quot;%1&quot; numa chave de instalação vazia.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>O ficheiro &quot;%1&quot; não existe ou não é executável.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Ocorreu uma saida abrupta durante a execução de &quot;%1&quot;.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>Não é possível executar o comando: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -678,6 +722,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>Não é possível criar o ficheiro &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>O ficheiro &quot;%1&quot; não é suportado. Não está registado um programa para a extensão &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -794,6 +842,10 @@ Erro ao carregar %2</translation>
<source>Total: </source>
<translation>Total:</translation>
</message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>Excedeu o número máximo de tentativas (%1).</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -968,12 +1020,24 @@ Erro ao carregar %2</translation>
</message>
<message>
<source>Recursion detected, component &quot;%1&quot; already added with reason: &quot;%2&quot;</source>
- <translation>Foi detectado um ciclo recursivo, componente &quot;%1&quot; já foi adicionado com o motivo: &quot;%2&quot;</translation>
+ <translation>Foi detectado um ciclo recursivo, o componente &quot;%1&quot; já foi adicionado devido a: &quot;%2&quot;</translation>
</message>
<message>
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Não foi possível encontrar a dependência &quot;%1&quot; para &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>Foi detetado uma dependência impossível de resolver. A instalação do componente &quot;%1&quot; teria de ser desinstalado devido à dependência &quot;%2&quot; que se encontra sinalizada para desinstalar por: &quot;%3&quot;.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>Componentes selecionados pelo &apos;alias&apos; &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>Foi detectado um ciclo recursivo, o &apos;alias&apos; do componente &quot;%1&quot; já foi adicionado devido a: &quot;%2&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::InstallIconsOperation</name>
@@ -1001,6 +1065,10 @@ Erro ao carregar %2</translation>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Não é possível criar o diretório &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>Não é possível preparar para a cópia de segurança &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>Lib7z</name>
@@ -1129,10 +1197,6 @@ Erro ao carregar %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Não é possível guardar o ficheiro de licença &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Não foi encontrado ficheiro de licença para ser excluído.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1156,10 +1220,6 @@ Erro ao carregar %2</translation>
<translation>O motor principal do gestor de pacotes não está disponível.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>A preparar o descarregamento de metadados...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>A descompactar repositórios. Por favor espere...</translation>
</message>
@@ -1188,14 +1248,6 @@ Erro ao carregar %2</translation>
<translation>Incompatibilidade detectada na verificação para &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>A obter metadados do repositório remoto...%1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>A obter metainformação do repositório remoto... </translation>
- </message>
- <message>
<source>Failure to fetch repositories.</source>
<translation>Ocorreu um erro ao obter repositórios.</translation>
</message>
@@ -1211,6 +1263,45 @@ Erro ao carregar %2</translation>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>Não é possível abrir o ficheiro &quot;%1&quot; para leitura: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>O ficheiro &quot;%1&quot; não é suportado. Não está registado um programa para a extensão &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>Buscando informações de atualização mais recentes...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>Atualizando o cache local com %n novo item...</numerusform>
+ <numerusform>Atualizando o cache local com %s novos itens...</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>Limpar o diretório de cache e reiniciar o aplicativo pode resolver esta situação.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Ocorreu um erro durante a actualização da cache.</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>Não foi possível abrir o ficheiro &quot;%1&quot; para leitura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Não foi possível abrir o ficheiro &quot;%1&quot; para escrita: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>A obter informações de repositórios remotos...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>A obter metainformação do repositório remoto...</translation>
+ </message>
</context>
<context>
<name>QInstaller::FileTaskObserver</name>
@@ -1270,10 +1361,8 @@ Erro ao carregar %2</translation>
<translation>Erro ao guardar a Ferramenta de Manutenção</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-A descarregar pacotes...</translation>
+ <source>Downloading packages...</source>
+ <translation>A descarregar pacotes...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1382,42 +1471,24 @@ De certeza que deseja continuar?</translation>
<translation>Não é possível obter todas as dependências.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Componentes a serem removidos.</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>Não é possível instalar o componente %1. O componente é instalado apenas como dependência automática de %2.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>Não é possível instalar o componente %1. O componente é instalado apenas como dependência automática de %2.
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>Não é possível instalar o componente %1. O componente não é verificável, o que significa que um dos subcomponentes deve ser selecionado.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>Não é possível instalar o componente %1. O componente não é verificável, o que significa que um dos subcomponentes deve ser selecionado.
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>Componente %1 já foi instalado</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>Componente %1 já foi instalado
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>Não é possível instalar %1. É um componente virtual.</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>Não é possível instalar %1. É um componente virtual.
-</translation>
- </message>
- <message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>Não é possível instalar %1. O componente não foi encontrado.
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>Foram encontrados processos em execução.</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>Não é possível instalar %1. O componente não foi encontrado.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1440,10 +1511,6 @@ De certeza que deseja continuar?</translation>
<translation>Não há espaço em disco suficiente para armazenar todos os componentes selecionados! Estão disponíveis %1, mas é necessário no mínimo %2.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>Não há espaço em disco suficiente para armazenar ficheiros temporários! Estão disponíveis %1, mas é necessário no mínimo %2.</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>O volume que selecionou para instalação tem espaço suficiente para instalação, mas posteriormente terá menos de 1% do espaço disponível.</translation>
</message>
@@ -1464,19 +1531,41 @@ De certeza que deseja continuar?</translation>
<translation>É necessário a interação com o utilizador, mas o dispositivo de saída não está associado a uma linha de comandos.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>Não é possível registar o componente! Já existe um componente com o identificador %1.</translation>
- </message>
- <message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>Não é possível instalar %1. O componente é descendente de um componente virtual %2.
-</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>Não é possível instalar %1. O componente é descendente de um componente virtual %2.</translation>
</message>
<message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation>O tamanho estimado do instalador é %1 e irá exceder o limite de tamanho executável de %2. A aplicação pode não iniciar. </translation>
</message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>Os seguintes componentes irão ser removidos:</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>Não é possível instalar o componente %1. Ocorreu um problema ao carregar o componente, este foi sinalizado como instável e não pode ser selecionado.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>Não há espaço em disco suficiente para armazenar arquivos temporários! %1 estão disponíveis, enquanto o mínimo necessário é %2. Você pode selecionar outro local para os arquivos temporários modificando o caminho do cache local nas configurações do instalador.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Não foi possível resolver os componentes a serem desinstalados</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>O &apos;alias&apos; %1 não pode ser selecionado. Ocorreu um problema a carregar este &apos;alias&apos;, foi marcado com instável e não pode ser selecionado.</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>O &apos;alias&apos; %1 não pode ser selecionado. Este &apos;alias&apos; está categorizado como virtual, o que significa que não pode ser selecionado manualmente.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>O instalador criado irá utilizar %1 de espaco de disco.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCorePrivate</name>
@@ -1593,16 +1682,12 @@ De certeza que deseja continuar?</translation>
<translation>A criar Ferramenta de Manutenção</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Instalação concluída!</translation>
+ <source>Installation finished!</source>
+ <translation>Instalação concluída!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Instalação cancelada!</translation>
+ <source>Installation aborted!</source>
+ <translation>Instalação cancelada!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1613,16 +1698,12 @@ Instalação cancelada!</translation>
<translation>A remover componentes deselecionados...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Atualização concluída!</translation>
+ <source>Update finished!</source>
+ <translation>Atualização concluída!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Atualização cancelada!</translation>
+ <source>Update aborted!</source>
+ <translation>Atualização cancelada!</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1658,17 +1739,15 @@ Atualização cancelada!</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation>A geração offline foi concluída com sucesso.</translation>
+ <translation>A geração &apos;offline&apos; foi concluída com sucesso.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation>A geração offline foi cancelada!</translation>
+ <translation>A geração &apos;offline&apos; foi cancelada!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-A instalar o componente %1</translation>
+ <source>Installing component %1</source>
+ <translation>A instalar o componente %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1715,10 +1794,6 @@ A instalar o componente %1</translation>
<translation>Não é possível recuperar metadados: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Não é possível adicionar informações de fontes de atualização temporária.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Não é possível encontrar informações de fonte de atualização.</translation>
</message>
@@ -1726,6 +1801,50 @@ A instalar o componente %1</translation>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>Ciclo de inter-dependência entre os componentes &quot;%1&quot; e &quot;%2&quot; detectados.</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>A preparar para descompactar componentes...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>Concluídas %1 de %2 operações.</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>A descompactar componentes...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>Revertidos %1 de %2 operações.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>As operações foram revertidas.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>Instalados %1 de %2 componentes.</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>Todos os componentes foram instalados.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>Carregando scripts de componentes...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>O &apos;alias&apos; declara um nome em conflito com um componente pré-existente &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>&apos;Alias&apos; dos componentes não resolvidos.</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>Foi detetado um ciclo de dependência entre os alias &quot;%1&quot; e &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -1762,7 +1881,7 @@ A instalar o componente %1</translation>
<translation>Pergunta %1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Configurações</translation>
</message>
<message>
@@ -1783,11 +1902,11 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>%1 - Configuração</translation>
+ <source>Welcome</source>
+ <translation>Bem-vindo</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Bem-vindo ao Assistente de Configuração %1.</translation>
</message>
<message>
@@ -1815,10 +1934,6 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Nenhuma atualização disponível.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Apenas gestãoo de pacotes locais disponível.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Sair</translation>
</message>
@@ -1858,62 +1973,38 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>Def&amp;eito</translation>
+ <source>Default</source>
+ <translation>Defeito</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>Selecione os componentes por defeito na vista de árvore.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Reverter</translation>
+ <source>Reset</source>
+ <translation>Reverter</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>Reverter todos os componentes para o seu estado original na visualização em árvore.</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>&amp;Selecionar Todos</translation>
+ <source>Select All</source>
+ <translation>Selecionar Todos</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>Selecione todos os componentes na visualização em árvore.</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Desmarcar Todos</translation>
+ <source>Deselect All</source>
+ <translation>Desmarcar Todos</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>Desselecione todos os componentes na visualização em árvore.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Procurar ficheiros QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>Selecione ficheiro &quot;Qt Board Support Package&quot; para instalar conteúdo adicional que não está disponível nos repositórios online.</translation>
</message>
@@ -1946,13 +2037,37 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Por favor, selecione os componentes que você deseja desinstalar.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Selecione componentes para os instalar. Deselecione componentes instalados para desinstalá-los. Os componentes previamente instalados não serão atualizados.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Selecione componentes para os instalar. Deselecione componentes instalados para desinstalá-los.&lt;br&gt;Os componentes previamente instalados não serão atualizados.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>Os componentes obrigatórios precisam ser atualizados antes de selecionar outros componentes para atualizar.</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>Pesquisa</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Selecionar ficheiros do tipo &amp;QBSP</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>Selecione</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Criar um Instalador &apos;Offline&apos;</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>Invés de instalar, criar um instalador &apos;Offline&apos; a partir dos componentes selecionados.</translation>
+ </message>
</context>
<context>
<name>QInstaller::TargetDirectoryPage</name>
@@ -2004,7 +2119,7 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Pronto para Desinstalar</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>O assistente de configuração está pronto para remover %1 do seu computador.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;O diretório do programa %2 será excluído completamente&lt;/font&gt;, incluindo todo o conteúdo nesse diretório!</translation>
</message>
<message>
@@ -2016,7 +2131,7 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Pronto para Atualizar Pacotes</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>O assistente de configuração está pronto para iniciar a atualização da sua instalação.</translation>
</message>
<message>
@@ -2028,13 +2143,25 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Pronto para Instalar</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>O assistente de configuração está pronto para iniciar a instalação de %1.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>Pronto para atualizar</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Criar um Instalador &apos;Offline&apos;</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>Pronto para criar um Instalador &apos;Offline&apos;</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>O assistente de configuração está pronto para criar um instalador offline para os componentes selecionados.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PerformInstallationPage</name>
@@ -2068,17 +2195,29 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
</message>
<message>
<source>Updating</source>
- <translation>>A atualizar</translation>
+ <translation>&gt;A atualizar</translation>
</message>
<message>
<source>Uninstalling</source>
<translation>A desinstalar</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>Criar um Instalador &apos;Offline&apos;</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>A criar um Instalador &apos;Offline&apos; para %1</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>A criar um Instalador &apos;Offline&apos;</translation>
+ </message>
</context>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>A concluir o Assistente %1</translation>
</message>
<message>
@@ -2086,7 +2225,7 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Concluído</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Clique em %1 para fechar o Assistente %2.</translation>
</message>
<message>
@@ -2098,14 +2237,14 @@ Por favor, copie o instalador para uma unidade de disco local</translation>
<translation>Executar %1 agora.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Ocorreu um erro no assistente %1.</translation>
</message>
</context>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>A concluir o Assistente de Configuração %1</translation>
</message>
</context>
@@ -2229,8 +2368,8 @@ Em alternativa, pode aceitar a alteração de permissões de acesso caso seja so
<translation>Não é possível abrir o ficheiro de configurações %1 para leitura: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>Selecionar categorias</translation>
+ <source>Categories</source>
+ <translation>Categorias</translation>
</message>
</context>
<context>
@@ -2421,6 +2560,10 @@ Em alternativa, pode aceitar a alteração de permissões de acesso caso seja so
<source>Try again</source>
<translation>Tente novamente</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>Não é possível fazer o descarregamento de %1. Não é possível criar o diretório &quot;%2&quot;</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -2692,10 +2835,6 @@ Em alternativa, pode aceitar a alteração de permissões de acesso caso seja so
<translation>Não é possível ler &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Ocorreu um erro a análisar %1 em %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Não é esperado este elemento raiz %1. Deveria ser &apos;Updates&apos;.</translation>
</message>
@@ -2738,8 +2877,8 @@ Em alternativa, pode aceitar a alteração de permissões de acesso caso seja so
<translation>Erro</translation>
</message>
<message>
- <source>Component Information</source>
- <translation>Informação do componente</translation>
+ <source>Information</source>
+ <translation>Informação</translation>
</message>
</context>
<context>
@@ -2748,6 +2887,22 @@ Em alternativa, pode aceitar a alteração de permissões de acesso caso seja so
<source>Extracting &quot;%1&quot;</source>
<translation>A descomprimir &quot;%1&quot;</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>O ficheiro &quot;%1&quot; não é suportado. Não está registado um programa para a extensão &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Não é possível abrir o ficheiro comprimido &quot;%1&quot; para leitura: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro a obter o conteudo do ficheiro comprimido &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>A remover ficheiros descomprimidos de &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2767,20 +2922,179 @@ Em alternativa, pode aceitar a alteração de permissões de acesso caso seja so
<translation>Não é possível abrir o ficheiro comprimido &quot;%1&quot; para leitura: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation>Ocorreu um erro a obter o conteudo do ficheiro comprimido &quot;%1&quot;: %2</translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro ao descomprimir o ficheiro comprimido &quot;%1&quot;: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation>Ocorreu um erro ao preparar para o ficheiro &quot;%1&quot;</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Não é possível abrir o ficheiro comprimido &quot;%1&quot; para leitura.</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation>A descompressão do ficheiro comprimido &quot;%1&quot; foi cancelada</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>Não é possível abrir o cabeçalho de entrada &quot;%1&quot; para leitura.</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Ocorreu um erro ao descomprimir o ficheiro comprimido &quot;%1&quot;: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Ocorreu um erro a escrever entrada &quot;%1&quot; para disco: %2.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Não é possível abrir o ficheiro comprimido &quot;%1&quot; para leitura</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>Não é possível abrir o cabeçalho de entrada &quot;%1&quot; para leitura.</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Ocorreu um erro a escrever entrada &quot;%1&quot; para disco: %2.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot; para escrita: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot; para leitura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro a escrever o cabeçalho de entrada &quot;%1&quot;: %2.</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>Componentes desselecionados:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>Componentes substituídos por &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>Irão ser removidos os seguintes componentes virtuais sem dependências:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>As dependências de &quot;%1&quot; foram removidas:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>As autodependências de &quot;%1&quot; foram removidas:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>Acerca do instalador %1 </translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>Acerca da ferramenta de manutenção %1 </translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>Não é possível inicializar o cache com caminho vazio.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>Não é possível criar o diretório &quot;%1&quot; para cache.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>Não é possível inicializar o cache: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>Não é possível limpar o cache invalidado.</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>Não é possível remover o arquivo de manifesto: % 1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>Erro ao limpar o cache: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>Não é possível recuperar itens do cache invalidado.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>Não é possível recuperar o item do cache invalidado.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>Não é possível registrar o item no cache invalidado.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>Não é possível registrar item nulo.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>Não é possível registar um item inválido com a soma de verificação % 1</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>Não é possível registrar o item com a soma de verificação %1. Já existe um item com a mesma soma de verificação no cache.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>Erro ao copiar o item para o caminho &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>Não é possível remover o item do cache invalidado.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>Não é possível remover o item especificado pela soma de verificação %1: esse item não existe.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>Erro ao remover o diretório &quot;%1&quot;: %2
+</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>Erro ao invalidar o cache: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>Não é possível abrir o arquivo de manifesto: % 1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>Não é possível gravar o conteúdo do arquivo de manifesto: % 1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>Não é possível sincronizar o cache invalidado.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>Foi selecionado um modo de registo desconhecido.</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>Cache limpo com sucesso!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_pt_BR.ts b/src/sdk/translations/ifw_pt_BR.ts
index ac7d05821..bae3a695c 100644
--- a/src/sdk/translations/ifw_pt_BR.ts
+++ b/src/sdk/translations/ifw_pt_BR.ts
@@ -210,6 +210,30 @@
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>URL do servidor que contém um repositório válido.</translation>
+ </message>
+ <message>
+ <source>Local cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -225,31 +249,31 @@
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>Erro a iniciar o binário do instalador como atualizador.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>Erro a iniciar o binário do instalador como gestor pacotes.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>Erro a iniciar o binário do instalador em modo desinstalador.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositórios para a opção &apos;Adicionar Repositório&apos; está vazia.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositórios para a opção &apos;Adicionar Repositório Temporário&apos; está vazia.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositórios para a opção &apos;Adicionar Repositório Temporário&apos; está vazia.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositórios para a opção &apos;Instalar Repositório Comprimido&apos; está vazia.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -257,18 +281,26 @@
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>Falta argumentos para opção %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>Valor de butão %1 não é válido.</translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>Argumentos para %1 não são corretos.</translation>
</message>
<message>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
+ <translation>Por favor, verifique que o usuário tem direitos de leitura do arquivo &quot;%1&quot; ou tente correr %2 com um conta de administrador.</translation>
+ </message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>Valor inválido para &apos;max-concurrent-operations&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -372,7 +404,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Não é possível copiar o arquivo &quot;%1&quot; para &quot;%2&quot;.</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -380,6 +412,10 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
+ <translation>Conteúdo inválido em &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -442,18 +478,6 @@
<translation>Componentes não podem ter filhos no modo de atualização.</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Não é possível abrir o arquivo da interface do usuário solicitado &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Não é possível carregar o arquivo da interface do usuário solicitado &quot;%1&quot;:%2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Não é possível abrir o arquivo de licença solicitado &quot;%1&quot;: %2</translation>
- </message>
- <message>
<source>Error</source>
<translation>Erro</translation>
</message>
@@ -471,7 +495,31 @@
</message>
<message>
<source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></translation>
+ <translation>Ocorreu um erro a carregar o componente selecionado. Este componente não pode ser instalado.</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Não é possível abrir o arquivo da interface do usuário solicitado &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Não é possível carregar o arquivo da interface do usuário solicitado &quot;%1&quot;:%2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Não é possível abrir o arquivo de licença solicitado &quot;%1&quot;: %2
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -532,12 +580,8 @@
<translation>Não é possível salvar a saída de &quot;%1&quot; em uma chave de instalação vazia.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>O arquivo &quot;%1&quot; não existe ou não é um binário executável.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>A execução de &quot;%1&quot; resultou em uma falha.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>Falha a executar o comando: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -636,11 +680,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Não é possível criar o caminho &quot;%1&quot;. </translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Não é possível remover o </translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -676,7 +720,11 @@
</message>
<message>
<source>Cannot create archive &quot;%1&quot;: %2</source>
- <translation type="unfinished">Não é possível criar o arquivo &quot;%1&quot;: %2</translation>
+ <translation>Não é possível criar o arquivo &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>O arquivo &quot;%1&quot; não é suportado: Não tem programa registado para a extenção &quot;%2&quot;.</translation>
</message>
</context>
<context>
@@ -744,11 +792,11 @@ Erro ao carregar %2</translation>
</message>
<message>
<source>%1 of %2</source>
- <translation type="unfinished">%1 de %2</translation>
+ <translation>%1 de %2</translation>
</message>
<message>
<source>%1 downloaded.</source>
- <translation type="unfinished">%1 baixado.</translation>
+ <translation>%1 baixado.</translation>
</message>
<message numerus="yes">
<source>%n day(s), </source>
@@ -788,10 +836,14 @@ Erro ao carregar %2</translation>
</message>
<message>
<source>Archive: </source>
- <translation type="unfinished"></translation>
+ <translation>Arquivo comprimido:</translation>
</message>
<message>
<source>Total: </source>
+ <translation>Total:</translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -974,6 +1026,18 @@ Erro ao carregar %2</translation>
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Não foi possível encontrar a dependência ausente &quot;%1&quot; para &quot;%2&quot;.</translation>
</message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::InstallIconsOperation</name>
@@ -1003,7 +1067,7 @@ Erro ao carregar %2</translation>
</message>
<message>
<source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Não é possível preparar o backup do arquivo &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -1074,11 +1138,11 @@ Erro ao carregar %2</translation>
</message>
<message>
<source>Internal code: %1</source>
- <translation type="unfinished"></translation>
+ <translation>Código interno: %1</translation>
</message>
<message>
<source>Not enough memory</source>
- <translation type="unfinished"></translation>
+ <translation>Não há memória suficiente.</translation>
</message>
</context>
<context>
@@ -1133,10 +1197,6 @@ Erro ao carregar %2</translation>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Não é possível gravar o arquivo de licença &quot;%1&quot;.</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>Nenhum arquivo de licença foi encontrado para ser excluído.</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
@@ -1160,10 +1220,6 @@ Erro ao carregar %2</translation>
<translation>Faltando o mecanismo principal do gerenciador de pacotes.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Preparando o download de metadados...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Descompactando repositórios compactados. Isso pode demorar um pouco...</translation>
</message>
@@ -1188,14 +1244,6 @@ Erro ao carregar %2</translation>
<translation>Incompatibilidade detectada na soma de verificação para &quot;%1&quot;.</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Recuperando metadados do repositório remoto...%1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Recuperando metadados do repositório remoto... </translation>
- </message>
- <message>
<source>Failure to fetch repositories.</source>
<translation>Falha ao buscar repositórios.</translation>
</message>
@@ -1215,6 +1263,45 @@ Erro ao carregar %2</translation>
<source>Metadata download canceled.</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Não é possível abrir o arquivo &quot;%1&quot; para gravação: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Recuperando informações de repositórios remotos...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Recuperando metadados do repositório remoto...</translation>
+ </message>
</context>
<context>
<name>QInstaller::FileTaskObserver</name>
@@ -1274,10 +1361,8 @@ Erro ao carregar %2</translation>
<translation>Erro ao gravar a Ferramenta de Manutenção</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Baixando pacotes...</translation>
+ <source>Downloading packages...</source>
+ <translation>Baixando pacotes...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1375,7 +1460,7 @@ Você quer continuar?</translation>
</message>
<message>
<source>Application running in Uninstaller mode.</source>
- <translation>Aplicação em execução no modo Desinstalador.</translation>
+ <translation>Aplicação em execução no modo desinstalador.</translation>
</message>
<message>
<source>There is an important update available, please run the updater first.</source>
@@ -1386,36 +1471,23 @@ Você quer continuar?</translation>
<translation>Não é possível resolver todas as dependências.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Componentes prestes a serem removidos.</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
+ <source>Component %1 already installed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
+ <source>Cannot install %1. Component is virtual.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Running processes found.</source>
+ <source>Cannot install %1. Component not found.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1439,10 +1511,6 @@ Você quer continuar?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation type="unfinished"></translation>
</message>
@@ -1463,16 +1531,39 @@ Você quer continuar?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
+ <source>Components about to be removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1591,16 +1682,12 @@ Você quer continuar?</translation>
<translation>Criando Ferramenta de Manutenção</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Instalação finalizada!</translation>
+ <source>Installation finished!</source>
+ <translation>Instalação finalizada!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Instalação cancelada!</translation>
+ <source>Installation aborted!</source>
+ <translation>Instalação cancelada!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1611,16 +1698,12 @@ Instalação cancelada!</translation>
<translation>Removendo componentes não selecionados...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Atualização finalizada!</translation>
+ <source>Update finished!</source>
+ <translation>Atualização finalizada!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Atualização cancelada!</translation>
+ <source>Update aborted!</source>
+ <translation>Atualização cancelada!</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
@@ -1655,10 +1738,8 @@ Atualização cancelada!</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Instalando o componente %1</translation>
+ <source>Installing component %1</source>
+ <translation>Instalando o componente %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1691,10 +1772,6 @@ Instalando o componente %1</translation>
<translation>Não é possível recuperar metadados: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Não é possível adicionar informações de fontes de atualização temporária.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Não é possível encontrar informações de fonte de atualização.</translation>
</message>
@@ -1723,6 +1800,50 @@ Instalando o componente %1</translation>
%1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -1755,7 +1876,7 @@ Instalando o componente %1</translation>
<translation>%1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Configurações</translation>
</message>
<message>
@@ -1780,11 +1901,11 @@ Por favor, copie o instalador para uma unidade local</translation>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>%1 - Configuração</translation>
+ <source>Welcome</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Bem-vindo ao Assistente de Configuração %1.</translation>
</message>
<message>
@@ -1812,10 +1933,6 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation>Nenhuma atualização disponível.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Apenas gerenciamento de pacotes locais disponível.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>Sair</translation>
</message>
@@ -1855,42 +1972,38 @@ Por favor, copie o instalador para uma unidade local</translation>
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>Def&amp;ault</translation>
+ <source>Default</source>
+ <translation>Default</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Resetar</translation>
+ <source>Reset</source>
+ <translation>Resetar</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>&amp;Selecionar Todos</translation>
+ <source>Select All</source>
+ <translation>Selecionar Todos</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Desmarcar Todos</translation>
+ <source>Deselect All</source>
+ <translation>Desmarcar Todos</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Procurar arquivos QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation type="unfinished"></translation>
</message>
@@ -1919,37 +2032,41 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation>Por favor, selecione os componentes que você deseja desinstalar.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Selecione os componentes para instalar. Desmarque os componentes instalados para desinstalá-los. Quaisquer componentes já instalados não serão atualizados.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Selecione os componentes para instalar. Desmarque os componentes instalados para desinstalá-los.&lt;br&gt;Quaisquer componentes já instalados não serão atualizados.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
+ <source>Filter the enabled repository categories</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
+ <source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
+ <source>Create Offline Installer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
+ <source>Create offline installer from selected components, instead of installing now.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
+ <source>Browse &amp;QBSP files</source>
+ <translation>&amp;Procurar arquivos QBSP</translation>
+ </message>
+ <message>
+ <source>Select</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Erro</translation>
+ </message>
</context>
<context>
<name>QInstaller::TargetDirectoryPage</name>
@@ -2001,7 +2118,7 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation>Pronto para Desinstalar</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>O assistente de configuração está pronto para remover %1 do seu computador.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;O diretório do programa %2 será excluído completamente&lt;/font&gt;, incluindo todo o conteúdo nesse diretório!</translation>
</message>
<message>
@@ -2013,7 +2130,7 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation>Pronto para Atualizar Pacotes</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>O assistente de configuração está pronto para começar a atualizar sua instalação.</translation>
</message>
<message>
@@ -2025,13 +2142,25 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation>Pronto para Instalar</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>O assistente de configuração está pronto para começar a instalar o %1 no seu computador.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::PerformInstallationPage</name>
@@ -2071,11 +2200,23 @@ Por favor, copie o instalador para uma unidade local</translation>
<source>Uninstalling</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Concluindo o Assistente %1</translation>
</message>
<message>
@@ -2083,7 +2224,7 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Clique em %1 para sair do Assistente %2.</translation>
</message>
<message>
@@ -2095,14 +2236,14 @@ Por favor, copie o instalador para uma unidade local</translation>
<translation>Executar %1 agora.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>O Assistente %1 falhou.</translation>
</message>
</context>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Concluindo o Assistente de Configuração %1</translation>
</message>
</context>
@@ -2153,7 +2294,10 @@ como um usuário com os privilégios apropriados e, em seguida, clicando em OK.<
Please start the setup program as a user with the appropriate rights,
or accept the elevation of access rights if being asked.</source>
- <translation type="unfinished"></translation>
+ <translation>Não é possível obter a autorização necessária para continuar a instalação.
+
+ Inicie o instalador como usuário com os privilégios apropriados,
+ ou aceite a elevação dos direitos acesso, se forem pedidos.</translation>
</message>
</context>
<context>
@@ -2167,11 +2311,11 @@ or accept the elevation of access rights if being asked.</source>
<name>QInstaller::ReplaceOperation</name>
<message>
<source>Current search argument calling &quot;%1&quot; with empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>A pesquisa atual &quot;%1&quot; com argumento vazio não é suportado.</translation>
</message>
<message>
<source>Current mode argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use string or regex.</source>
- <translation type="unfinished"></translation>
+ <translation>A pesquisa atual &quot;%1&quot; com os argumentos &quot;%2&quot; não são suportados. Use &quot;string&quot; ou &quot;regex&quot;.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2223,8 +2367,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>Não é possível abrir o arquivo de configurações %1 para leitura: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>Categorias</translation>
</message>
</context>
<context>
@@ -2235,7 +2379,7 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Current method argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use set, remove, add_array_value, or remove_array_value.</source>
- <translation type="unfinished"></translation>
+ <translation>O método atual &quot;%1&quot; com argumentos &quot;%2&quot; não são suportados. Use &quot;set&quot;, &quot;remove&quot;, &quot;add_array_value&quot;, ou &quot;remove_array_value&quot;</translation>
</message>
</context>
<context>
@@ -2415,6 +2559,10 @@ or accept the elevation of access rights if being asked.</source>
<source>Try again</source>
<translation>Tente novamente</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -2686,10 +2834,6 @@ or accept the elevation of access rights if being asked.</source>
<translation>Não é possível ler &quot;%1&quot;</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Erro de análise em %1 em %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Elemento raiz %1 inesperado. Deveria ser &apos;Updates&apos;.</translation>
</message>
@@ -2718,22 +2862,22 @@ or accept the elevation of access rights if being asked.</source>
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>Não é possível iniciar o instalador</translation>
</message>
</context>
<context>
<name>QInstaller::ComponentSelectionPagePrivate</name>
<message>
<source>Filter</source>
- <translation type="unfinished"></translation>
+ <translation>Filtro</translation>
</message>
<message>
<source>Error</source>
<translation>Erro</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Informação</translation>
</message>
</context>
<context>
@@ -2742,6 +2886,22 @@ or accept the elevation of access rights if being asked.</source>
<source>Extracting &quot;%1&quot;</source>
<translation>Extraindo &quot;%1&quot;</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>O arquivo comprimido &quot;%1&quot; não é suportado. Não existe um programa registado para este extensão de nome de arquivo.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Não é possível abrir o arquivo &quot;%1&quot; para leitura: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro ao ler o conteúdo do arquivo comprimido &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>A remover arquivos extraidos de &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2761,20 +2921,178 @@ or accept the elevation of access rights if being asked.</source>
<translation type="unfinished">Não é possível abrir o arquivo &quot;%1&quot; para leitura: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation type="unfinished">Erro ao extrair o arquivo &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
<translation type="unfinished"></translation>
</message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
+ <source>Cannot open archive for reading: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation type="unfinished">Erro ao extrair o arquivo &quot;%1&quot;: %2</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation type="unfinished">Não é possível abrir o arquivo &quot;%1&quot; para gravação: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation type="unfinished">Não é possível abrir o arquivo &quot;%1&quot; para leitura: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation type="unfinished"></translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_ru.ts b/src/sdk/translations/ifw_ru.ts
index 407b6bf38..33d4c4c37 100644
--- a/src/sdk/translations/ifw_ru.ts
+++ b/src/sdk/translations/ifw_ru.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>Не удалось найти компонент «%1», необходимый для «%2».</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>Выявлено невозможное разрешение зависимостей. Принудительная установка компонента &quot;%1&quot; будет удалена, потому что зависимый &quot;%2&quot; помечен для удаления по причине: &quot;%3&quot;.</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>Выбран компонент под именем &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>Замечено повторение, компонент с именем &quot;%1&quot; уже выбран.</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -310,6 +322,10 @@
<source>Cannot download %1. Cannot create file &quot;%2&quot;: %3</source>
<translation>Невозможно загрузить «%1». Не удалось создать «%2»: %3</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>Невозможно загрузить %1. Невозможно создать каталог для &quot;%2&quot;</translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -494,10 +510,6 @@
<translation>Невозможно прочитать «%1»</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>Ошибка разбора XML в %1 в %2, %3: %4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>Непредвиденный корневой элемент %1, требуется «Updates».</translation>
</message>
@@ -749,6 +761,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>Недопустимые данные в «%1».</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>Это может быть решено перезапуском приложения после очистки кэша:</translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -769,24 +785,36 @@
<translation>Информация об обновлении: </translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>Не удалось открыть запрошенный UI файл «%1»: %2</translation>
+ <source>Error: Operation %1 does not exist.</source>
+ <translation>Ошибка: операция %1 не существует.</translation>
</message>
<message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>Не удалось загрузить запрошенный UI файл «%1»: %2</translation>
+ <source>There was an error loading the selected component. This component cannot be installed.</source>
+ <translation>Возникла ошибка при загрузке выбранного компонента. Установить его не получится.</translation>
</message>
<message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Не удалось открыть запрошенный файл лицензии «%1»: %2</translation>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Не удалось открыть запрошенный UI файл «%1»: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
<message>
- <source>Error: Operation %1 does not exist.</source>
- <translation>Ошибка: операция %1 не существует.</translation>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Не удалось загрузить запрошенный UI файл «%1»: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
<message>
- <source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation>Возникла ошибка при загрузке выбранного компонента. Установить его не получится.</translation>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>Не удалось открыть запрошенный файл лицензии «%1»: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -835,42 +863,38 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Def&amp;ault</source>
- <translation>&amp;По умолчанию</translation>
+ <source>Default</source>
+ <translation>По умолчанию</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>Выберите компоненты по умолчанию в древовидном представлении.</translation>
</message>
<message>
- <source>&amp;Reset</source>
- <translation>&amp;Отменить</translation>
+ <source>Reset</source>
+ <translation>Отменить</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>Сбросьте все компоненты в исходное состояние выбора в древовидном представлении.</translation>
</message>
<message>
- <source>&amp;Select All</source>
- <translation>&amp;Выбрать всё</translation>
+ <source>Select All</source>
+ <translation>Выбрать всё</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>Выберите все компоненты в древовидном представлении.</translation>
</message>
<message>
- <source>&amp;Deselect All</source>
- <translation>&amp;Отменить выделенное</translation>
+ <source>Deselect All</source>
+ <translation>Отменить выделенное</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>Отмените выбор всех компонентов в древовидном представлении.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Обзор файлов QBSP</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>Выберите файл инструментальных средств для разработки Qt Board Support Package, чтобы установить дополнительное содержимое, которое недоступно непосредственно из сетевых хранилищ.</translation>
</message>
@@ -895,8 +919,8 @@
<translation>Пожалуйста, выберите компоненты, которые вы хотите удалить.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
- <translation>Выберите компоненты для установки. Для удаления уже установленных компонентов снимите отметки выбора. Уже установленные компоненты не будут обновлены.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
+ <translation>Выберите компоненты для установки. Для удаления уже установленных компонентов снимите отметки выбора.&lt;br&gt;Уже установленные компоненты не будут обновлены.</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
@@ -907,28 +931,32 @@
<translation>Открытие файла</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
+ <source>Filter the enabled repository categories</source>
+ <translation>Отфильтруйте категории включенного хранилища по выбору.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
+ <source>Search</source>
+ <translation>Поиск</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Посмотреть &amp;QBSP файлы</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
+ <source>Select</source>
+ <translation>Выбрать</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation>Отфильтруйте категории включенного хранилища по выбору.</translation>
+ <source>Error</source>
+ <translation>Ошибка</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Создать Автономный Установщик</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>Создать автономный установщик из выбранных компонентов вместо установки сейчас.</translation>
</message>
</context>
<context>
@@ -942,8 +970,8 @@
<translation>Ошибка</translation>
</message>
<message>
- <source>Component Information</source>
- <translation>Сведения о компонентах</translation>
+ <source>Information</source>
+ <translation>Информация</translation>
</message>
</context>
<context>
@@ -961,12 +989,8 @@
<translation>Невозможно сохранить вывод «%1» в пустое значение ключа установщика.</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>Файл «%1» не существует или не является исполняемым.</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>Запуск «%1» завершился крахом.</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>Не удалось запустить команду: &quot;%1&quot;: %2</translation>
</message>
</context>
<context>
@@ -1107,6 +1131,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>Не удалось создать архив «%1»: %2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Неподдерживаемый архив &quot;%1&quot;: нет зарегестрированного обработчика для файла с расширением &quot;%2&quot;.</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1227,6 +1255,10 @@ Error while loading %2</source>
<source>Total: </source>
<translation>Всего: </translation>
</message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>Превышено количество (%1) повторов</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1301,6 +1333,22 @@ Error while loading %2</source>
<source>Extracting &quot;%1&quot;</source>
<translation>Извлечение «%1»</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Неподдерживаемый архив &quot;%1&quot;: нет зарегестрированного обработчика для файла с расширением &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>Не удалось открыть архив «%1» для чтения: %2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Ошибка при чтении содержимого архива &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Удаление файлов, извлеченных из &quot;%1&quot;</translation>
+ </message>
</context>
<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
@@ -1375,7 +1423,7 @@ Error while loading %2</source>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Завершение установки %1</translation>
</message>
<message>
@@ -1391,11 +1439,11 @@ Error while loading %2</source>
<translation>Запустить %1 сейчас.</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>Установка %1 не удалась.</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>Нажмите «%1» для выхода из мастера %2.</translation>
</message>
</context>
@@ -1436,15 +1484,19 @@ Error while loading %2</source>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>Не удалось создать каталог «%1»: %2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>Не удалось подготовиться для создания резервной копии файла &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>Установка - %1</translation>
+ <source>Welcome</source>
+ <translation>Добро пожаловать</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>Добро пожаловать в мастер установки %1.</translation>
</message>
<message>
@@ -1472,10 +1524,6 @@ Error while loading %2</source>
<translation>Нет доступных обновлений.</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation> Доступно только локальное управление пакетами.</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>&amp;Выйти</translation>
</message>
@@ -1523,10 +1571,6 @@ Error while loading %2</source>
<translation>В операции «%1» необходимый объект установщика пуст.</translation>
</message>
<message>
- <source>No license files found to delete.</source>
- <translation>Невозможно удалить файл лицензии: файл не найден.</translation>
- </message>
- <message>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>Не удалось записать файл лицензии «%1».</translation>
</message>
@@ -1553,10 +1597,6 @@ Error while loading %2</source>
<translation>Отсутствует менеджер пакетов.</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>Подготовка к загрузке метаданных...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Распаковка сжатых хранилищ. Это может занять некоторое время...</translation>
</message>
@@ -1577,14 +1617,6 @@ Error while loading %2</source>
<translation>Обнаружено несовпадение контрольной суммы у «%1».</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>Получение метаданных из внешнего хранилища... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Получение метаданных из внешнего хранилища... </translation>
- </message>
- <message>
<source>Failure to fetch repositories.</source>
<translation>Не удалось загрузить хранилища.</translation>
</message>
@@ -1608,6 +1640,46 @@ Error while loading %2</source>
<source>Metadata download canceled.</source>
<translation>Загрузка метаданных отменена.</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>Неподдерживаемый архив &quot;%1&quot;: нет зарегестрированного обработчика для файла с расширением &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>Получение информации о последнем обновлении</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>Обновление локального кэша с добавлением %n нового файла</numerusform>
+ <numerusform>Обновление локального кэша с добавлением %n новых файлов</numerusform>
+ <numerusform>Обновление локального кэша с добавлением %n новых файлов</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>Очистка кэш-директории и перезапуск приложения может исправить это.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Неизвестное исключение во время обновления кэша.</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>Невозможно открыть распакованный файл &quot;%1&quot; для чтения.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Невозможно открыть файл &quot;%1&quot; для записи: %2</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>Получение информации из внешнего хранилища...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>Получение метаданных из внешнего хранилища...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1616,10 +1688,8 @@ Error while loading %2</source>
<translation>Ошибка записи Maintenance Tool</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-Загрузка пакетов...</translation>
+ <source>Downloading packages...</source>
+ <translation>Загрузка пакетов...</translation>
</message>
<message>
<source>All downloads finished.</source>
@@ -1704,32 +1774,20 @@ Do you want to continue?</source>
<translation>Доступно важное исправление, сначала запустите программу обновления.</translation>
</message>
<message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>Не удалось установить компонент %1. Компонент устанавливается только как автоматическая зависимость для %2.
-</translation>
- </message>
- <message>
- <source>Component %1 already installed
-</source>
- <translation>Компонент %1 уже установлен
-</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>Не удалось установить компонент %1. Компонент устанавливается только как автоматическая зависимость для %2.</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>Не удалось установить %1. Компонент является виртуальным.
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>Компонент %1 уже установлен</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>Не удалось установить %1. Компонент не найден.
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>Не удалось установить %1. Компонент является виртуальным.</translation>
</message>
<message>
- <source>Running processes found.</source>
- <translation>Обнаружены запущенные процессы.</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>Не удалось установить %1. Компонент не найден.</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1776,29 +1834,19 @@ Do you want to continue?</source>
<translation>Не удалось разрешить все зависимости.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Удаляемые компоненты.</translation>
- </message>
- <message>
<source>User input is required but the output device is not associated with a terminal.</source>
<translation>Требуется ввод данных пользователем, но устройство вывода не связано с терминалом.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>Не удалось зарегистрировать компонент! Компонент с идентификатором %1 уже существует.</translation>
- </message>
- <message>
<source>Canceling the Installer</source>
<translation>Отмена программы установки</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
<translation>Не удалось установить компонент %1. Компонент не является проверяемым, и это означает, что необходимо выбрать один из подкомпонентов.</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation>Не удалось установить %1. Компонент является производным от виртуального компонента %2.</translation>
</message>
<message>
@@ -1810,10 +1858,6 @@ Do you want to continue?</source>
<translation>Недостаточно места на диске для сохранения всех выбранных компонентов. Доступно %1, а требуется минимум: %2.</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>Недостаточно места на диске для временных файлов. Доступно %1, а требуется минимум %2.</translation>
- </message>
- <message>
<source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
<translation>Приблизительный размер установочника %1 превысит поддерживаемый предел размера исполняемого файла %2. Возможно, приложение не сможет быть запущено. </translation>
</message>
@@ -1821,6 +1865,34 @@ Do you want to continue?</source>
<source>Invalid</source>
<translation>недопустимая версия</translation>
</message>
+ <message>
+ <source>Components about to be removed:</source>
+ <translation>Компонент практически удален:</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>Невозможно установить компонент %1. Произошла ошибка загрузки этого компонента, он был помечен нестабильным и не может быть выбран.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>Недостаточно места на диске для хранения временных файлов! %1 доступно, минимально необходимо %2. Вы можете выбрать другое место для временных файлов, изменив путь к локальному кэшу в настройках установщика.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Невозможно определить компоненты для удаления.</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>Невозможно выбрать псевдоним %1. Была проблема с загрузкой этого псевдонима, он был помечен нестабильным и не может быть выбран.</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>Невозможно выбрать %1. Псевдоним помечен как виртуальный и не может быть выбран вручную.</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>Созданный установщик займет %1 дискового пространства.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCorePrivate</name>
@@ -1873,16 +1945,12 @@ Do you want to continue?</source>
<translation>Создаётся локальное хранилище</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-Установка завершена!</translation>
+ <source>Installation finished!</source>
+ <translation>Установка завершена!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-Установка прервана!</translation>
+ <source>Installation aborted!</source>
+ <translation>Установка прервана!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1893,16 +1961,12 @@ Installation aborted!</source>
<translation>Удаление компонентов...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-Обновление завершено!</translation>
+ <source>Update finished!</source>
+ <translation>Обновление завершено!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-Обновление прервано!</translation>
+ <source>Update aborted!</source>
+ <translation>Обновление прервано!</translation>
</message>
<message>
<source>Unresolved dependencies</source>
@@ -1993,10 +2057,8 @@ Update aborted!</source>
<translation>Создание автономного экземпляра прервано!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-Установка компонента %1</translation>
+ <source>Installing component %1</source>
+ <translation>Установка компонента %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -2020,10 +2082,6 @@ Installing component %1</source>
<translation>Невозможно загрузить метаданные: %1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>Невозможно добавить информацию о временном сервере обновления.</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>Невозможно найти информацию об источниках обновления.</translation>
</message>
@@ -2069,6 +2127,50 @@ Installing component %1</source>
<translation>Ошибка в процессе установки:
%1</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>Подготовка к распаковке компонента...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>1 из %2 операции завершены</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>Распаковка компонентов...</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 из %2 были возвращены в предыдущее состояние.</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>Возврат в предыдущее состояние завершен.</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%1 из %2 компонентов установлены</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>Все компоненты установлены.</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>Загрузка скриптов компонента...</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>Псевдоним назван именем, которое конфликтует с существующим компонентом &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>Неразрешенные псевдонимы компонентов.</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>Цикличная зависимость между псевдонимами &quot;%1&quot; и &quot;%2&quot; замечена.</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2097,7 +2199,7 @@ Installing component %1</source>
<translation>Выйти из приложения обслуживания?</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Настройки</translation>
</message>
<message>
@@ -2172,6 +2274,18 @@ Please copy the installer to a local drive</source>
<source>Uninstalling</source>
<translation>Удаление</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>Создать Автономный Установщик.</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>Создание Автономного Установщика для %1</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>Создание Автономного Установщика</translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2215,7 +2329,7 @@ Please copy the installer to a local drive</source>
<translation>Всё готово к удалению</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>Программа установки готова начать удаление %1 с вашего компьютера. &lt;br&gt;&lt;font color=&quot;red&quot;&gt;Директория с программой %2 будет полностью удалена&lt;/font&gt;, включая содержимое этой директории!</translation>
</message>
<message>
@@ -2227,7 +2341,7 @@ Please copy the installer to a local drive</source>
<translation>Готов к обновлению пакетов</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>Программа установки готова к обновлению файлов.</translation>
</message>
<message>
@@ -2239,13 +2353,25 @@ Please copy the installer to a local drive</source>
<translation>Всё готово к установке</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>Программа установки готова начать установку %1 на ваш компьютер.</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>Всё готово к обновлению</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>Создать Автономный Установщик.</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>Готов к установке Автономного Установщика.</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>Вся необходимая информация доступна для создания автономного установщика для выбранных компонентов.</translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2302,7 +2428,7 @@ Please copy the installer to a local drive</source>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>Завершение %1 мастера установки</translation>
</message>
</context>
@@ -2525,6 +2651,14 @@ Please copy the installer to a local drive</source>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>Убедитесь, что текущий пользователь имеет разрешение на чтение файла «%1», или попробуйте запустить %2 от имени администратора.</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>Неверное значение for &apos;max-concurrent-operations&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>Пустое значение параметра &apos;cache-path&apos;.</translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2571,8 +2705,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>Невозможно открыть файл настроек %1 на чтение: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>Выберите категории пакетов</translation>
+ <source>Categories</source>
+ <translation>Выберите категорию</translation>
</message>
</context>
<context>
@@ -2709,6 +2843,30 @@ or accept the elevation of access rights if being asked.</source>
<source>The server&apos;s URL that contains a valid repository.</source>
<translation>Адреса серверов, которые содержат рабочие хранилища.</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>Локальный кэш</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>Мета информация с удаленных репозиториев кэшируется на диске для ускорения загрузочного процесса. Вы можете выбрать другую папку для хранения кэша или удалить содержимое существующего кэша.</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>Путь для кэша:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>Удаление содержимого существующей кэш-директории.</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>Очистить кэш</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>Очистка кэша...</translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2779,20 +2937,178 @@ or accept the elevation of access rights if being asked.</source>
<translation>Не удалось открыть архив «%1» для чтения: %2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation>Ошибка при чтении содержимого архива &quot;%1&quot;: %2</translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Ошибка извлечения из архива «%1»: %2</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation>Невозможно подготовить файл &quot;%1&quot;</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Не удалось открыть архив для чтения: %1</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation>Распаковка для архива &quot;%1&quot; отменена.</translation>
+ <source>Cannot read entry header: %1</source>
+ <translation>Не удалось прочесть заголовок записи: %1 </translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Ошибка извлечения из архива «%1»: %2</translation>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Не удалось записать &quot;%1&quot; на диск: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>Не удалось открыть архив для чтения: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>Не удалось прочесть заголовок записи: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>Не удалось записать &quot;%1&quot; на диск: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>Не удалось открыть файл &quot;%1&quot; для записи: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>Не удалось открыть файл «%1» для чтения: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>Не удалось записать заголовок записи для &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>Выбранные компоненты:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>Компоненты заменены на &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>Удаление виртуальных компонентов без существующих зависимостей:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>Компоненты зависимостей &quot;%1&quot; удалены:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>Компоненты автозависимостей &quot;%1&quot; удалены:</translation>
+ </message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
+ <message>
+ <source>About %1 installer</source>
+ <translation>Об %1 установщике</translation>
+ </message>
+ <message>
+ <source>About %1 Maintenance Tool</source>
+ <translation>Об %1 Maintenance Tool</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>Невозможно инициализировать кэш с пустым путем.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>Невозможно создать директорию &quot;%1&quot; для кэша.</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>Невозможно инициализировать кэш: %1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>Невозможно очистить недействительный кэш. </translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>Невозможно удалить файл-манифест: %1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>Ошибка во время очистки кэша: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>Невозможно получить файлы из недействительного кэша.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>Невозможно получить файл из недействительного кэша.</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>Невозможно зарегестрировать файл для недействительного кэша.</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>Невозможно зарегестрировать недействительный файл.</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation></translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>Невозможно зарегестрировать файл с контрольной суммой %1. Файл с идентичной контрольной суммой уже существует в кэше.</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>Ошибка при копировании файла в &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>Невозможно удалить файл из недействительного кэша.</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>Невозможно удалить файл с контрольной суммой %1: файла не существует.</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>Ошибка при удалении директории &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>Ошибка при аннулировании кэша: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>Невозможно открыть файл-манифест: %1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>Невозможно записать содержимое для файл-манифеста: %1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>Не удается синхронизировать недействительный кеш.</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>Выбран неизвестный режим регистра.</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>Кэш успешно очищен!</translation>
</message>
</context>
</TS>
diff --git a/src/sdk/translations/ifw_zh_CN.ts b/src/sdk/translations/ifw_zh_CN.ts
index 8e411b1f5..7246914a1 100644
--- a/src/sdk/translations/ifw_zh_CN.ts
+++ b/src/sdk/translations/ifw_zh_CN.ts
@@ -136,6 +136,18 @@
<source>Cannot find missing dependency &quot;%1&quot; for &quot;%2&quot;.</source>
<translation>找不到“%2”的缺失依赖项“%1”。</translation>
</message>
+ <message>
+ <source>Impossible dependency resolution detected. Forced install component &quot;%1&quot; would be uninstalled because its dependency &quot;%2&quot; is marked for uninstallation with reason: &quot;%3&quot;.</source>
+ <translation>检测到无法解决的依赖关系。强制安装组件:“%1”将会被移除,因为它的依赖“%2”被标记为移除,原因:“%3”。</translation>
+ </message>
+ <message>
+ <source>Components selected by alias &quot;%1&quot;:</source>
+ <translation>通过别名“%1”选中的组件:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component alias &quot;%1&quot; already added.</source>
+ <translation>检测到递归,组件别名“%1”已添加。</translation>
+ </message>
</context>
<context>
<name>Job</name>
@@ -217,7 +229,7 @@
</message>
<message>
<source>Download canceled.</source>
- <translation>下载已取消</translation>
+ <translation>下载已取消。</translation>
</message>
<message>
<source>%1 of %2</source>
@@ -225,7 +237,7 @@
</message>
<message>
<source>%1 downloaded.</source>
- <translation>%1 已下载</translation>
+ <translation>%1 已下载。</translation>
</message>
<message>
<source>(%1/sec)</source>
@@ -257,11 +269,11 @@
</message>
<message>
<source> - %1%2%3%4 remaining.</source>
- <translation>- 剩余 %1%2%3%4。</translation>
+ <translation> - 剩余 %1%2%3%4。</translation>
</message>
<message>
<source> - unknown time remaining.</source>
- <translation>- 剩余时间未知。</translation>
+ <translation> - 剩余时间未知。</translation>
</message>
</context>
<context>
@@ -302,6 +314,10 @@
<source>Try again</source>
<translation>重试</translation>
</message>
+ <message>
+ <source>Cannot download %1. Cannot create directory for &quot;%2&quot;</source>
+ <translation>无法下载%1。无法为“%2”创建目录。</translation>
+ </message>
</context>
<context>
<name>KDUpdater::LocalFileDownloader</name>
@@ -398,7 +414,7 @@
</message>
<message>
<source>The directory does not exist.</source>
- <translation>目录不存在!</translation>
+ <translation>目录不存在。</translation>
</message>
<message>
<source>Cannot recreate directory &quot;%1&quot;: %2</source>
@@ -484,10 +500,6 @@
<translation>无法读取“%1”</translation>
</message>
<message>
- <source>Parse error in %1 at %2, %3: %4</source>
- <translation>%1 中 %2、%3 的解析错误:%4</translation>
- </message>
- <message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
<translation>意外的根元素 %1,应为“Updates”。</translation>
</message>
@@ -739,6 +751,10 @@
<source>Invalid content in &quot;%1&quot;.</source>
<translation>“%1”中的内容无效。</translation>
</message>
+ <message>
+ <source>This may be solved by restarting the application after clearing the cache from:</source>
+ <translation>清空此处缓存之后重启应用程序也许可以解决问题:</translation>
+ </message>
</context>
<context>
<name>QInstaller::Component</name>
@@ -747,18 +763,6 @@
<translation>更新程序模式下组件不得包含子项。</translation>
</message>
<message>
- <source>Cannot open the requested UI file &quot;%1&quot;: %2</source>
- <translation>无法打开请求的 UI 文件“%1”:%2</translation>
- </message>
- <message>
- <source>Cannot load the requested UI file &quot;%1&quot;: %2</source>
- <translation>无法加载请求的 UI 文件“%1”:%2</translation>
- </message>
- <message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>无法打开请求的许可文件“%1”:%2</translation>
- </message>
- <message>
<source>Error</source>
<translation>错误</translation>
</message>
@@ -776,7 +780,31 @@
</message>
<message>
<source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></translation>
+ <translation>加载选中组件的过程中出现错误。这个组件不会被安装。</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>无法打开请求的 UI 文件“%1”:%2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot load the requested UI file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>无法加载请求的 UI 文件“%1”:%2.
+
+%3 &quot;%4&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot open the requested license file &quot;%1&quot;: %2.
+
+%3 &quot;%4&quot;</source>
+ <translation>无法打开请求的许可文件“%1”:%2.
+
+%3 &quot;%4&quot;</translation>
</message>
</context>
<context>
@@ -825,68 +853,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Def&amp;ault</source>
- <translation>默认(&amp;A)</translation>
+ <source>Default</source>
+ <translation>默认</translation>
</message>
<message>
<source>Select default components in the tree view.</source>
<translation>在树视图中选择默认组件。</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation>Alt+R</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>重置(&amp;R)</translation>
+ <source>Reset</source>
+ <translation>重置</translation>
</message>
<message>
<source>Reset all components to their original selection state in the tree view.</source>
<translation>在树视图中将所有组件重置为其原始选择状态。</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation>Alt+S</translation>
- </message>
- <message>
- <source>&amp;Select All</source>
- <translation>全选(&amp;S)</translation>
+ <source>Select All</source>
+ <translation>全选</translation>
</message>
<message>
<source>Select all components in the tree view.</source>
<translation>在树视图中选择所有组件。</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation>Alt+D</translation>
- </message>
- <message>
- <source>&amp;Deselect All</source>
- <translation>取消全选(&amp;D)</translation>
+ <source>Deselect All</source>
+ <translation>取消全选</translation>
</message>
<message>
<source>Deselect all components in the tree view.</source>
<translation>在树视图中删除所有组件。</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>浏览 QBSP 文件(&amp;B)</translation>
- </message>
- <message>
<source>Select a Qt Board Support Package file to install additional content that is not directly available from the online repositories.</source>
<translation>选择 Qt Board Support Package 文件以安装无法直接从在线存储库中获得的附加内容。</translation>
</message>
<message>
<source>Filter the enabled repository categories</source>
- <translation>过滤已启用的存储库类别以供选择。</translation>
+ <translation>过滤已启用的存储库类别</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -913,13 +917,37 @@
<translation>请选择要卸载的组件。</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
+ <source>Select the components to install. Deselect installed components to uninstall them.&lt;br&gt;Any components already installed will not be updated.</source>
<translation>选择要安装的组件。 取消选择已安装组件以卸载它们。 所有已安装的组件均不会更新。</translation>
</message>
<message>
<source>Mandatory components need to be updated first before you can select other components to update.</source>
<translation>必须先更新必备组件,然后才能选择其他组件进行更新。</translation>
</message>
+ <message>
+ <source>Search</source>
+ <translation>搜索</translation>
+ </message>
+ <message>
+ <source>Browse &amp;QBSP files</source>
+ <translation>浏览&amp;QBSP文件</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>选择</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>创建离线安装程序</translation>
+ </message>
+ <message>
+ <source>Create offline installer from selected components, instead of installing now.</source>
+ <translation>根据选中组件创建离线安装程序,而不是现在就安装。</translation>
+ </message>
</context>
<context>
<name>QInstaller::ConsumeOutputOperation</name>
@@ -936,12 +964,8 @@
<translation>无法将“%1”的输出保存为空安装程序密钥值。</translation>
</message>
<message>
- <source>File &quot;%1&quot; does not exist or is not an executable binary.</source>
- <translation>文件“%1”不存在或不是可执行的二进制文件。</translation>
- </message>
- <message>
- <source>Running &quot;%1&quot; resulted in a crash.</source>
- <translation>运行“%1”导致崩溃。</translation>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>运行命令“%1”失败:%2</translation>
</message>
</context>
<context>
@@ -1082,6 +1106,10 @@
<source>Cannot create archive &quot;%1&quot;: %2</source>
<translation>无法创建存档“%1”:%2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>不支持的存档“%1”:没有处理程序注册在文件后缀“%2”名下。</translation>
+ </message>
</context>
<context>
<name>QInstaller::CreateShortcutOperation</name>
@@ -1117,14 +1145,6 @@
<translation>下载错误</translation>
</message>
<message>
- <source>Hash verification while downloading failed. This is a temporary error, please retry.</source>
- <translation>下载时的哈希验证失败。 此错误为临时错误,请重试。</translation>
- </message>
- <message>
- <source>Cannot verify Hash</source>
- <translation>无法验证哈希</translation>
- </message>
- <message>
<source>Cannot download archive %1: %2</source>
<translation>无法下载存档 %1:%2</translation>
</message>
@@ -1152,7 +1172,7 @@ Error while loading %2</source>
</message>
<message>
<source>%1 downloaded.</source>
- <translation>%1 已下载</translation>
+ <translation>%1 已下载。</translation>
</message>
<message numerus="yes">
<source>%n day(s), </source>
@@ -1180,19 +1200,40 @@ Error while loading %2</source>
</message>
<message>
<source> - %1%2%3%4 remaining.</source>
- <translation>- 剩余 %1%2%3%4。</translation>
+ <translation> - 剩余 %1%2%3%4。</translation>
</message>
<message>
<source> - unknown time remaining.</source>
- <translation>- 剩余时间未知。</translation>
+ <translation> - 剩余时间未知。</translation>
</message>
<message>
<source>Archive: </source>
- <translation type="unfinished"></translation>
+ <translation>存档:</translation>
</message>
<message>
<source>Total: </source>
- <translation type="unfinished"></translation>
+ <translation>总计:</translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>超过重试次数(%1)</translation>
+ </message>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.
+
+Expected: %1
+Downloaded: %2</source>
+ <translation>下载时的哈希验证失败。 此错误为临时错误,请重试。
+预期的:%1
+已下载:%2</translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash
+Expected: %1
+Downloaded: %2</source>
+ <translation>无法验证哈希
+预期的:%1
+已下载:%2</translation>
</message>
</context>
<context>
@@ -1225,7 +1266,7 @@ Error while loading %2</source>
</message>
<message>
<source>Network error while downloading &apos;%1&apos;: %2.</source>
- <translation>下载“%1”时出现网络错误:%2</translation>
+ <translation>下载“%1”时出现网络错误:%2。</translation>
</message>
<message>
<source>Unknown network error while downloading &quot;%1&quot;.</source>
@@ -1322,17 +1363,17 @@ Error while loading %2</source>
</message>
<message>
<source> - %1%2%3%4 remaining.</source>
- <translation>- 剩余 %1%2%3%4。</translation>
+ <translation> - 剩余 %1%2%3%4。</translation>
</message>
<message>
<source> - unknown time remaining.</source>
- <translation>- 剩余时间未知。</translation>
+ <translation> - 剩余时间未知。</translation>
</message>
</context>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>正在完成 %1 向导</translation>
</message>
<message>
@@ -1340,7 +1381,7 @@ Error while loading %2</source>
<translation>已完成</translation>
</message>
<message>
- <source>Click %1 to exit the %2 Wizard.</source>
+ <source>Click %1 to exit the %2 Setup.</source>
<translation>单击 %1 退出 %2 向导。</translation>
</message>
<message>
@@ -1352,7 +1393,7 @@ Error while loading %2</source>
<translation>立即运行 %1。</translation>
</message>
<message>
- <source>The %1 Wizard failed.</source>
+ <source>The %1 Setup failed.</source>
<translation>%1 向导失败。</translation>
</message>
</context>
@@ -1393,15 +1434,19 @@ Error while loading %2</source>
<source>Cannot create directory &quot;%1&quot;: %2</source>
<translation>无法创建目录“%1”:%2</translation>
</message>
+ <message>
+ <source>Cannot prepare to backup file &quot;%1&quot;: %2</source>
+ <translation>无法为备份文件“%1”准备:%2</translation>
+ </message>
</context>
<context>
<name>QInstaller::IntroductionPage</name>
<message>
- <source>Setup - %1</source>
- <translation>安装程序 - %1</translation>
+ <source>Welcome</source>
+ <translation>欢迎</translation>
</message>
<message>
- <source>Welcome to the %1 Setup Wizard.</source>
+ <source>Welcome to the %1 Setup.</source>
<translation>欢迎使用 %1 安装向导。</translation>
</message>
<message>
@@ -1429,16 +1474,12 @@ Error while loading %2</source>
<translation>无可用更新。</translation>
</message>
<message>
- <source> Only local package management available.</source>
- <translation>仅本地软件包管理可用。</translation>
- </message>
- <message>
<source>&amp;Quit</source>
<translation>退出</translation>
</message>
<message>
<source>There is an important update available. Please select &apos;%1&apos; first</source>
- <translation type="unfinished"></translation>
+ <translation>有重要的更新可供使用,请先选择“%1”</translation>
</message>
</context>
<context>
@@ -1483,16 +1524,12 @@ Error while loading %2</source>
<source>Can not write license file &quot;%1&quot;.</source>
<translation>无法写入许可文件“%1”。</translation>
</message>
- <message>
- <source>No license files found to delete.</source>
- <translation>未找到要删除的许可文件。</translation>
- </message>
</context>
<context>
<name>QInstaller::LineReplaceOperation</name>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation>不支持空搜索参数。</translation>
+ <translation>%1 中的无效参数:不支持空搜索参数。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1510,10 +1547,6 @@ Error while loading %2</source>
<translation>缺少包管理器核心引擎。</translation>
</message>
<message>
- <source>Preparing meta information download...</source>
- <translation>正在准备下载元信息...</translation>
- </message>
- <message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>解压压缩资料档案库。 这可能需要一些时间...</translation>
</message>
@@ -1550,14 +1583,6 @@ Error while loading %2</source>
<translation>检测到“%1”的校验和不匹配。</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... %1/%2 </source>
- <translation>正在从远程资料档案库中检索元信息... %1/%2 </translation>
- </message>
- <message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>正在从远程资料档案库中检索元信息... </translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>提取存档“%1”时出错:%2</translation>
</message>
@@ -1565,6 +1590,44 @@ Error while loading %2</source>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>无法打开文件“%1”进行读取:%2</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>不支持的存档“%1”:没有处理程序注册在文件后缀“%2”名下。</translation>
+ </message>
+ <message>
+ <source>Fetching latest update information...</source>
+ <translation>正在获取最新更新信息……</translation>
+ </message>
+ <message numerus="yes">
+ <source>Updating local cache with %n new items...</source>
+ <translation>
+ <numerusform>正在更新本地缓存中的%n个新项目……</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>正在清空缓存目录并且重启应用程序也许可以解决这个问题。</translation>
+ </message>
+ <message>
+ <source>Unknown exception during updating cache.</source>
+ <translation>更新缓存过程中的未知异常。</translation>
+ </message>
+ <message>
+ <source>Cannot open extracted file &quot;%1&quot; for reading: %2</source>
+ <translation>无法为了读取%2打开已经提取的文件”%1“</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>无法为了写入%2打开文件“%1”</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote repositories...</source>
+ <translation>正在从远程存储库检索信息...</translation>
+ </message>
+ <message>
+ <source>Retrieving meta information from remote repository...</source>
+ <translation>正在从远程资料档案库中检索元信息...</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerCore</name>
@@ -1573,10 +1636,8 @@ Error while loading %2</source>
<translation>编写维护工具时出错</translation>
</message>
<message>
- <source>
-Downloading packages...</source>
- <translation>
-正在下载包...</translation>
+ <source>Downloading packages...</source>
+ <translation>正在下载包...</translation>
</message>
<message>
<source>Installation canceled by user.</source>
@@ -1685,42 +1746,24 @@ Do you want to continue?</source>
<translation>无法解析所有依赖项。</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>即将被移除的组件。</translation>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation>组件安装仅自动依赖 %2 。
-</translation>
+ <source>Cannot install component %1. Component is installed only as automatic dependency to %2.</source>
+ <translation>无法安装组件 %1。组件仅作为 %2 的自动依赖时安装。</translation>
</message>
<message>
- <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation>不可检查组件,这意味着您必须选择其中一個子组件。
-</translation>
+ <source>Cannot install component %1. Component is not checkable, meaning you have to select one of the subcomponents.</source>
+ <translation>无法安装组件 %1。组件不可选择,这意味着您必须选择其中一个子组件。</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation>组件 %1 已安装
-</translation>
+ <source>Component %1 already installed</source>
+ <translation>组件 %1 已安装</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation>组件是虚拟的。
-</translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>无法安装 %1。组件是虚拟的。</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation>未找到组件。
-</translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation>已找到正在运行的进程。</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>无法安装 %1。未找到组件。</translation>
</message>
<message>
<source>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
@@ -1743,10 +1786,6 @@ Do you want to continue?</source>
<translation>没有足够的磁盘空间来存储所有选定的组件! %1 可用,但至少需要 %2。</translation>
</message>
<message>
- <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation>没有足够的磁盘空间来存储临时文件! %1 可用,但至少需要 %2。</translation>
- </message>
- <message>
<source>The volume you selected for installation seems to have sufficient space for installation, but there will be less than 1% of the volume&apos;s space available afterwards.</source>
<translation>您选择安装的容量似乎有足够的安装空间,但之后的可用空间将不到该容量的 1%。</translation>
</message>
@@ -1767,18 +1806,40 @@ Do you want to continue?</source>
<translation>需要用户输入,但输出设备并未与任何终端裝置建立关联。</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation>标识符为 %1 的组件已存在。</translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>无法安装 %1。组件是虚拟组件 %2 的后代。</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation>组件是虚拟组件 %2 的后代。
-</translation>
+ <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
+ <translation>预估的安装程序大小 %1 可能超过被支持的可执行程序大小限制 %2。应用程序可能无法运行。</translation>
</message>
<message>
- <source>The estimated installer size %1 would exceed the supported executable size limit of %2. The application may not be able to run.</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>即将要移除的组件:</translation>
+ </message>
+ <message>
+ <source>Cannot install component %1. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>无法安装组件 %1。加载这个组件时发生错误,所以它被标记为不稳定并且不能被选择。</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2. You may select another location for the temporary files by modifying the local cache path from the installer settings.</source>
+ <translation>没有足够的硬盘空间存储临时文件!有%1可用,但是最少需要%2。您可以通过修改安装程序设置中的本地缓存路径来为这些临时文件指定另外一个存储位置。</translation>
+ </message>
+ <message>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>无法解析要移除的组件。</translation>
+ </message>
+ <message>
+ <source>Cannot select alias %1. There was a problem loading this alias, so it is marked unstable and cannot be selected.</source>
+ <translation>无法选择别名%1。加载这一别名时发生问题,所以它被标识为不稳定,并且无法被选中。</translation>
+ </message>
+ <message>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>无法选择%1。别名被标记为虚拟,意味着它不能被手动选中。</translation>
+ </message>
+ <message>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>创建的安装程序将使用%1的磁盘空间。</translation>
</message>
</context>
<context>
@@ -1825,7 +1886,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Writing maintenance tool.</source>
- <translation>编写维护工具</translation>
+ <translation>编写维护工具。</translation>
</message>
<message>
<source>Failed to seek in file %1: %2</source>
@@ -1896,16 +1957,12 @@ Do you want to continue?</source>
<translation>正在创建维护工具</translation>
</message>
<message>
- <source>
-Installation finished!</source>
- <translation>
-安装已完成!</translation>
+ <source>Installation finished!</source>
+ <translation>安装已完成!</translation>
</message>
<message>
- <source>
-Installation aborted!</source>
- <translation>
-安装已中止!</translation>
+ <source>Installation aborted!</source>
+ <translation>安装已中止!</translation>
</message>
<message>
<source>It is not possible to run that operation from a network location</source>
@@ -1916,16 +1973,12 @@ Installation aborted!</source>
<translation>正在移除未选中的组件...</translation>
</message>
<message>
- <source>
-Update finished!</source>
- <translation>
-更新已完成!</translation>
+ <source>Update finished!</source>
+ <translation>更新已完成!</translation>
</message>
<message>
- <source>
-Update aborted!</source>
- <translation>
-更新已中止!</translation>
+ <source>Update aborted!</source>
+ <translation>更新已中止!</translation>
</message>
<message>
<source>Removal completed successfully.</source>
@@ -1968,10 +2021,8 @@ Update aborted!</source>
<translation>已放弃离线生成!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation>
-正在安装组件 %1</translation>
+ <source>Installing component %1</source>
+ <translation>正在安装组件 %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -2018,10 +2069,6 @@ Installing component %1</source>
<translation>无法检索元信息:%1</translation>
</message>
<message>
- <source>Cannot add temporary update source information.</source>
- <translation>无法添加临时更新源信息。</translation>
- </message>
- <message>
<source>Cannot find any update source information.</source>
<translation>找不到任何更新源信息。</translation>
</message>
@@ -2029,6 +2076,50 @@ Installing component %1</source>
<source>Dependency cycle between components &quot;%1&quot; and &quot;%2&quot; detected.</source>
<translation>检测到组件“%1”和“%2”之间的依赖项循环。</translation>
</message>
+ <message>
+ <source>Preparing to unpack components...</source>
+ <translation>正在准备解压组件......</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%2 个操作中的 %1 个已经完成。</translation>
+ </message>
+ <message>
+ <source>Unpacking components...</source>
+ <translation>正在解压组件......</translation>
+ </message>
+ <message>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%2 个操作中的 %1 个已经回滚。</translation>
+ </message>
+ <message>
+ <source>Rollbacks complete.</source>
+ <translation>回滚完成。</translation>
+ </message>
+ <message>
+ <source>%1 of %2 components installed.</source>
+ <translation>%2 个组件中的 %1 个已经安装。</translation>
+ </message>
+ <message>
+ <source>All components installed.</source>
+ <translation>所有组件已安装。</translation>
+ </message>
+ <message>
+ <source>Loading component scripts...</source>
+ <translation>正在加载组件脚本……</translation>
+ </message>
+ <message>
+ <source>Alias declares name that conflicts with an existing component &quot;%1&quot;</source>
+ <translation>别名声明的名称与已经存在的组件“%1”冲突。</translation>
+ </message>
+ <message>
+ <source>Unresolved component aliases</source>
+ <translation>无法解析的组件别名</translation>
+ </message>
+ <message>
+ <source>Cyclic dependency between aliases &quot;%1&quot; and &quot;%2&quot; detected.</source>
+ <translation>检测到别名“%1”和“%2”之间的依赖项循环。</translation>
+ </message>
</context>
<context>
<name>QInstaller::PackageManagerGui</name>
@@ -2065,7 +2156,7 @@ Installing component %1</source>
<translation>%1 问题</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>设置</translation>
</message>
<message>
@@ -2087,11 +2178,11 @@ Please copy the installer to a local drive</source>
<name>QInstaller::PerformInstallationForm</name>
<message>
<source>&amp;Show Details</source>
- <translation>显示详细信息(%S)</translation>
+ <translation>显示详细信息(&amp;S)</translation>
</message>
<message>
<source>&amp;Hide Details</source>
- <translation>隐藏详细信息(%H)</translation>
+ <translation>隐藏详细信息(&amp;H)</translation>
</message>
</context>
<context>
@@ -2132,6 +2223,18 @@ Please copy the installer to a local drive</source>
<source>Uninstalling</source>
<translation>正在卸载</translation>
</message>
+ <message>
+ <source>&amp;Create Offline Installer</source>
+ <translation>创建离线安装程序(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer for %1</source>
+ <translation>正在为%1创建离线安装程序</translation>
+ </message>
+ <message>
+ <source>Creating Offline Installer</source>
+ <translation>正在创建离线安装程序</translation>
+ </message>
</context>
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
@@ -2175,19 +2278,19 @@ Please copy the installer to a local drive</source>
<translation>准备卸载</translation>
</message>
<message>
- <source>Setup is now ready to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
+ <source>All required information is now available to begin removing %1 from your computer.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;The program directory %2 will be deleted completely&lt;/font&gt;, including all content in that directory!</source>
<translation>安装程序现已准备好从您的计算机中移除 %1。&lt;br&gt;&lt;font color=&quot;red&quot;&gt;将彻底删除程序目录 %2&lt;/font&gt;,目录内所有内容也将被删除!</translation>
</message>
<message>
<source>U&amp;pdate</source>
- <translation>更新(%P)</translation>
+ <translation>更新(&amp;P)</translation>
</message>
<message>
<source>Ready to Update Packages</source>
<translation>准备更新包</translation>
</message>
<message>
- <source>Setup is now ready to begin updating your installation.</source>
+ <source>All required information is now available to begin updating your installation.</source>
<translation>安装程序现已准备好安装您的更新。</translation>
</message>
<message>
@@ -2199,13 +2302,25 @@ Please copy the installer to a local drive</source>
<translation>准备安装</translation>
</message>
<message>
- <source>Setup is now ready to begin installing %1 on your computer.</source>
+ <source>All required information is now available to begin installing %1 on your computer.</source>
<translation>安装程序现已准备好在您的计算器中安装 %1。</translation>
</message>
<message>
<source>Ready to Update</source>
<translation>准备更新</translation>
</message>
+ <message>
+ <source>Create Offline Installer</source>
+ <translation>创建离线安装程序</translation>
+ </message>
+ <message>
+ <source>Ready to Create Offline Installer</source>
+ <translation>准备创建离线安装程序</translation>
+ </message>
+ <message>
+ <source>All required information is now available to create an offline installer for selected components.</source>
+ <translation>为所选组件创建离线安装程序的所需信息都已经准备好。</translation>
+ </message>
</context>
<context>
<name>QInstaller::RegisterFileTypeOperation</name>
@@ -2233,7 +2348,7 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Current mode argument calling &quot;%1&quot; with arguments &quot;%2&quot; is not supported. Please use string or regex.</source>
- <translation>请使用字符串或正则表达式。</translation>
+ <translation>当前使用参数“%2”的模式参数调用“%1”不被支持。请使用字符串或正则表达式。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2262,7 +2377,7 @@ Please copy the installer to a local drive</source>
<context>
<name>QInstaller::RestartPage</name>
<message>
- <source>Completing the %1 Setup Wizard</source>
+ <source>Finished the %1 Setup</source>
<translation>正在完成 %1 安装向导</translation>
</message>
</context>
@@ -2485,6 +2600,14 @@ Please copy the installer to a local drive</source>
<source>Please make sure that the current user has read access to file &quot;%1&quot; or try running %2 as an administrator.</source>
<translation>请确保当前用户拥有文件“%1”的读取权限,或尝试以管理员身份运行 %2。</translation>
</message>
+ <message>
+ <source>Invalid value for &apos;max-concurrent-operations&apos;.</source>
+ <translation>“max-concurrent-operations”的值无效。</translation>
+ </message>
+ <message>
+ <source>Empty value for option &apos;cache-path&apos;.</source>
+ <translation>“cache-path”选项的值为空。</translation>
+ </message>
</context>
<context>
<name>RemoteClient</name>
@@ -2531,8 +2654,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>无法打开设置文件 %1 进行读取:%2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation>选择类别</translation>
+ <source>Categories</source>
+ <translation>类别</translation>
</message>
</context>
<context>
@@ -2669,6 +2792,30 @@ or accept the elevation of access rights if being asked.</source>
<source>Deselect All</source>
<translation>取消全选</translation>
</message>
+ <message>
+ <source>Local cache</source>
+ <translation>本地缓存</translation>
+ </message>
+ <message>
+ <source>The meta information from remote repositories is cached to disk to improve loading times. You may select another directory to store the cache or clear the contents of the current cache.</source>
+ <translation>为了缩短加载时间,远程仓库的元信息被缓存到硬盘。您可以选择另外一个目录来存储缓存,或者清空当前缓存的内容。</translation>
+ </message>
+ <message>
+ <source>Path for cache:</source>
+ <translation>缓存的路径:</translation>
+ </message>
+ <message>
+ <source>Deletes the contents of the cache directory</source>
+ <translation>删除缓存目录中的内容</translation>
+ </message>
+ <message>
+ <source>Clear cache</source>
+ <translation>清空缓存</translation>
+ </message>
+ <message>
+ <source>Clearing cache...</source>
+ <translation>正在清空缓存...</translation>
+ </message>
</context>
<context>
<name>UpdateOperation</name>
@@ -2728,7 +2875,7 @@ or accept the elevation of access rights if being asked.</source>
<translation>错误</translation>
</message>
<message>
- <source>Component Information</source>
+ <source>Information</source>
<translation>组件信息</translation>
</message>
</context>
@@ -2738,6 +2885,22 @@ or accept the elevation of access rights if being asked.</source>
<source>Extracting &quot;%1&quot;</source>
<translation>正在提取“%1”</translation>
</message>
+ <message>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>不支持的存档“%1”:没有处理程序注册在文件后缀名“%2”下。</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
+ <translation>无法打开存档“%1”进行读取:%2</translation>
+ </message>
+ <message>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>读取存档“%1”内容时发生错误:%2</translation>
+ </message>
+ <message>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>正在移除从“%1”中提取的文件</translation>
+ </message>
</context>
<context>
<name>QInstaller::QFileDialogProxy</name>
@@ -2750,27 +2913,185 @@ or accept the elevation of access rights if being asked.</source>
<name>QInstaller::ExtractArchiveOperation::Worker</name>
<message>
<source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>无法为存档“%1”创建处理程序对象:“%2”。</translation>
</message>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
<translation>无法打开存档“%1”进行读取:%2</translation>
</message>
<message>
- <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>提取存档“%1”时出错:%2</translation>
</message>
+</context>
+<context>
+ <name>AboutApplicationDialog</name>
<message>
- <source>Cannot prepare for file &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <source>About %1 installer</source>
+ <translation>关于 %1 安装程序</translation>
</message>
<message>
- <source>Extract for archive &quot;%1&quot; canceled.</source>
- <translation type="unfinished"></translation>
+ <source>About %1 Maintenance Tool</source>
+ <translation>关于 %1 维护工具</translation>
</message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</name>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>提取存档“%1”时出错:%2</translation>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>无法打开存档进行读取:%1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>无法读取条目头部:%1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>无法将条目“%1”写入磁盘:%2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LibArchiveArchive</name>
+ <message>
+ <source>Cannot open archive for reading: %1</source>
+ <translation>无法打开存档进行读取:%1</translation>
+ </message>
+ <message>
+ <source>Cannot read entry header: %1</source>
+ <translation>无法读取条目头部:%1</translation>
+ </message>
+ <message>
+ <source>Cannot write entry &quot;%1&quot; to disk: %2</source>
+ <translation>无法将条目“%1”写入磁盘:%2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>无法打开文件“%1”进行写入:%2</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>无法打开文件“%1”进行读取:%2</translation>
+ </message>
+ <message>
+ <source>Cannot write entry header for &quot;%1&quot;: %2</source>
+ <translation>无法为“%1”写入条目头部:%2</translation>
+ </message>
+</context>
+<context>
+ <name>UninstallerCalculator</name>
+ <message>
+ <source>Deselected Components:</source>
+ <translation>取消组件选择:</translation>
+ </message>
+ <message>
+ <source>Components replaced by &quot;%1&quot;:</source>
+ <translation>组件被替换为“%1”:</translation>
+ </message>
+ <message>
+ <source>Removing virtual components without existing dependencies:</source>
+ <translation>正在移除没有现存依赖的虚拟组件:</translation>
+ </message>
+ <message>
+ <source>Components dependency &quot;%1&quot; removed:</source>
+ <translation>组件依赖“%1”已移除:</translation>
+ </message>
+ <message>
+ <source>Components autodependency &quot;%1&quot; removed:</source>
+ <translation>组件自动依赖“%1”已移除:</translation>
+ </message>
+</context>
+<context>
+ <name>GenericDataCache</name>
+ <message>
+ <source>Cannot initialize cache with empty path.</source>
+ <translation>无法使用空白路径初始化缓存。</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot; for cache.</source>
+ <translation>无法为缓存创建“%1”目录。</translation>
+ </message>
+ <message>
+ <source>Cannot initialize cache: %1</source>
+ <translation>无法初始化缓存:%1</translation>
+ </message>
+ <message>
+ <source>Cannot clear invalidated cache.</source>
+ <translation>无法清空失效的缓存。</translation>
+ </message>
+ <message>
+ <source>Cannot remove manifest file: %1</source>
+ <translation>无法移除清单(manifest)文件:%1</translation>
+ </message>
+ <message>
+ <source>Error while clearing cache: %1</source>
+ <translation>清空缓存时发生错误:%1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve items from invalidated cache.</source>
+ <translation>无法从失效的缓存中获取项目。</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve item from invalidated cache.</source>
+ <translation>无法从失效的缓存中获取项目。</translation>
+ </message>
+ <message>
+ <source>Cannot register item to invalidated cache.</source>
+ <translation>无法向失效的缓存中注册项目。</translation>
+ </message>
+ <message>
+ <source>Cannot register null item.</source>
+ <translation>无法注册空项目。</translation>
+ </message>
+ <message>
+ <source>Cannot register invalid item with checksum %1</source>
+ <translation>无法注册校验和为%1的无效项目</translation>
+ </message>
+ <message>
+ <source>Cannot register item with checksum %1. An item with the same checksum already exists in cache.</source>
+ <translation>无法注册校验和为%1的项目。缓存中已经存在一个相同校验和的项目。</translation>
+ </message>
+ <message>
+ <source>Error while copying item to path &quot;%1&quot;: %2</source>
+ <translation>复制项目到“%1”路径时发生错误:%2</translation>
+ </message>
+ <message>
+ <source>Cannot remove item from invalidated cache.</source>
+ <translation>无法从失效缓存中移除项目。</translation>
+ </message>
+ <message>
+ <source>Cannot remove item specified by checksum %1: no such item exists.</source>
+ <translation>无法移除通过校验和%1指定的项目:查无此项。</translation>
+ </message>
+ <message>
+ <source>Error while removing directory &quot;%1&quot;: %2</source>
+ <translation>移除“%1”目录时发生错误:%2</translation>
+ </message>
+ <message>
+ <source>Error while invalidating cache: %1</source>
+ <translation>使缓存失效时发生错误:%1</translation>
+ </message>
+ <message>
+ <source>Cannot open manifest file: %1</source>
+ <translation>无法打开清单(manifest)文件:%1</translation>
+ </message>
+ <message>
+ <source>Cannot write contents for manifest file: %1</source>
+ <translation>无法写入清单(manifest)文件的内容:%1</translation>
+ </message>
+ <message>
+ <source>Cannot synchronize invalidated cache.</source>
+ <translation>无法同步失效的缓存。</translation>
+ </message>
+ <message>
+ <source>Unknown register mode selected!</source>
+ <translation>未知的注册模式被选中!</translation>
+ </message>
+</context>
+<context>
+ <name>TabController</name>
+ <message>
+ <source>Cache cleared successfully!</source>
+ <translation>缓存清空成功!</translation>
</message>
</context>
</TS>