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.cpp2
-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.cpp59
-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.cpp124
-rw-r--r--src/libs/installer/componentmodel.h32
-rw-r--r--src/libs/installer/componentselectionpage_p.cpp470
-rw-r--r--src/libs/installer/componentselectionpage_p.h40
-rw-r--r--src/libs/installer/componentsortfilterproxymodel.cpp152
-rw-r--r--src/libs/installer/componentsortfilterproxymodel.h63
-rw-r--r--src/libs/installer/concurrentoperationrunner.cpp279
-rw-r--r--src/libs/installer/concurrentoperationrunner.h88
-rw-r--r--src/libs/installer/constants.h91
-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.cpp15
-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.cpp81
-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.cpp148
-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.cpp106
-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.cpp70
-rw-r--r--src/libs/installer/globals.h20
-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.pro61
-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.cpp18
-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.cpp29
-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.cpp570
-rw-r--r--src/libs/installer/libarchivearchive.h32
-rw-r--r--src/libs/installer/libarchivewrapper.cpp16
-rw-r--r--src/libs/installer/libarchivewrapper.h27
-rw-r--r--src/libs/installer/libarchivewrapper_p.cpp83
-rw-r--r--src/libs/installer/libarchivewrapper_p.h5
-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.cpp195
-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.cpp1748
-rw-r--r--src/libs/installer/packagemanagercore.h123
-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.cpp32
-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.h9
-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.h24
-rw-r--r--src/libs/installer/remotefileengine.cpp40
-rw-r--r--src/libs/installer/remotefileengine.h86
-rw-r--r--src/libs/installer/remoteobject.cpp32
-rw-r--r--src/libs/installer/remoteobject.h110
-rw-r--r--src/libs/installer/remoteserver_p.h4
-rw-r--r--src/libs/installer/remoteserverconnection.cpp312
-rw-r--r--src/libs/installer/remoteserverconnection.h41
-rw-r--r--src/libs/installer/remoteserverconnection_p.h12
-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.cpp59
-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.h133
-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.ts1003
-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.ts1046
-rw-r--r--src/sdk/translations/ifw_es.ts979
-rw-r--r--src/sdk/translations/ifw_fr.ts1019
-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.ts944
-rw-r--r--src/sdk/translations/ifw_ko.ts3093
-rw-r--r--src/sdk/translations/ifw_pl.ts858
-rw-r--r--src/sdk/translations/ifw_pt_BR.ts754
-rw-r--r--src/sdk/translations/ifw_pt_PT.ts3118
-rw-r--r--src/sdk/translations/ifw_ru.ts888
-rw-r--r--src/sdk/translations/ifw_zh_CN.ts962
-rw-r--r--src/sdk/translations/translations.pro2
907 files changed, 34881 insertions, 9789 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.cpp b/src/libs/installer/abstractarchive.cpp
index dd9b8e625..f2b4300c4 100644
--- a/src/libs/installer/abstractarchive.cpp
+++ b/src/libs/installer/abstractarchive.cpp
@@ -65,7 +65,7 @@ namespace QInstaller {
*/
/*!
- \fn QInstaller::AbstractArchive::completedChanged(quint64 completed, quint64 total)
+ \fn QInstaller::AbstractArchive::completedChanged(const quint64 completed, const quint64 total)
The ratio of \a completed entries from \a total changed. Subclasses should emit
this whenever the progress changes.
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 a9af93a55..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());
}
@@ -81,9 +103,11 @@ QSize AspectRatioLabel::sizeHint() const
*/
QPixmap AspectRatioLabel::scaledPixmap() const
{
- return m_pixmap.isNull()
- ? QPixmap()
- : m_pixmap.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ if (m_pixmap.isNull())
+ return QPixmap();
+
+ return m_pixmap.scaled(size() * m_pixmap.devicePixelRatio(),
+ Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
/*!
@@ -96,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 642828ad7..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
@@ -101,7 +96,6 @@ ComponentModel::ComponentModel(int columns, PackageManagerCore *core)
, m_modelState(DefaultChecked)
{
m_headerData.insert(0, columns, QVariant());
- connect(this, &QAbstractItemModel::modelReset, this, &ComponentModel::slotModelReset);
}
/*!
@@ -222,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) {
@@ -239,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)
{
@@ -253,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);
@@ -339,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.
*/
@@ -385,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
@@ -417,49 +429,49 @@ void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootCompone
m_rootComponentList.append(component);
}
endResetModel();
+ postModelReset();
}
/*!
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
}
// -- private slots
-void ComponentModel::slotModelReset()
+void ComponentModel::onVirtualStateChanged()
+{
+ // If the virtual state of a component changes, force a reset of the component model.
+ reset(m_core->components(PackageManagerCore::ComponentType::Root));
+}
+
+
+// -- private
+
+void ComponentModel::postModelReset()
{
ComponentList components = m_rootComponentList;
if (!m_core->isUpdater()) {
@@ -485,17 +497,12 @@ void ComponentModel::slotModelReset()
updateAndEmitModelState(); // update the internal state
}
-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));
-}
-
-
-// -- private
-
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;
@@ -511,15 +518,6 @@ void ComponentModel::updateAndEmitModelState()
}
emit checkStateChanged(m_modelState);
-
- foreach (const Component *component, m_rootComponentList) {
- emit dataChanged(indexFromComponentName(component->treeName()),
- indexFromComponentName(component->treeName()));
- QList<Component *> children = component->childItems();
- foreach (const Component *child, children)
- emit dataChanged(indexFromComponentName(child->treeName()),
- indexFromComponentName(child->treeName()));
- }
}
void ComponentModel::collectComponents(Component *const component, const QModelIndex &parent) const
@@ -563,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();
}
}
@@ -580,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 8a9fbf884..c93dd60ae 100644
--- a/src/libs/installer/componentmodel.h
+++ b/src/libs/installer/componentmodel.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 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,21 +89,20 @@ 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:
- void slotModelReset();
void onVirtualStateChanged();
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 a180888d1..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,12 +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 {
@@ -59,20 +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_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_treeView->setUniformRowHeights(true);
m_descriptionBaseWidget = new QWidget(q);
m_descriptionBaseWidget->setObjectName(QLatin1String("DescriptionBaseWidget"));
@@ -81,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);
@@ -103,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);
@@ -155,15 +192,31 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
metaLayout->addWidget(m_progressBar);
metaLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding));
+ m_searchLineEdit = new QLineEdit(q);
+ m_searchLineEdit->setObjectName(QLatin1String("SearchLineEdit"));
+ m_searchLineEdit->setPlaceholderText(ComponentSelectionPage::tr("Search"));
+ m_searchLineEdit->setClearButtonEnabled(true);
+ 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);
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);
@@ -172,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()
@@ -196,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()
@@ -259,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)
@@ -272,35 +309,31 @@ 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_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel;
- m_treeView->setModel(m_currentModel);
- m_treeView->setExpanded(m_currentModel->index(0, 0), true);
- foreach (Component *component, m_core->components(PackageManagerCore::ComponentType::All)) {
- if (component->isExpandedByDefault()) {
- const QModelIndex index = m_currentModel->indexFromComponentName(component->treeName());
- m_treeView->setExpanded(index, true);
- }
- }
+ m_proxyModel->setSourceModel(m_currentModel);
+ m_treeView->setModel(m_proxyModel);
+ expandDefault();
const bool installActionColumnVisible = m_core->settings().installActionColumnVisible();
if (!installActionColumnVisible)
@@ -341,7 +374,57 @@ void ComponentSelectionPagePrivate::updateTreeView()
connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ComponentSelectionPagePrivate::currentSelectedChanged);
- m_treeView->setCurrentIndex(m_currentModel->index(0, 0));
+ m_treeView->setCurrentIndex(m_proxyModel->index(0, 0));
+}
+
+/*!
+ Expands components that should be expanded by default.
+*/
+void ComponentSelectionPagePrivate::expandDefault()
+{
+ m_treeView->setExpanded(m_proxyModel->index(0, 0), true);
+ foreach (auto *component, m_core->components(PackageManagerCore::ComponentType::All)) {
+ if (component->isExpandedByDefault()) {
+ const QModelIndex index = m_proxyModel->mapFromSource(
+ m_currentModel->indexFromComponentName(component->treeName()));
+ m_treeView->setExpanded(index, true);
+ }
+ }
+}
+
+/*!
+ Expands components that were accepted by proxy models filter.
+*/
+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) {
+ if (!proxyModelIndex.isValid())
+ continue;
+
+ QModelIndex index = proxyModelIndex.parent();
+ while (index.isValid()) {
+ if (m_treeView->isExpanded(index))
+ break; // Multiple direct matches in a branch, can be skipped
+
+ m_treeView->expand(index);
+ 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)
@@ -351,12 +434,12 @@ void ComponentSelectionPagePrivate::currentSelectedChanged(const QModelIndex &cu
m_sizeLabel->setText(QString());
- QString description = m_currentModel->data(m_currentModel->index(current.row(),
+ QString description = m_proxyModel->data(m_proxyModel->index(current.row(),
ComponentModelHelper::NameColumn, current.parent()), Qt::ToolTipRole).toString();
m_descriptionLabel->setText(description);
- Component *component = m_currentModel->componentFromIndex(current);
+ Component *component = m_currentModel->componentFromIndex(m_proxyModel->mapToSource(current));
if ((m_core->isUninstaller()) || (!component))
return;
@@ -367,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);
@@ -377,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)
@@ -405,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
@@ -421,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()) {
@@ -429,33 +521,31 @@ void ComponentSelectionPagePrivate::fetchRepositoryCategories()
QLatin1String("FailToFetchPackages"), tr("Error"), m_core->error());
}
updateWidgetVisibility(false);
+ 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);
}
/*!
@@ -489,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.
@@ -498,13 +603,76 @@ 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())
currentSelectedChanged(m_treeView->selectionModel()->currentIndex());
}
+/*!
+ Sets the new filter pattern to \a text and expands the tree nodes.
+*/
+void ComponentSelectionPagePrivate::setSearchPattern(const QString &text)
+{
+ m_proxyModel->setFilterWildcard(text);
+
+ m_treeView->collapseAll();
+ if (text.isEmpty()) {
+ // Expand user selection and default expanded, ensure selected is visible
+ QModelIndex index = m_treeView->selectionModel()->currentIndex();
+ while (index.isValid()) {
+ m_treeView->expand(index);
+ index = index.parent();
+ }
+ expandDefault();
+ m_treeView->scrollTo(m_treeView->selectionModel()->currentIndex());
+ } else {
+ expandSearchResults();
+ }
+}
+
+/*!
+ 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 d2d30e3f0..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,9 +31,11 @@
#include <QObject>
#include <QWidget>
+#include <QHeaderView>
#include "componentmodel.h"
#include "packagemanagergui.h"
+#include "componentsortfilterproxymodel.h"
class QTreeView;
class QLabel;
@@ -46,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
{
@@ -64,49 +66,67 @@ 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);
void selectDefault();
void onModelStateChanged(QInstaller::ComponentModel::ModelState state);
+ 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;
ComponentModel *m_currentModel;
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
new file mode 100644
index 000000000..9308d2356
--- /dev/null
+++ b/src/libs/installer/componentsortfilterproxymodel.cpp
@@ -0,0 +1,152 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 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 "componentsortfilterproxymodel.h"
+
+namespace QInstaller {
+
+/*!
+ \class QInstaller::ComponentSortFilterProxyModel
+ \inmodule QtInstallerFramework
+ \brief The ComponentSortFilterProxyModel provides support for sorting and
+ filtering data passed between another model and a view.
+
+ The class subclasses QSortFilterProxyModel. Compared to the base class,
+ filters affect also child indexes in the base model, meaning if a
+ certain row has a parent that is accepted by filter, it is also accepted.
+ A distinction is made betweed directly and indirectly accepted indexes.
+*/
+
+/*!
+ \enum ComponentSortFilterProxyModel::AcceptType
+
+ This enum holds the possible values for filter acception type for model indexes.
+
+ \value Direct
+ Index was accepted directly by filter.
+ \value Descendant
+ Index is a descendant of an accepted index.
+ \value Rejected
+ Index was not accepted by filter.
+*/
+
+/*!
+ Constructs object with \a parent.
+*/
+ComponentSortFilterProxyModel::ComponentSortFilterProxyModel(QObject *parent)
+ : QSortFilterProxyModel(parent)
+{
+}
+
+/*!
+ Returns a list of source model indexes that were accepted directly by the filter.
+*/
+QVector<QModelIndex> ComponentSortFilterProxyModel::directlyAcceptedIndexes() const
+{
+ QVector<QModelIndex> indexes;
+ for (int i = 0; i < rowCount(); i++) {
+ QModelIndex childIndex = index(i, 0, QModelIndex());
+ findDirectlyAcceptedIndexes(childIndex, indexes);
+ }
+ return indexes;
+}
+
+/*!
+ Returns \c true if the item in the row indicated by the given \a sourceRow and
+ \a sourceParent should be included in the model; otherwise returns \c false.
+*/
+bool ComponentSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+ return acceptsRow(sourceRow, sourceParent);
+}
+
+/*!
+ Returns \c true if the item in the row indicated by the given \a sourceRow and
+ \a sourceParent should be included in the model; otherwise returns \c false. The
+ acception type can be retrieved with \a type.
+*/
+bool ComponentSortFilterProxyModel::acceptsRow(int sourceRow, const QModelIndex &sourceParent,
+ AcceptType *type) const
+{
+ if (type)
+ *type = AcceptType::Rejected;
+
+ if (QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) {
+ if (type)
+ *type = AcceptType::Direct;
+ return true;
+ }
+
+ if (!isRecursiveFilteringEnabled()) // filter not applied for children
+ return false;
+
+ if (!sourceParent.isValid()) // already root
+ return false;
+
+ int currentRow = sourceParent.row();
+ QModelIndex currentParent = sourceParent.parent();
+ // Ascend and check if any parent is accepted
+ forever {
+ if (QSortFilterProxyModel::filterAcceptsRow(currentRow, currentParent)) {
+ if (type)
+ *type = AcceptType::Descendant;
+ return true;
+ }
+ if (!currentParent.isValid()) // we hit a root node
+ break;
+
+ currentRow = currentParent.row();
+ currentParent = currentParent.parent();
+ }
+ return false;
+}
+
+/*!
+ Finds directly accepted child \a indexes for parent index \a in. Returns \c true
+ if at least one accepted index was found, \c false otherwise.
+*/
+bool ComponentSortFilterProxyModel::findDirectlyAcceptedIndexes(const QModelIndex &in, QVector<QModelIndex> &indexes) const
+{
+ bool found = false;
+ for (int i = 0; i < rowCount(in); i++) {
+ if (findDirectlyAcceptedIndexes(index(i, 0, in), indexes))
+ found = true;
+ }
+ if (!hasChildren(in) || !found) { // No need to check current if any child matched
+ AcceptType acceptType;
+ const QModelIndex sourceIndex = mapToSource(in);
+ acceptsRow(sourceIndex.row(), sourceIndex.parent(), &acceptType);
+ if (acceptType == AcceptType::Direct) {
+ indexes.append(in);
+ found = true;
+ }
+ }
+ return found;
+}
+
+} // namespace QInstaller
diff --git a/src/libs/installer/componentsortfilterproxymodel.h b/src/libs/installer/componentsortfilterproxymodel.h
new file mode 100644
index 000000000..12fd0a627
--- /dev/null
+++ b/src/libs/installer/componentsortfilterproxymodel.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** 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 COMPONENTSORTFILTERPROXYMODEL_H
+#define COMPONENTSORTFILTERPROXYMODEL_H
+
+#include "installer_global.h"
+
+#include <QSortFilterProxyModel>
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT ComponentSortFilterProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ enum AcceptType {
+ Direct,
+ Descendant,
+ Rejected
+ };
+
+ explicit ComponentSortFilterProxyModel(QObject *parent = nullptr);
+
+ QVector<QModelIndex> directlyAcceptedIndexes() const;
+
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
+
+private:
+ bool acceptsRow(int sourceRow, const QModelIndex &sourceParent, AcceptType *type = nullptr) const;
+ bool findDirectlyAcceptedIndexes(const QModelIndex &in, QVector<QModelIndex> &indexes) const;
+};
+
+} // namespace QInstaller
+
+#endif // COMPONENTSORTFILTERPROXYMODEL_H
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 0e16d4c4b..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.
@@ -40,6 +40,8 @@ static const QLatin1String scFalse("false");
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");
@@ -56,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");
@@ -67,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");
@@ -81,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");
@@ -90,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");
@@ -112,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 {
@@ -144,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");
@@ -205,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");
@@ -215,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");
@@ -237,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 a40838178..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,11 +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();
removeFiles(sourceDir, helper); // cleanup the files we compressed
if (!archive.rename(sourceDir + fileName)) {
throw Error(CreateLocalRepositoryOperation::tr("Cannot move file \"%1\" to \"%2\": %3")
@@ -373,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 c7ba9dc80..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 {
@@ -269,8 +274,8 @@ void DownloadArchivesJob::onDownloadStatusChanged(const QString &status)
extendedStatus += tr(" - unknown time remaining.");
}
- emit downloadStatusChanged(QLatin1String("Archive: ") + status
- + QLatin1String("<br>Total: ") + extendedStatus);
+ emit downloadStatusChanged(tr("Archive: ") + status
+ + QLatin1String("<br>") + tr("Total: ")+ extendedStatus);
}
/*!
@@ -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 b2bda24a2..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(QLatin1String("TargetDir"));
+ // 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()) {
@@ -184,7 +246,7 @@ bool ExtractArchiveOperation::undoOperation()
bool useStringListType(value(QLatin1String("files")).type() == QVariant::StringList);
QString targetDir = arguments().at(1);
if (packageManager())
- targetDir = packageManager()->value(QLatin1String("TargetDir"));
+ targetDir = packageManager()->value(scTargetDir);
QStringList files;
if (useStringListType) {
files = value(QLatin1String("files")).toStringList();
@@ -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 3c9f2ad1c..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,6 +457,52 @@ 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.
*/
@@ -680,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)
@@ -699,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;
}
@@ -802,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 0da4bc3b6..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,10 +30,17 @@
#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";
-const char IFW_PACKAGE_INFO[] = "ifw.package.info";
// Internal-only, hidden in --help text
const char IFW_PROGRESS_INDICATOR[] = "ifw.progress.indicator";
@@ -62,7 +69,8 @@ namespace QInstaller
*/
/*!
- \fn QInstaller::lcPackageInfo()
+ \fn inline QInstaller::splitStringWithComma(const QString &value())
+ Splits \a value into substrings wherever comma occurs, and returns the list of those strings.
\internal
*/
@@ -70,7 +78,6 @@ Q_LOGGING_CATEGORY(lcServer, IFW_SERVER)
Q_LOGGING_CATEGORY(lcInstallerInstallLog, IFW_INSTALLER_INSTALLLOG)
Q_LOGGING_CATEGORY(lcProgressIndicator, IFW_PROGRESS_INDICATOR)
Q_LOGGING_CATEGORY(lcDeveloperBuild, IFW_DEVELOPER_BUILD)
-Q_LOGGING_CATEGORY(lcPackageInfo, IFW_PACKAGE_INFO)
/*!
Returns available logging categories.
@@ -79,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();
}
@@ -118,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 5053f6d9f..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 {
@@ -40,15 +40,27 @@ INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcInstallerInstallLog)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcProgressIndicator)
INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcDeveloperBuild)
-INSTALLER_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcPackageInfo)
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 4721bb089..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,16 +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 \
@@ -90,7 +100,6 @@ HEADERS += packagemanagercore.h \
constants.h \
packagemanagerproxyfactory.h \
createlocalrepositoryoperation.h \
- lib7z_facade.h \
link.h \
createlinkoperation.h \
packagemanagercoredata.h \
@@ -104,7 +113,6 @@ HEADERS += packagemanagercore.h \
copyfiletask.h \
downloadfiletask.h \
downloadfiletask_p.h \
- unziptask.h \
observer.h \
runextensions.h \
metadatajob.h \
@@ -131,26 +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 \
@@ -192,7 +205,6 @@ SOURCES += packagemanagercore.cpp \
permissionsettings.cpp \
packagemanagerproxyfactory.cpp \
createlocalrepositoryoperation.cpp \
- lib7z_facade.cpp \
link.cpp \
createlinkoperation.cpp \
packagemanagercoredata.cpp \
@@ -203,7 +215,6 @@ SOURCES += packagemanagercore.cpp \
abstractfiletask.cpp \
copyfiletask.cpp \
downloadfiletask.cpp \
- unziptask.cpp \
observer.cpp \
metadatajob.cpp \
protocol.cpp \
@@ -225,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
@@ -249,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 de1ddcc4f..b21634cd7 100644
--- a/src/libs/installer/installiconsoperation.cpp
+++ b/src/libs/installer/installiconsoperation.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.
@@ -32,6 +32,7 @@
#include "globals.h"
#include "adminauthorization.h"
#include "remoteclient.h"
+#include "errors.h"
#include <QDebug>
#include <QDir>
@@ -53,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;
@@ -158,7 +159,16 @@ bool InstallIconsOperation::performOperation()
if (QFile(target).exists()) {
// first backup...
- const QString backup = generateTemporaryFileName(target);
+ QString backup;
+ try {
+ backup = generateTemporaryFileName(target);
+ } catch (const QInstaller::Error &e) {
+ setError(UserDefinedError);
+ setErrorString(tr("Cannot prepare to backup file \"%1\": %2")
+ .arg(QDir::toNativeSeparators(target), e.message()));
+ undoOperation();
+ return false;
+ }
QFile bf(target);
if (!bf.copy(backup)) {
setError(UserDefinedError);
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 17176d7b0..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"
@@ -188,12 +189,6 @@ namespace Lib7z {
Prints string \a s.
*/
-/*!
- \fn bool Lib7z::operator==(const File &lhs, const File &rhs);
-
- Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
-*/
-
// -- 7z init codecs, archives
std::once_flag gOnceFlag;
@@ -368,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;
@@ -544,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);
@@ -628,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;
@@ -770,6 +771,18 @@ STDMETHODIMP ExtractCallback::SetOperationResult(Int32 /*resultEOperationResult*
*/
/*!
+ \typedef Lib7z::Compression
+
+ Synonym for QInstaller::CompressionLevel
+*/
+
+/*!
+ \typedef Lib7z::File
+
+ Synonym for QInstaller::ArchiveEntry
+*/
+
+/*!
\namespace Lib7z
\inmodule QtInstallerFramework
\brief The Lib7z namespace contains miscellaneous identifiers used throughout the Lib7z library.
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 ad5609490..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,14 +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 {
/*!
@@ -57,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
@@ -86,17 +276,22 @@ 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
foreach (const QString &directory, createdDirs)
emit currentEntryChanged(directory);
- int status = archive_read_open(reader.get(), this, nullptr, readCallback, nullptr);
+ archive_read_set_read_callback(reader.get(), readCallback);
+ archive_read_set_callback_data(reader.get(), this);
+ archive_read_set_seek_callback(reader.get(), seekCallback);
+
+ 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;
}
@@ -105,17 +300,24 @@ 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 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);
if (!writeEntry(reader.get(), writer.get(), entry))
@@ -142,6 +344,12 @@ void ExtractWorker::addDataBlock(const QByteArray buffer)
emit dataReadyForRead();
}
+void ExtractWorker::onFilePositionChanged(qint64 pos)
+{
+ m_lastPos = pos;
+ emit seekReady();
+}
+
void ExtractWorker::cancel()
{
m_status = Canceled;
@@ -177,6 +385,26 @@ ssize_t ExtractWorker::readCallback(archive *reader, void *caller, const void **
return buffer->size();
}
+la_int64_t ExtractWorker::seekCallback(archive *reader, void *caller, la_int64_t offset, int whence)
+{
+ Q_UNUSED(reader)
+
+ ExtractWorker *obj;
+ if (!(obj = static_cast<ExtractWorker *>(caller)))
+ return ARCHIVE_FATAL;
+
+ emit obj->seekRequested(static_cast<qint64>(offset), whence);
+
+ {
+ QEventLoop loop;
+ QTimer::singleShot(30000, &loop, &QEventLoop::quit);
+ connect(obj, &ExtractWorker::seekReady, &loop, &QEventLoop::quit);
+ loop.exec();
+ }
+
+ return static_cast<la_int64_t>(obj->m_lastPos);
+}
+
bool ExtractWorker::writeEntry(archive *reader, archive *writer, archive_entry *entry)
{
int status;
@@ -184,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;
}
}
@@ -235,6 +474,13 @@ bool ExtractWorker::writeEntry(archive *reader, archive *writer, archive_entry *
*/
/*!
+ \fn QInstaller::LibArchiveArchive::seekRequested(qint64 offset, int whence)
+
+ Emitted when the worker object requires a seek to \a offset to continue extracting.
+ The \a whence value defines the starting position for \a offset.
+*/
+
+/*!
\fn QInstaller::LibArchiveArchive::workerFinished()
Emitted when the worker object finished extracting an archive.
@@ -267,6 +513,12 @@ bool ExtractWorker::writeEntry(archive *reader, archive *writer, archive_entry *
*/
/*!
+ \fn QInstaller::LibArchiveArchive::workerAboutToSetFilePosition(qint64 pos)
+
+ Emitted when the worker object is about to set new file position \a pos.
+*/
+
+/*!
Constructs an archive object representing an archive file
specified by \a filename with \a parent as the parent object.
*/
@@ -370,34 +622,46 @@ 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
foreach (const QString &directory, createdDirs)
emit currentEntryChanged(directory);
- int status = archive_read_open(reader.get(), m_data, nullptr, readCallback, nullptr);
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ int status = archiveReadOpenWithCallbacks(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 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);
@@ -424,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]);
+
+ m_data->file.fileName().toWCharArray(fileName_w.get());
+ fileName_w.get()[m_data->file.fileName().length()] = '\0';
- for (auto &dataEntry : data) {
+ 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 (fileOrDir.isDir())
+ 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;
@@ -496,21 +815,26 @@ QVector<ArchiveEntry> LibArchiveArchive::list()
QVector<ArchiveEntry> entries;
try {
- int status = archive_read_open(reader.get(), m_data, nullptr, readCallback, nullptr);
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ int status = archiveReadOpenWithCallbacks(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);
@@ -537,9 +861,11 @@ bool LibArchiveArchive::isSupported()
configureReader(reader.get());
try {
- const int status = archive_read_open(reader.get(), m_data, nullptr, readCallback, nullptr);
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ const int status = archiveReadOpenWithCallbacks(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);
@@ -575,6 +901,14 @@ void LibArchiveArchive::workerSetDataAtEnd()
}
/*!
+ Signals the worker object that the client file position changed to \a pos.
+*/
+void LibArchiveArchive::workerSetFilePosition(qint64 pos)
+{
+ emit workerAboutToSetFilePosition(pos);
+}
+
+/*!
Cancels the extract in progress for the worker object.
*/
void LibArchiveArchive::workerCancel()
@@ -620,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);
}
/*!
@@ -627,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);
}
}
@@ -672,9 +1016,11 @@ void LibArchiveArchive::initExtractWorker()
connect(this, &LibArchiveArchive::workerAboutToExtract, &m_worker, &ExtractWorker::extract);
connect(this, &LibArchiveArchive::workerAboutToAddDataBlock, &m_worker, &ExtractWorker::addDataBlock);
connect(this, &LibArchiveArchive::workerAboutToSetDataAtEnd, &m_worker, &ExtractWorker::dataAtEnd);
+ connect(this, &LibArchiveArchive::workerAboutToSetFilePosition, &m_worker, &ExtractWorker::onFilePositionChanged);
connect(this, &LibArchiveArchive::workerAboutToCancel, &m_worker, &ExtractWorker::cancel);
connect(&m_worker, &ExtractWorker::dataBlockRequested, this, &LibArchiveArchive::dataBlockRequested);
+ connect(&m_worker, &ExtractWorker::seekRequested, this, &LibArchiveArchive::seekRequested);
connect(&m_worker, &ExtractWorker::finished, this, &LibArchiveArchive::onWorkerFinished);
connect(&m_worker, &ExtractWorker::currentEntryChanged, this, &LibArchiveArchive::currentEntryChanged);
@@ -684,6 +1030,20 @@ void LibArchiveArchive::initExtractWorker()
}
/*!
+ \internal
+
+ Sets default callbacks for archive \a reader and opens for reading.
+*/
+int LibArchiveArchive::archiveReadOpenWithCallbacks(archive *reader)
+{
+ archive_read_set_read_callback(reader, readCallback);
+ archive_read_set_callback_data(reader, m_data);
+ archive_read_set_seek_callback(reader, seekCallback);
+
+ return archive_read_open1(reader);
+}
+
+/*!
Writes the current \a entry header, then pulls data from the archive \a reader
and writes it to the \a writer handle.
*/
@@ -694,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;
}
}
@@ -767,6 +1135,43 @@ ssize_t LibArchiveArchive::readCallback(archive *reader, void *archiveData, cons
}
/*!
+ \internal
+
+ Seeks to specified \a offset in the file device in \a archiveData and returns the position.
+ Possible \a whence values are \c SEEK_SET, \c SEEK_CUR, and \c SEEK_END. Returns
+ \c ARCHIVE_FATAL if the seek fails.
+*/
+la_int64_t LibArchiveArchive::seekCallback(archive *reader, void *archiveData, la_int64_t offset, int whence)
+{
+ Q_UNUSED(reader)
+
+ ArchiveData *data;
+ if (!(data = static_cast<ArchiveData *>(archiveData)))
+ return ARCHIVE_FATAL;
+
+ if (!data->file.isOpen() || data->file.isSequential())
+ return ARCHIVE_FATAL;
+
+ switch (whence) {
+ case SEEK_SET: // moves file pointer position to the beginning of the file
+ if (!data->file.seek(offset))
+ return ARCHIVE_FATAL;
+ break;
+ case SEEK_CUR: // moves file pointer position to given location
+ if (!data->file.seek(data->file.pos() + offset))
+ return ARCHIVE_FATAL;
+ break;
+ case SEEK_END: // moves file pointer position to the end of file
+ if (!data->file.seek(data->file.size() + offset))
+ return ARCHIVE_FATAL;
+ break;
+ default:
+ return ARCHIVE_FATAL;
+ }
+ return data->file.pos();
+}
+
+/*!
Returns the \a path to a file or directory, without the Win32 namespace prefix.
On Unix platforms, the \a path is returned unaltered.
*/
@@ -783,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()
@@ -794,16 +1214,20 @@ quint64 LibArchiveArchive::totalFiles()
configureReader(reader.get());
try {
- int status = archive_read_open(reader.get(), m_data, nullptr, readCallback, nullptr);
- if (status != ARCHIVE_OK)
- throw Error(QLatin1String(archive_error_string(reader.get())));
+ int status = archiveReadOpenWithCallbacks(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 e0281e655..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.
@@ -64,12 +64,15 @@ public:
public Q_SLOTS:
void extract(const QString &dirPath, const quint64 totalFiles);
void addDataBlock(const QByteArray buffer);
+ void onFilePositionChanged(qint64 pos);
void cancel();
Q_SIGNALS:
void dataBlockRequested();
void dataAtEnd();
void dataReadyForRead();
+ void seekRequested(qint64 offset, int whence);
+ void seekReady();
void finished(const QString &errorString = QString());
void currentEntryChanged(const QString &filename);
@@ -77,10 +80,12 @@ Q_SIGNALS:
private:
static ssize_t readCallback(archive *reader, void *caller, const void **buff);
+ static la_int64_t seekCallback(archive *reader, void *caller, la_int64_t offset, int whence);
bool writeEntry(archive *reader, archive *writer, archive_entry *entry);
private:
QByteArray m_buffer;
+ qint64 m_lastPos = 0;
Status m_status;
};
@@ -94,33 +99,36 @@ 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);
void workerSetDataAtEnd();
+ void workerSetFilePosition(qint64 pos);
void workerCancel();
ExtractWorker::Status workerStatus() const;
Q_SIGNALS:
void dataBlockRequested();
+ void seekRequested(qint64 offset, int whence);
void workerFinished();
void workerAboutToExtract(const QString &dirPath, const quint64 totalFiles);
void workerAboutToAddDataBlock(const QByteArray buffer);
void workerAboutToSetDataAtEnd();
+ void workerAboutToSetFilePosition(qint64 pos);
void workerAboutToCancel();
public Q_SLOTS:
- void cancel() Q_DECL_OVERRIDE;
+ void cancel() override;
private Q_SLOTS:
void onWorkerFinished(const QString &errorString);
@@ -133,12 +141,16 @@ private:
void initExtractWorker();
+ int archiveReadOpenWithCallbacks(archive *reader);
bool writeEntry(archive *reader, archive *writer, archive_entry *entry);
static qint64 readData(QFile *file, char *data, qint64 maxSize);
static ssize_t readCallback(archive *reader, void *archiveData, const void **buff);
+ 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 c259678ca..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 {
@@ -45,19 +46,6 @@ namespace QInstaller {
*/
/*!
- \fn QInstaller::LibArchiveWrapper::currentEntryChanged(const QString &filename)
-
- Current entry changed to \a filename. Emitted when the entry to process is changed.
-*/
-
-/*!
- \fn QInstaller::LibArchiveWrapper::completedChanged(quint64 completed, quint64 total)
-
- The ratio of \a completed entries from \a total changed.
- Emitted when the progress changes.
-*/
-
-/*!
Constructs an archive object representing an archive file
specified by \a filename with \a parent as the parent object.
*/
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 5509812cf..b4325243d 100644
--- a/src/libs/installer/libarchivewrapper_p.cpp
+++ b/src/libs/installer/libarchivewrapper_p.cpp
@@ -41,13 +41,15 @@ namespace QInstaller {
*/
/*!
- \fn QInstaller::ArchiveWrapper::dataBlockRequested()
+ \internal
+ \fn QInstaller::LibArchiveWrapperPrivate::dataBlockRequested()
Emitted when the server process has requested another data block.
*/
/*!
- \fn QInstaller::ArchiveWrapper::remoteWorkerFinished()
+ \internal
+ \fn QInstaller::LibArchiveWrapperPrivate::remoteWorkerFinished()
Emitted when the server process has finished extracting an archive.
*/
@@ -77,7 +79,6 @@ LibArchiveWrapperPrivate::LibArchiveWrapperPrivate()
*/
LibArchiveWrapperPrivate::~LibArchiveWrapperPrivate()
{
- m_timer.stop();
}
/*!
@@ -106,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);
@@ -139,18 +140,24 @@ 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;
connect(this, &LibArchiveWrapperPrivate::remoteWorkerFinished, &loop, &QEventLoop::quit);
loop.exec();
}
+ timer.stop();
return (workerStatus() == ExtractWorker::Success);
}
- return m_archive.extract(dirPath, totalFiles);
+ return m_archive.extract(dirPath, total);
}
/*!
@@ -198,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;
}
@@ -214,7 +221,7 @@ void LibArchiveWrapperPrivate::cancel()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveCancel));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveCancel));
m_lock.unlock();
return;
}
@@ -247,6 +254,10 @@ void LibArchiveWrapperPrivate::processSignals()
emit completedChanged(completed, total);
} else if (name == QLatin1String(Protocol::AbstractArchiveSignalDataBlockRequested)) {
emit dataBlockRequested();
+ } else if (name == QLatin1String(Protocol::AbstractArchiveSignalSeekRequested)) {
+ const qint64 offset = receivedSignals.takeFirst().value<qint64>();
+ const int whence = receivedSignals.takeFirst().value<int>();
+ emit seekRequested(offset, whence);
} else if (name == QLatin1String(Protocol::AbstractArchiveSignalWorkerFinished)) {
emit remoteWorkerFinished();
}
@@ -258,7 +269,7 @@ void LibArchiveWrapperPrivate::processSignals()
*/
void LibArchiveWrapperPrivate::onDataBlockRequested()
{
- constexpr quint64 blockSize = 10 * 1024 * 1024; // 10MB
+ constexpr quint64 blockSize = 1024 * 1024; // 1MB
QFile *const file = &m_archive.m_data->file;
if (!file->isOpen() || file->isSequential()) {
@@ -294,15 +305,39 @@ void LibArchiveWrapperPrivate::onDataBlockRequested()
}
/*!
- Starts the timer to process server-side signals and connects handler
- signals for the matching signals of the wrapper object.
+ Seeks to specified \a offset in the underlying file device. Possible \a whence
+ values are \c SEEK_SET, \c SEEK_CUR, and \c SEEK_END.
*/
-void LibArchiveWrapperPrivate::init()
+void LibArchiveWrapperPrivate::onSeekRequested(qint64 offset, int whence)
{
- m_timer.start(250);
- QObject::connect(&m_timer, &QTimer::timeout,
- this, &LibArchiveWrapperPrivate::processSignals);
+ QFile *const file = &m_archive.m_data->file;
+ if (!file->isOpen() || file->isSequential()) {
+ qCWarning(QInstaller::lcInstallerInstallLog) << file->errorString();
+ setClientFilePosition(ARCHIVE_FATAL);
+ return;
+ }
+ bool success = false;
+ switch (whence) {
+ case SEEK_SET: // moves file pointer position to the beginning of the file
+ success = file->seek(offset);
+ break;
+ case SEEK_CUR: // moves file pointer position to given location
+ success = file->seek(file->pos() + offset);
+ break;
+ case SEEK_END: // moves file pointer position to the end of file
+ success = file->seek(file->size() + offset);
+ break;
+ default:
+ break;
+ }
+ setClientFilePosition(success ? file->pos() : ARCHIVE_FATAL);
+}
+/*!
+ Connects handler signals for the matching signals of the wrapper object.
+*/
+void LibArchiveWrapperPrivate::init()
+{
QObject::connect(&m_archive, &LibArchiveArchive::currentEntryChanged,
this, &LibArchiveWrapperPrivate::currentEntryChanged);
QObject::connect(&m_archive, &LibArchiveArchive::completedChanged,
@@ -310,6 +345,8 @@ void LibArchiveWrapperPrivate::init()
QObject::connect(this, &LibArchiveWrapperPrivate::dataBlockRequested,
this, &LibArchiveWrapperPrivate::onDataBlockRequested);
+ QObject::connect(this, &LibArchiveWrapperPrivate::seekRequested,
+ this, &LibArchiveWrapperPrivate::onSeekRequested);
}
/*!
@@ -319,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();
}
}
@@ -332,7 +369,19 @@ void LibArchiveWrapperPrivate::setClientDataAtEnd()
{
if (connectToServer()) {
m_lock.lockForWrite();
- callRemoteMethod(QLatin1String(Protocol::AbstractArchiveSetClientDataAtEnd));
+ callRemoteMethodDefaultReply(QLatin1String(Protocol::AbstractArchiveSetClientDataAtEnd));
+ m_lock.unlock();
+ }
+}
+
+/*!
+ Calls a remote method to set new file position \a pos.
+*/
+void LibArchiveWrapperPrivate::setClientFilePosition(qint64 pos)
+{
+ if (connectToServer()) {
+ m_lock.lockForWrite();
+ 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 ea8409da0..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>
@@ -66,6 +65,7 @@ Q_SIGNALS:
void currentEntryChanged(const QString &filename);
void completedChanged(const quint64 completed, const quint64 total);
void dataBlockRequested();
+ void seekRequested(qint64 offset, int whence);
void remoteWorkerFinished();
public Q_SLOTS:
@@ -74,16 +74,17 @@ public Q_SLOTS:
private Q_SLOTS:
void processSignals();
void onDataBlockRequested();
+ void onSeekRequested(qint64 offset, int whence);
private:
void init();
void addDataBlock(const QByteArray &buffer);
void setClientDataAtEnd();
+ void setClientFilePosition(qint64 pos);
ExtractWorker::Status workerStatus() const;
private:
- QTimer m_timer;
mutable QReadWriteLock m_lock;
LibArchiveArchive m_archive;
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 45f7aab1b..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;
@@ -145,10 +149,7 @@ void LoggingHandler::messageHandler(QtMsgType type, const QMessageLogContext &co
static Uptime uptime;
- QString ba;
- if (context.category != lcPackageInfo().categoryName()) {
- ba = QLatin1Char('[') + QString::number(uptime.elapsed()) + QStringLiteral("] ");
- }
+ QString ba = QLatin1Char('[') + QString::number(uptime.elapsed()) + QStringLiteral("] ");
ba += trimAndPrepend(type, msg);
if (type != QtDebugMsg && context.file) {
@@ -251,23 +252,28 @@ bool LoggingHandler::outputRedirected() const
}
/*!
- Prints basic information about \a components.
+ Prints update information from \a components.
*/
-void LoggingHandler::printComponentInfo(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();
}
- qCDebug(lcPackageInfo) << qPrintable(doc.toString(4));
+ stream.writeEndElement();
+
+ stream.writeEndDocument();
+ std::cout << qPrintable(output);
}
/*!
@@ -276,28 +282,37 @@ void LoggingHandler::printComponentInfo(const QList<Component *> components) con
*/
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();
}
- qCDebug(lcPackageInfo) << qPrintable(doc.toString(4));
+ stream.writeEndElement();
+
+ stream.writeEndDocument();
+ std::cout << qPrintable(output);
}
/*!
@@ -305,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());
}
- root.appendChild(update);
+ stream.writeEndElement();
}
- qCDebug(lcPackageInfo) << qPrintable(doc.toString(4));
+ 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();
+ }
+ );
+
+ 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(output);
}
/*!
@@ -421,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 a997a6d60..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 printComponentInfo(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 232024f66..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()));
}
/*!
@@ -1003,8 +1079,46 @@ QString PackageManagerCore::readConsoleLine(const QString &title, qint64 maxlen)
}
/*!
- Checks whether the target directory \a targetDirectory exists and has contents:
+ Returns \a path with the '/' separators converted to separators that are
+ appropriate for the underlying operating system.
+
+ 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)
+{
+ return QDir::toNativeSeparators(path);
+}
+
+/*!
+ Returns \a path using '/' as file separator.
+
+ 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)
+{
+ return QDir::fromNativeSeparators(path);
+}
+
+/*!
+ 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.
@@ -1012,14 +1126,17 @@ QString PackageManagerCore::readConsoleLine(const QString &title, qint64 maxlen)
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)
@@ -1076,8 +1193,8 @@ QString PackageManagerCore::targetDirWarning(const QString &targetDirectory) con
}
}
- target = target.canonicalPath();
- if (!target.isEmpty() && (target == QDir::root() || target == QDir::home())) {
+ target.setPath(target.canonicalPath());
+ if (!target.path().isEmpty() && (target == QDir::root() || target == QDir::home())) {
return tr("As the install directory is completely deleted, installing in %1 is forbidden.")
.arg(QDir::toNativeSeparators(target.path()));
}
@@ -1170,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
@@ -1194,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")))
@@ -1204,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.";
@@ -1353,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.
@@ -1366,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."));
@@ -1377,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);
@@ -1405,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();
}
@@ -1418,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();
@@ -1476,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;
}
@@ -1494,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);
@@ -1512,7 +1732,7 @@ bool PackageManagerCore::fetchRemotePackagesTree()
return false;
}
- const LocalPackagesHash installedPackages = d->localInstalledPackages();
+ const LocalPackagesMap installedPackages = d->localInstalledPackages();
if (!isInstaller() && status() == Failure)
return false;
@@ -1522,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()) {
@@ -1777,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
+{
+ 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()
{
- d->m_testChecksum = test;
+ 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.
@@ -1823,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);
}
@@ -1888,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++;
@@ -1904,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);
@@ -1917,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);
}
/*!
@@ -1946,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.
*/
@@ -1983,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.
@@ -1995,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;
}
/*!
@@ -2012,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) {
@@ -2061,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;
}
/*!
@@ -2104,7 +2476,7 @@ bool PackageManagerCore::calculateComponentsToUninstall() const
*/
QList<Component *> PackageManagerCore::componentsToUninstall() const
{
- return d->uninstallerCalculator()->componentsToUninstall().toList();
+ return d->uninstallerCalculator()->resolvedComponents();
}
/*!
@@ -2112,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();
}
/*!
@@ -2126,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);
}
/*!
@@ -2159,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
@@ -2167,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;
}
@@ -2182,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)
@@ -2227,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;
@@ -2236,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)
@@ -2253,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()
@@ -2277,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;
@@ -2320,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)
@@ -2344,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) {
@@ -2362,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.
@@ -2369,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();
@@ -2481,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;
@@ -2528,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())) {
@@ -2551,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);
}
/*!
@@ -2578,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();
@@ -2593,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);
}
/*!
@@ -2673,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)
@@ -2681,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());
@@ -2714,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
@@ -2728,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;
@@ -2838,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.
@@ -2849,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.
@@ -3056,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('<'));
@@ -3154,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.
@@ -3176,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();
}
/*!
@@ -3348,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()
*/
@@ -3406,6 +4067,7 @@ bool PackageManagerCore::isUninstaller() const
void PackageManagerCore::setUpdater()
{
d->m_magicBinaryMarker = BinaryContent::MagicUpdaterMarker;
+ d->m_componentByNameHash.clear();
emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
@@ -3426,6 +4088,7 @@ bool PackageManagerCore::isUpdater() const
void PackageManagerCore::setPackageManager()
{
d->m_magicBinaryMarker = BinaryContent::MagicPackageManagerMarker;
+ d->m_componentByNameHash.clear();
emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
@@ -3447,6 +4110,7 @@ bool PackageManagerCore::isPackageManager() const
void PackageManagerCore::setOfflineGenerator()
{
d->m_magicMarkerSupplement = BinaryContent::OfflineGenerator;
+ emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
/*!
@@ -3465,6 +4129,7 @@ bool PackageManagerCore::isOfflineGenerator() const
void PackageManagerCore::setPackageViewer()
{
d->m_magicMarkerSupplement = BinaryContent::PackageViewer;
+ emit installerBinaryMarkerChanged(d->m_magicBinaryMarker);
}
/*!
@@ -3478,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.
*/
@@ -3614,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.
@@ -3680,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;
}
@@ -3687,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);
@@ -3703,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
@@ -3718,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 (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());
+ foreach (auto &package, locals) {
+ if (package.virtualComp && package.autoDependencies.isEmpty()) {
+ if (!d->m_localVirtualComponents.contains(package.name))
+ d->m_localVirtualComponents.append(package.name);
+ }
+
+ 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->buildComponentTree(components, true))
+ if (!d->buildComponentAliases())
+ return false;
+
+ } catch (const Error &error) {
+ d->clearAllComponentLists();
+ d->setStatus(PackageManagerCore::Failure, error.message());
+
+ // 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) {
@@ -3899,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
@@ -3921,7 +4715,6 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
component->setCheckState(Qt::Checked);
}
}
-
if (foundEssentialUpdate()) {
foreach (QInstaller::Component *component, components) {
if (d->statusCanceledOrFailed())
@@ -3949,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.
@@ -3962,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();
@@ -4026,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 b5ef6304e..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);
@@ -213,7 +242,10 @@ public:
Q_INVOKABLE QString readFile(const QString &filePath, const QString &codecName) const;
Q_INVOKABLE QString readConsoleLine(const QString &title = QString(), qint64 maxlen = 0) const;
- bool checkTargetDir(const QString &targetDirectory);
+ Q_INVOKABLE QString toNativeSeparators(const QString &path);
+ Q_INVOKABLE QString fromNativeSeparators(const QString &path);
+
+ bool installationAllowedToDirectory(const QString &targetDirectory);
QString targetDirWarning(const QString &targetDirectory) const;
public:
@@ -226,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();
@@ -272,6 +321,8 @@ public:
void setPackageViewer();
Q_INVOKABLE bool isPackageViewer() const;
+ void resetBinaryMarkerSupplement();
+
void setUserSetBinaryMarker(qint64 magicMarker);
Q_INVOKABLE bool isUserSetBinaryMarker() const;
@@ -286,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;
@@ -332,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();
@@ -343,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;
@@ -352,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();
@@ -379,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);
@@ -401,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 8f6f24a09..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,14 +234,14 @@ 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);
if (dir.isEmpty())
dir = replaceVariables(m_settings.value(key, _default).toString());
#ifdef Q_OS_WIN
- return QInstaller::normalizePathName(dir);
+ return QDir::fromNativeSeparators(QInstaller::normalizePathName(dir));
#else
if (dir.startsWith(QLatin1String("~/")))
return QDir::home().absoluteFilePath(dir.mid(2));
@@ -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 c7eb9a308..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";
@@ -177,6 +178,7 @@ const char AbstractArchiveIsSupported[] = "AbstractArchive::isSupported";
const char AbstractArchiveSetCompressionLevel[] = "AbstractArchive::setCompressionLevel";
const char AbstractArchiveAddDataBlock[] = "AbstractArchive::addDataBlock";
const char AbstractArchiveSetClientDataAtEnd[] = "AbstractArchive::setClientDataAtEnd";
+const char AbstractArchiveSetFilePosition[] = "AbstractArchive::setFilePosition";
const char AbstractArchiveWorkerStatus[] = "AbstractArchive::workerStatus";
const char AbstractArchiveCancel[] = "AbstractArchive::cancel";
@@ -184,6 +186,7 @@ const char GetAbstractArchiveSignals[] = "GetAbstractArchiveSignals";
const char AbstractArchiveSignalCurrentEntryChanged[] = "AbstractArchive::currentEntryChanged";
const char AbstractArchiveSignalCompletedChanged[] = "AbstractArchive::completedChanged";
const char AbstractArchiveSignalDataBlockRequested[] = "AbstractArchive::dataBlockRequested";
+const char AbstractArchiveSignalSeekRequested[] = "AbstractArchive::seekRequested";
const char AbstractArchiveSignalWorkerFinished[] = "AbstractArchive::workerFinished";
} // namespace Protocol
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 9cc679de8..3dec97c95 100644
--- a/src/libs/installer/remoteclient_p.h
+++ b/src/libs/installer/remoteclient_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,8 +39,9 @@
#include "constants.h"
#include <QCoreApplication>
-#include <QElapsedTimer>
-#include <QMutex>
+#include <QDeadlineTimer>
+#include <QRecursiveMutex>
+#include <QTimer>
#include <QThread>
namespace QInstaller {
@@ -54,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)
@@ -165,11 +165,19 @@ public:
}
if (started) {
- QElapsedTimer t;
- t.start();
+ QTimer timer;
+ QEventLoop loop;
// 30 seconds waiting ought to be enough for the app to start
- while ((!m_serverStarted) && (t.elapsed() < 30000))
+ QDeadlineTimer deadline(30000);
+
+ connect(&timer, &QTimer::timeout, [&]() {
m_serverStarted = authorize();
+ if (m_serverStarted || deadline.hasExpired())
+ loop.quit();
+ });
+
+ timer.start(100);
+ loop.exec();
}
}
@@ -192,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..2ead83861 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) 2024 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);
}
@@ -534,7 +554,11 @@ bool RemoteFileEngine::renameOverwrite(const QString &newName)
return m_fileEngine.renameOverwrite(newName);
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
QDateTime RemoteFileEngine::fileTime(FileTime time) const
+#else
+QDateTime RemoteFileEngine::fileTime(QFile::FileTime time) const
+#endif
{
if ((const_cast<RemoteFileEngine *>(this))->connectToServer()) {
return callRemoteMethod<QDateTime>
diff --git a/src/libs/installer/remotefileengine.h b/src/libs/installer/remotefileengine.h
index 9544403f7..c46e861ca 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) 2024 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,64 @@ 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;
+#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
+ QDateTime fileTime(FileTime time) const override;
+#else
+ QDateTime fileTime(QFile::FileTime time) const override;
+#endif
+ 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 1c521cdf3..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.
@@ -30,6 +30,7 @@
#include "protocol.h"
#include "remoteclient.h"
+#include "globals.h"
#include <QCoreApplication>
#include <QElapsedTimer>
@@ -45,7 +46,6 @@ namespace QInstaller {
RemoteObject::RemoteObject(const QString &wrappedType, QObject *parent)
: QObject(parent)
- , dummy(nullptr)
, m_type(wrappedType)
, m_socket(nullptr)
{
@@ -57,8 +57,22 @@ 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.
+ QEventLoop loop;
+ connect(m_socket, &QLocalSocket::bytesWritten, &loop, &QEventLoop::quit);
+ loop.exec();
+ }
+ m_socket->disconnectFromServer();
+ if (!(m_socket->state() == QLocalSocket::UnconnectedState
+ || m_socket->waitForDisconnected())) {
+ qCWarning(lcServer) << "Error while disconnecting from remote server:"
+ << m_socket->error();
+ }
+ }
} else {
Q_ASSERT_X(false, Q_FUNC_INFO, "Socket running in a different Thread than this object.");
}
@@ -107,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;
}
@@ -120,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 5d72f834d..55c4f48d9 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) 2024 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,47 @@ 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)));
+#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
+ reply->send(m_engine->fileTime(static_cast<QAbstractFileEngine::FileTime> (filetime)));
+#else
+ reply->send(m_engine->fileTime(static_cast<QFile::FileTime> (filetime)));
+#endif
} 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 +605,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 +615,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;
@@ -596,8 +630,12 @@ void RemoteServerConnection::handleArchive(QIODevice *socket, const QString &com
archive->workerAddDataBlock(buff);
} else if (command == QLatin1String(Protocol::AbstractArchiveSetClientDataAtEnd)) {
archive->workerSetDataAtEnd();
+ } else if (command == QLatin1String(Protocol::AbstractArchiveSetFilePosition)) {
+ qint64 pos;
+ 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 dc6d794b6..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);
@@ -143,6 +143,8 @@ private:
this, &AbstractArchiveSignalReceiver::onCompletedChanged);
connect(archive, &LibArchiveArchive::dataBlockRequested,
this, &AbstractArchiveSignalReceiver::onDataBlockRequested);
+ connect(archive, &LibArchiveArchive::seekRequested,
+ this, &AbstractArchiveSignalReceiver::onSeekRequested);
connect(archive, &LibArchiveArchive::workerFinished,
this, &AbstractArchiveSignalReceiver::onWorkerFinished);
}
@@ -169,6 +171,14 @@ private Q_SLOTS:
m_receivedSignals.append(QLatin1String(Protocol::AbstractArchiveSignalDataBlockRequested));
}
+ void onSeekRequested(qint64 offset, int whence)
+ {
+ QMutexLocker _(&m_lock);
+ m_receivedSignals.append(QLatin1String(Protocol::AbstractArchiveSignalSeekRequested));
+ m_receivedSignals.append(offset);
+ m_receivedSignals.append(whence);
+ }
+
void onWorkerFinished()
{
QMutexLocker _(&m_lock);
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 59e9afe90..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().printComponentInfo(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();
@@ -264,15 +285,15 @@ bool CommandLineInterface::setTargetDir()
if (m_parser.isSet(CommandLineOptions::scRootLong)) {
targetDir = m_parser.value(CommandLineOptions::scRootLong);
} else {
- targetDir = m_core->value(QLatin1String("TargetDir"));
+ 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);
} else {
- m_core->setValue(QLatin1String("TargetDir"), targetDir);
+ m_core->setValue(QInstaller::scTargetDir, targetDir);
return true;
}
}
@@ -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 7573241cf..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,28 +147,25 @@ 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"
"ifw.installer.* = true\n"
"ifw.server = true\n"
- "ifw.progress.indicator = true\n"
- "ifw.package.* = true\n");
+ "ifw.progress.indicator = true\n");
} else {
// enable all except detailed package information and developer specific logging
loggingRules = QLatin1String("ifw.* = true\n"
- "ifw.developer.build = false\n"
- "ifw.package.* = true\n");
+ "ifw.developer.build = false\n");
}
if (QInstaller::LoggingHandler::instance().verboseLevel() == QInstaller::LoggingHandler::Detailed) {
- loggingRules += QLatin1String("\nifw.developer.build = true\n"
- "ifw.package.* = true\n");
+ loggingRules += QLatin1String("\nifw.developer.build = true\n");
}
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)
@@ -184,18 +185,19 @@ 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);
}
+ QLocale lang = QLocale::English;
#ifndef IFW_DISABLE_TRANSLATIONS
if (!isCommandLineInterface) {
const QString directory = QLatin1String(":/translations");
@@ -205,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)
@@ -215,27 +218,36 @@ 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
- emit m_core->defaultTranslationsLoadedForLanguage(locale.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;
}
}
#endif
@@ -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('='))) {
@@ -394,6 +426,9 @@ public:
errorMessage = e.message();
return false;
}
+
+ m_core->setValue(QInstaller::scUILanguage, lang.name());
+ emit m_core->defaultTranslationsLoadedForLanguage(lang);
ProductKeyCheck::instance()->addPackagesFromXml(QLatin1String(":/metadata/Updates.xml"));
return true;
@@ -447,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();
}
@@ -482,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;
@@ -495,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);
}
}
@@ -544,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 af37a8c19..ee995f3d5 100644
--- a/src/sdk/translations/ifw_ar.ts
+++ b/src/sdk/translations/ifw_ar.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="ar">
+<TS version="2.1" language="ar_EG" sourcelanguage="en_GB">
<context>
<name>QInstaller::ProxyCredentialsDialog</name>
<message>
@@ -9,7 +9,7 @@
</message>
<message>
<source>The proxy %1 requires a username and password.</source>
- <translation>الوكيل %1 بتطلب اسم مستخدم وكلمة مرور.</translation>
+ <translation>الوكيل %1 يتطلب اسم مستخدم وكلمة مرور.</translation>
</message>
<message>
<source>Username:</source>
@@ -161,6 +161,10 @@
<translation>أضف اسم كلمة المرور للمصادقة على الخادم.</translation>
</message>
<message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>رابط الخادم المحتوي على مستودع صالح.</translation>
+ </message>
+ <message>
<source>An error occurred while testing this repository.</source>
<translation>حدث خطأ أثناء اختبار هذا المستودع.</translation>
</message>
@@ -209,8 +213,28 @@
<translation>المستودعات المعرفة من قبل المستخدم</translation>
</message>
<message>
- <source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -221,55 +245,63 @@
</message>
<message>
<source>Another %1 instance is already running. Wait until it finishes, close it, or restart your system.</source>
- <translation type="unfinished">نسخة أخرى من %1 تعمل بالفعل. انتظر حتى تنتهي أو أغلقها أو أعد تشغيل نظامك.</translation>
+ <translation>نسخة أخرى من %1 تعمل بالفعل. انتظر حتى تنتهي أو أغلقها أو أعد تشغيل نظامك.</translation>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن بدء برنامج التثبيت الثنائي كمُحدث.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن بدء برنامج التثبيت الثنائي كمدير للحزم.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن بدء برنامج التثبيت الثنائي كبرنامج إلغاء التثبيت.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>قائمة مستودع فارغة للخيار &quot;addRepository&quot;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>قائمة مستودع فارغة للخيار &quot;addTempRepository&quot;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>قائمة مستودع فارغة للخيار &quot;setTempRepository&quot;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>قائمة مستودع فارغة للخيار &quot;installCompressedRepository&quot;.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
- <translation type="unfinished">الملف %1 ليس موجوداً.</translation>
+ <translation>الملف %1 ليس موجوداً.</translation>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>معاملات مفقودة للخيار %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>قيمة زر غير صالحة %1 </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>معاملات غير صحيحة لـ %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 type="unfinished"></translation>
+ <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>
@@ -344,43 +376,47 @@
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation></translation>
+ <translation>لا يمكن إنشاء المجلد &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot copy file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation></translation>
+ <translation>لا يمكن نسخ الملف من &quot;%1&quot; إلى &quot;%2&quot;: %3</translation>
</message>
<message>
<source>Cannot move file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation></translation>
+ <translation>لا يمكن نقل الملف من &quot;%1&quot; إلى &quot;%2&quot;: %3</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
- <translation></translation>
+ <translation>لا يمكن إنشاء المجلد &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot open temporary file: %1</source>
- <translation></translation>
+ <translation>لا يمكن فتح الملف المؤقت: %1</translation>
</message>
<message>
<source>Cannot open temporary file for template %1: %2</source>
- <translation></translation>
+ <translation>لا يمكن فتح الملف المؤقت للقالب %1: %2</translation>
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation type="unfinished">لا يمكن نسخ الملف &quot;%1&quot; إلى &quot;%2&quot;: %3</translation>
+ <translation>لا يمكن نسخ الملف &quot;%1&quot; إلى &quot;%2&quot;: %3</translation>
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن نسخ الملف من &quot;%1&quot; إلى &quot;%2&quot;:</translation>
</message>
<message>
<source>The specified module could not be found.</source>
- <translation></translation>
+ <translation>تعذر العثور على النموذج المحدد.</translation>
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -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>
@@ -463,7 +487,7 @@
</message>
<message>
<source>Cannot resolve isDefault in %1</source>
- <translation></translation>
+ <translation>لا يمكن الحل isDefault في%1</translation>
</message>
<message>
<source>Update Info: </source>
@@ -471,11 +495,27 @@
</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>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>لا يمكن فتح ملف واجهة المستخدم المطلوب &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>
@@ -524,44 +564,44 @@
<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 type="unfinished"></translation>
+ <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 type="unfinished"></translation>
+ <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 type="unfinished"></translation>
+ <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 type="unfinished"></translation>
+ <translation>قم بإلغاء تحديد المكونات الافتراضية في عرض الشجري.</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;تصفح ملفات QBSP</translation>
+ <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>
<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>
+ <source>Filter the enabled repository categories</source>
+ <translation>قم بتصفية فئات المستودع الممكنة للاختيار.</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -577,7 +617,7 @@
</message>
<message>
<source>Please select the components you want to update.</source>
- <translation></translation>
+ <translation>الرجاء تحديد المكونات التي تريد تحديثها.</translation>
</message>
<message>
<source>Please select the components you want to install.</source>
@@ -588,7 +628,7 @@
<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>
@@ -596,28 +636,28 @@
<translation>المكونات الضرورية التي يجب تحديثها أولاً قبل اختيار المكونات الآخرى للتحديث.</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Search</source>
+ <translation>بحث</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>تصفح ملفات &amp;QBSP</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Select</source>
+ <translation>اختيار</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Error</source>
+ <translation>خطأ</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -631,8 +671,8 @@
<translation>خطأ</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>معلومات المكون</translation>
</message>
</context>
<context>
@@ -650,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>
@@ -754,11 +790,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن إنشاء المسار &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن إزالة المجلد &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -792,6 +828,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<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>
@@ -827,14 +871,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>
@@ -856,6 +892,97 @@ Error while loading %2</source>
<source>Cannot find component for %1.</source>
<translation>لا يمكن العثور على المكون لـ %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 من %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>تم تحميل %1.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n يوم(أيام)، </numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n ساعة(ساعات)، </numerusform>
+ <numerusform>ساعة، </numerusform>
+ <numerusform>ساعتان، </numerusform>
+ <numerusform>%n ساعات، </numerusform>
+ <numerusform>%n ساعة، </numerusform>
+ <numerusform>%n ساعة، </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n دقيقة(دقائق)</numerusform>
+ <numerusform>دقيقة</numerusform>
+ <numerusform>دقيقتان</numerusform>
+ <numerusform>%n دقائق</numerusform>
+ <numerusform>%n دقيقة</numerusform>
+ <numerusform>%n دقيقة</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n ثانية(ثوان)</numerusform>
+ <numerusform>ثانية</numerusform>
+ <numerusform>ثانيتان</numerusform>
+ <numerusform>%n ثوان</numerusform>
+ <numerusform>%n ثانية</numerusform>
+ <numerusform>%n ثانية</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - يتبقى %1%2%3%4.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - الوقت المتبقي غير معلوم.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>أرشيف: </translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <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>
<name>QInstaller::Downloader</name>
@@ -998,20 +1125,21 @@ Error while loading %2</source>
<source>Extracting &quot;%1&quot;</source>
<translation>استخراج &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>أرشيف غير مدعوم &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 extracting archive &quot;%1&quot;: %2</source>
- <translation>خطأ أثناء استخراج الأرشيف &quot;%1&quot;: %2</translation>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>حدث خطأ أثناء قراءة محتويات الأرشيف &quot;%1&quot;: %2.</translation>
</message>
<message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>اكتُشف خطأ غير معروف أثناء استخراج &quot;%1&quot;.</translation>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>إزالة الملفات المستخرجة من &quot;%1&quot;</translation>
</message>
</context>
<context>
@@ -1066,6 +1194,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>
@@ -1093,10 +1233,22 @@ 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>
<message>
+ <source>Internal code: %1</source>
+ <translation>الرمز الداخلي: %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>لا توجد ذاكرة كافية</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>خطأ: %1</translation>
</message>
@@ -1160,14 +1312,6 @@ Error while loading %2</source>
<source>Unknown exception caught (%1)</source>
<translation>اكتُشف استثناء مجهول (%1)</translation>
</message>
- <message>
- <source>Internal code: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not enough memory</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>DirectoryGuard</name>
@@ -1221,16 +1365,12 @@ 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>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>معامل غير صالح %1. معامل البحث الفارغ غير مدعومة.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1248,14 +1388,14 @@ 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>
<message>
+ <source>Metadata download canceled.</source>
+ <translation>تم إلغاء تحميل البيانات الوصفية.</translation>
+ </message>
+ <message>
<source>Unknown exception during extracting.</source>
<translation>حدث خطأ غير معروف أثناء الاستخراج.</translation>
</message>
@@ -1284,28 +1424,55 @@ 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>Cannot open file &quot;%1&quot; for reading: %2</source>
+ <translation>لا يمكن فتح الملف &quot;%1&quot; للقراءة: %2</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>جارٍ الحصول على معلومات التعريف من المستودع البعيد... </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>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>حدث خطأ أثناء إستخراج الأرشيف &quot;%1&quot;: %2</translation>
+ <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>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>اكتُشف استثناء غير معروف أثناء استخراج الأرشيف &quot;%1&quot;.</translation>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>قد يؤدي مسح دليل ذاكرة التخزين المؤقت وإعادة تشغيل التطبيق إلى حل هذه المشكلة.</translation>
</message>
<message>
- <source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>لا يمكن فتح الملف &quot;%1&quot; للقراءة: %2</translation>
+ <source>Unknown exception during updating cache.</source>
+ <translation>حدث خطأ غير معروف أثناء تحديث ذاكرة التخزين المؤقت.</translation>
</message>
<message>
- <source>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1382,10 +1549,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>
@@ -1396,6 +1561,10 @@ Downloading packages...</source>
<translation>انتهت كل التنزيلات.</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation>إلغاء المثبت</translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>حدث خطأ في المصادقة</translation>
</message>
@@ -1413,65 +1582,65 @@ Downloading packages...</source>
</message>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>مطلوب إدخال المستخدم ولكن جهاز الإخراج غير مرتبط بطرف.</translation>
</message>
<message>
<source>The directory you selected already exists and contains an installation. Choose a different target for installation.</source>
- <translation type="unfinished">المجلد الذي اخترته موجود بالفعل ويحتوي على تثبيت. اختر وجهة مختلفة للتثبيت.</translation>
+ <translation>المجلد الذي اخترته موجود بالفعل ويحتوي على تثبيت. اختر وجهة مختلفة للتثبيت.</translation>
</message>
<message>
<source>Warning</source>
- <translation type="unfinished">تحذير</translation>
+ <translation>تحذير</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 type="unfinished">لقد اخترت مجلداً موجودأ وغير فارغ للتثبيت.
+ <translation>لقد اخترت مجلداً موجودأ وغير فارغ للتثبيت.
سيتم حذفه تماماً عند إزالة تثبيت هذا التطبيق.
لا يُنصح بالتثبيت إلى هذا المجلد لاحتمالية فشل التثبيت.
هل تريد الاستمرار؟</translation>
</message>
<message>
<source>You have selected an existing file or symlink, please choose a different target for installation.</source>
- <translation type="unfinished">لقد حددت ملفاً موجوداً أو اختصاراً، يرجى اختيار وجهة مختلفة للتثبيت.</translation>
+ <translation>لقد حددت ملفاً موجوداً أو اختصاراً، يرجى اختيار وجهة مختلفة للتثبيت.</translation>
</message>
<message>
<source>The installation path cannot be empty, please specify a valid directory.</source>
- <translation type="unfinished">لا يمكن أن يكون مسار التثبيت فارغاً. يرجى تحديد مجلد صالح.</translation>
+ <translation>لا يمكن أن يكون مسار التثبيت فارغاً. يرجى تحديد مجلد صالح.</translation>
</message>
<message>
<source>The installation path cannot be relative, please specify an absolute path.</source>
- <translation type="unfinished">لا يمكن أن يكون مسار التثبيت نسبياً، يرجى تحديد مسار مطلق.</translation>
+ <translation>لا يمكن أن يكون مسار التثبيت نسبياً، يرجى تحديد مسار مطلق.</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 type="unfinished">المسار أو مجلد التثبيت لا يحتوي على محارف ASCII. هذا غير مدعوم حالياً يرجى اختيار مسار أو مجلد تثبيت مختلف.</translation>
+ <translation>المسار أو مجلد التثبيت لا يحتوي على محارف ASCII. هذا غير مدعوم حالياً يرجى اختيار مسار أو مجلد تثبيت مختلف.</translation>
</message>
<message>
<source>As the install directory is completely deleted, installing in %1 is forbidden.</source>
- <translation type="unfinished">التثبيت في %1 محظور لأن مجلد التثبيت سيُمسح تماماً.</translation>
+ <translation>التثبيت في %1 محظور لأن مجلد التثبيت سيُمسح تماماً.</translation>
</message>
<message>
<source>The path you have entered is too long, please make sure to specify a valid path.</source>
- <translation type="unfinished">المسار الذي أدخلته طويل جداً، يرجى التأكد من تخصيص مسار صالح.</translation>
+ <translation>المسار الذي أدخلته طويل جداً، يرجى التأكد من تخصيص مسار صالح.</translation>
</message>
<message>
<source>The path you have entered is not valid, please make sure to specify a valid target.</source>
- <translation type="unfinished">المسار الذي أدخلته غير صالح، يرحى التأكد من تخصيص وجهة صالحة.</translation>
+ <translation>المسار الذي أدخلته غير صالح، يرحى التأكد من تخصيص وجهة صالحة.</translation>
</message>
<message>
<source>The path you have entered is not valid, please make sure to specify a valid drive.</source>
- <translation type="unfinished">المسار الذي أدخلته غير صالح، يرحى التأكد من تخصيص قرص صالح.</translation>
+ <translation>المسار الذي أدخلته غير صالح، يرحى التأكد من تخصيص قرص صالح.</translation>
</message>
<message>
<source>The installation path must not end with &apos;.&apos;, please specify a valid directory.</source>
- <translation type="unfinished">يجب ألا ينتهي مسار التثبيت بنقطة &quot;.&quot;، يرجى تخصيص مجلد صالح.</translation>
+ <translation>يجب ألا ينتهي مسار التثبيت بنقطة &quot;.&quot;، يرجى تخصيص مجلد صالح.</translation>
</message>
<message>
<source>The installation path must not contain &quot;%1&quot;, please specify a valid directory.</source>
- <translation type="unfinished">يجب ألا يحتوي مسار التثبيت على &quot;%1&quot;، يرجى تخصيص مجلد صالح.</translation>
+ <translation>يجب ألا يحتوي مسار التثبيت على &quot;%1&quot;، يرجى تخصيص مجلد صالح.</translation>
</message>
<message>
<source>Application not running in Package Manager mode.</source>
@@ -1482,10 +1651,6 @@ Do you want to continue?</source>
<translation>لم يُعثر على حزم مثبتة.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>Application running in Uninstaller mode.</source>
<translation>يعمل التطبيق في وضع إزالة التثبيت.</translation>
</message>
@@ -1498,36 +1663,28 @@ Do you want to continue?</source>
<translation>لا يمكن الحصول على كافة الاعتماديات.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>المكونات على وشك الحذف.</translation>
+ <source>Cannot install %1. Component not found.</source>
+ <translation>المكون غير موجود.</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation type="unfinished"></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 installed only as automatic dependency to %2.
-</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>المكون غير قابل للتحقق مما يعني أنه يجب عليك تحديد أحد المكونات الفرعية.</translation>
</message>
<message>
- <source>Component %1 already installed
-</source>
- <translation type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>المكون %1 مثبت بالفعل</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation type="unfinished"></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>
- <translation type="unfinished"></translation>
+ <translation>الرجاء إعادة تشغيل التطبيق كمسؤول.</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1538,50 +1695,64 @@ Do you want to continue?</source>
<translation>خطأ</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>لا توجد مساحة كافية لتخزين الملفات المؤقتة والتثبيت! بينما المساحة المطلوبة هي %2 على الأقل، المساحة المتاحة هي %1.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store all selected components! %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 type="unfinished"></translation>
+ <translation>يبدو أن وحدة التخزين التي حددتها للتثبيت بها مساحة كافية للتثبيت، ولكن سيكون هناك أقل من 1% من مساحة وحدة التخزين المتاحة بعد ذلك.</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>يبدو أن وحدة التخزين التي حددتها للتثبيت تحتوي على مساحة كافية للتثبيت ، ولكن سيكون هناك أقل من 100 ميجابايت بعد ذلك.</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
- <translation type="unfinished">سيستخدم التثبيت %1 من مساحة القرص الصلب.</translation>
+ <translation>سيستخدم التثبيت %1 من مساحة القرص الصلب.</translation>
+ </message>
+ <message>
+ <source>Invalid</source>
+ <translation>غير صالح</translation>
+ </message>
+ <message>
+ <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>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>المكونات التالية على وشك الإزالة:</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. 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>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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>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>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>لا يمكن تحديد المكونات المطلوب إزالتها.</translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>لا يمكن تحديد %1. تم وضع علامة على الاسم المستعار افتراضيًا، مما يعني أنه لا يمكن تحديده يدويًا.</translation>
</message>
<message>
- <source>Invalid</source>
- <translation type="unfinished"></translation>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>سيستخدم المثبت الذي تم إنشاؤه %1 من مساحة القرص.</translation>
</message>
</context>
<context>
@@ -1616,7 +1787,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>تم تجاوز عدد مرات إعادة المحاولة</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
@@ -1652,23 +1823,23 @@ Do you want to continue?</source>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>كتابة قاعدة ثنائية غير متصلة بالإنترنت.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن إزالة المجلد &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation type="unfinished">لا يمكن إنشاء المجلد &quot;%1&quot;.</translation>
+ <translation>لا يمكن إنشاء المجلد &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن كتابة الملف الثنائي دون اتصال إلى &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن إزالة الملف المؤقت &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1691,16 +1862,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>
@@ -1711,53 +1878,56 @@ 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>
+ <translation>أُزيل التثبيت بنجاح.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>أُلغيت إزالة التثبيت.</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن إنشاء دليل هدف للمثبت.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>جاري تحضير الجيل غير المتصل ...</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>جاري تحضير تكوين المثبت ...</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>جاري إنشاء المثبت ...</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>فشل إنشاء برنامج التثبيت دون اتصال. %1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن إزالة المجلد المؤقت &quot;%1&quot;.</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>اكتمل الإنشاء في وضع عدم الاتصال بنجاح.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></translation>
+ <translation>تم إحباط الجيل غير المتصل!</translation>
</message>
<message>
- <source>
-Installing component %1</source>
- <translation type="unfinished"></translation>
+ <source>Installing component %1</source>
+ <translation>لا يمكن تثبيت المكون %1</translation>
</message>
<message>
<source>Installer Error</source>
@@ -1774,6 +1944,20 @@ Installing component %1</source>
<translation>انتهى</translation>
</message>
<message>
+ <source>Cannot prepare removal</source>
+ <translation>لا يمكن تحضير إزالة التثبيت</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>لا يمكن بدأ إزالة التثبيت</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>حدث خطأ أثناء عملية إزالة التثبيت :
+%1</translation>
+ </message>
+ <message>
<source>Unknown error</source>
<translation>خطأ غير معروف</translation>
</message>
@@ -1790,10 +1974,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>
@@ -1805,28 +1985,51 @@ Installing component %1</source>
<source>These processes should be stopped to continue:
%1</source>
- <translation type="unfinished"></translation>
+ <translation>يجب إيقاف هذه العمليات للمتابعة:%1</translation>
</message>
<message>
- <source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <source>Preparing to unpack components...</source>
+ <translation>جاري التحضير لتفريغ المكونات ...</translation>
</message>
<message>
- <source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations completed.</source>
+ <translation>اكتملت%1 من%2 عملية.</translation>
</message>
<message>
- <source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <source>Unpacking components...</source>
+ <translation>جاري تفريغ المكونات ...</translation>
</message>
<message>
- <source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>تم التراجع عن1% من2% عملية.</translation>
</message>
<message>
- <source>Error during removal process:
-%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1844,6 +2047,10 @@ Installing component %1</source>
<translation>هل تريد إلغاء عملية التثبيت؟</translation>
</message>
<message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>هل تريد إلغاء عملية إزالة التثبيت؟</translation>
+ </message>
+ <message>
<source>Do you want to quit the installer application?</source>
<translation>هل تريد الخروج من برنامج المثبت؟</translation>
</message>
@@ -1860,12 +2067,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 type="unfinished"></translation>
+ <translation>حدد إعدادات الوكيل وقم بتكوين المستودعات لمكونات الوظيفة الإضافية.</translation>
</message>
<message>
<source>Error</source>
@@ -1877,19 +2084,15 @@ Please copy the installer to a local drive</source>
<translation>من غير الممكن التثبيت من موقع في الشبكة
يرجى نسخ المثبت إلى فرص محلي</translation>
</message>
- <message>
- <source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></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>
@@ -1917,13 +2120,13 @@ 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>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>هناك تحديث هام متاح. الرجاء تحديد %1 أولا</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1932,6 +2135,11 @@ Please copy the installer to a local drive</source>
<translation>اتفاقية الترخيص</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>يرجى قراءة اتفاقية الترخيص الآتية. يجب أن توافق على الشروط الواردة في هذه الاتفاقية قبل متابعة التثبيت.</translation>
</message>
@@ -1947,11 +2155,6 @@ Please copy the installer to a local drive</source>
<source>I accept the licenses.</source>
<translation>أقبل الرخص.</translation>
</message>
- <message>
- <source>Alt+A</source>
- <comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
- </message>
</context>
<context>
<name>QInstaller::TargetDirectoryPage</name>
@@ -1964,22 +2167,22 @@ Please copy the installer to a local drive</source>
<translation>يرجى تخصيص مجلد تثبيت %1.</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;ستعرض...</translation>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>تصفح نظام الملفات لاختيار دليل التثبيت.</translation>
</message>
<message>
<source>Select Installation Folder</source>
<translation>اختر مجلد التثبيت</translation>
</message>
- <message>
- <source>Alt+R</source>
- <comment>Browse file system to choose a file</comment>
- <translation type="unfinished">Alt+R</translation>
- </message>
</context>
<context>
<name>QInstaller::StartMenuDirectoryPage</name>
@@ -2003,7 +2206,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>
@@ -2015,7 +2218,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>
@@ -2027,12 +2230,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2063,29 +2278,41 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>جاري التثبيت</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>جار التحديث</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
<source>Finished</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2097,14 +2324,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>
@@ -2143,14 +2370,21 @@ Please copy the installer to a local drive</source>
%1
as a user with the appropriate rights and then clicking OK.</source>
- <translation type="unfinished"></translation>
+ <translation>لا يمكن الحصول على التفويض المطلوب لمتابعة التثبيت. قم بإلغاء التثبيت أو استخدام الحل الاحتياطي عن طريق تشغيل
+
+%1
+
+كمستخدم لديه الحقوق المناسبة ثم النقر فوق &quot;موافق&quot;.</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 type="unfinished"></translation>
+ <translation>لا يمكن الحصول على التفويض المطلوب لمتابعة التثبيت.
+
+يرجى بدء برنامج الإعداد كمستخدم لديه الحقوق المناسبة ،
+أو قبول رفع حقوق الوصول إذا طُلب منك ذلك.</translation>
</message>
</context>
<context>
@@ -2164,11 +2398,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>معاملة البحث الحالية التي تستدعي &quot;%1&quot; مع معاملة البحث الفارغ غير مدعومة.</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>الرجاء استخدام string أو regex.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2205,12 +2439,12 @@ or accept the elevation of access rights if being asked.</source>
<translation>كائن المثبت المطلوب في العملية %1 فارغ.</translation>
</message>
<message>
- <source>Self Restart: Invalid arguments</source>
- <translation>إعادة التشغيل التلقائية: معاملات غير صحيحة</translation>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>إعادة التشغيل التلقائية: متاحة فقط في وضع المحدث أو وضع مدير الحزم.</translation>
</message>
<message>
- <source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>إعادة التشغيل التلقائية: معاملات غير صحيحة</translation>
</message>
</context>
<context>
@@ -2220,8 +2454,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>لا يمكن فتح ملف الإعدادات %1 للقراءة: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>حدد الاقسام</translation>
</message>
</context>
<context>
@@ -2232,7 +2466,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>معامل الدالة الحالية المستدعاة &amp;quot;%1&amp;quot; بالمعاملات &amp;quot;%2&amp;quot; غير مدعوم. يرجى استخدام set أو remove أو add_array_value أو remove_array_value.</translation>
</message>
</context>
<context>
@@ -2428,6 +2662,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>
@@ -2703,10 +2941,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>
@@ -2735,14 +2969,199 @@ or accept the elevation of access rights if being asked.</source>
<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>مطلوب إدخال المستخدم ولكن جهاز الإخراج غير مرتبط بطرف.</translation>
</message>
</context>
<context>
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>تعذر بدء المثبت</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>تعذر إنشاء معالج للأرشيف &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 extracting archive &quot;%1&quot;: %2</source>
+ <translation>حدث خطأ أثناء إستخراج الأرشيف &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</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>
+</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 7d272746b..ad80c6624 100644
--- a/src/sdk/translations/ifw_de.ts
+++ b/src/sdk/translations/ifw_de.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="de_DE">
+<TS version="2.1" language="de_DE" sourcelanguage="en_GB">
<context>
<name>AuthenticationRequiredException</name>
<message>
@@ -107,7 +107,7 @@
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>Installer konnte nicht gestartet werden</translation>
</message>
</context>
<context>
@@ -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,16 +318,20 @@
<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>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Konnte Datei &apos;%1&apos; nicht zum Lesen öffnen.</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for writing: %2</source>
- <translation>Konnte Zieldatei &apos;%1&apos; nicht zum Schreiben öffnen.</translation>
+ <translation>Konnte Zieldatei &quot;%1&quot; nicht zum Schreiben öffnen: %2</translation>
</message>
<message>
<source>Writing to file &quot;%1&quot; failed: %2</source>
@@ -349,7 +365,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%1&quot; kopieren: %3</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%2&quot; kopieren: %3</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;.</source>
@@ -486,11 +502,7 @@
</message>
<message>
<source>Cannot read &quot;%1&quot;</source>
- <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>
+ <translation>Konnte Datei &quot;%1&quot; nicht lesen</translation>
</message>
<message>
<source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
@@ -506,20 +518,28 @@
</message>
<message>
<source>PackageUpdate element without Name</source>
- <translation>Element PackageUpdate braucht ein Feld Name.</translation>
+ <translation>Element PackageUpdate braucht ein Feld Name</translation>
</message>
<message>
<source>PackageUpdate element without Version</source>
- <translation>Element PackageUpdate braucht ein Feld Version.</translation>
+ <translation>Element PackageUpdate braucht ein Feld Version</translation>
</message>
<message>
<source>PackageUpdate element without ReleaseDate</source>
- <translation>Element PackageUpdate braucht ein Feld ReleaseDate.</translation>
+ <translation>Element PackageUpdate braucht ein Feld ReleaseDate</translation>
</message>
</context>
<context>
<name>Lib7z</name>
<message>
+ <source>Internal code: %1</source>
+ <translation>Interner Fehlercode: %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>nicht genug Speicher</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Fehler: %1</translation>
</message>
@@ -541,7 +561,7 @@
</message>
<message>
<source>Cannot open archive &quot;%1&quot;.</source>
- <translation>Konnte Archiv nicht öffnen.</translation>
+ <translation>Konnte Archiv &quot;%1&quot; nicht öffnen.</translation>
</message>
<message>
<source>Cannot retrieve number of items in archive.</source>
@@ -561,11 +581,11 @@
</message>
<message>
<source>Unsupported archive type.</source>
- <translation type="unfinished"></translation>
+ <translation>Nicht unterstützter Archivtyp.</translation>
</message>
<message>
<source>Cannot create archive &quot;%1&quot;</source>
- <translation>Konnte kein Archiv &quot;%1&quot; anlegen.</translation>
+ <translation>Konnte kein Archiv &quot;%1&quot; anlegen</translation>
</message>
<message>
<source>Cannot create archive &quot;%1&quot;: %2</source>
@@ -573,23 +593,15 @@
</message>
<message>
<source>Cannot remove old archive &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Konnte altes Archiv &quot;%1&quot; nicht entfernen: %2</translation>
</message>
<message>
<source>Cannot rename temporary archive &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation type="unfinished"></translation>
+ <translation>Konnte temporäres Archiv &quot;%1&quot; nicht in &quot;%2&quot; umbenennen: %3</translation>
</message>
<message>
<source>Unknown exception caught (%1)</source>
- <translation>Unbekannte Ausnahmebedingung (%1).</translation>
- </message>
- <message>
- <source>Internal code: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not enough memory</source>
- <translation type="unfinished"></translation>
+ <translation>Unbekannter Ausnahmefehler (%1)</translation>
</message>
</context>
<context>
@@ -714,7 +726,7 @@
</message>
<message>
<source>Cannot move file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%1&quot; verschieben: %3</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%2&quot; verschieben: %3</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
@@ -734,7 +746,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%2“ kopieren.</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -742,7 +754,11 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -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>
@@ -781,11 +785,31 @@
</message>
<message>
<source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></translation>
+ <translation>Es ist ein Fehler beim Laden der ausgewählten Komponente aufgetreten. Diese Komponente kann nicht installiert werden.</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>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>
@@ -834,48 +858,52 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<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 type="unfinished"></translation>
+ <translation>Wählt die Standardkomponenten in der Baumansicht aus.</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 type="unfinished"></translation>
+ <translation>Setzt alle Komponenten in der Baumansicht auf die ursprüngliche Auswahl zurück.</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 type="unfinished"></translation>
+ <translation>Wählt alle Komponenten in der Baumansicht aus.</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 type="unfinished"></translation>
+ <translation>Wählt alle Komponenten in der Baumansicht ab.</translation>
</message>
<message>
- <source>Open File</source>
- <translation type="unfinished"></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>
- <translation type="unfinished"></translation>
+ <translation>Wählen Sie eine Qt Board Support Package-Datei, um zusätzliche Inhalte zu installieren, die nicht direkt in den Online-Repositories verfügbar sind.</translation>
+ </message>
+ <message>
+ <source>Filter the enabled repository categories</source>
+ <translation>Filtert die aktivierten Repository-Kategorien</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -898,58 +926,54 @@
<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>
+ <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>Mandatory components need to be updated first before you can select other components to update.</source>
- <translation type="unfinished"></translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Durchsuche QBSP Dateien</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Select</source>
+ <translation>Auswählen</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished"></translation>
+ <source>Error</source>
+ <translation>Fehler</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Create Offline Installer</source>
+ <translation>Offline-Installer Erstellen</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+B</translation>
+ <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>Filter the enabled repository categories</source>
- <translation type="unfinished"></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>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>
<message>
<source>Filter</source>
- <translation type="unfinished"></translation>
+ <translation>Filtern</translation>
</message>
<message>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Informationen</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 type="unfinished"></translation>
+ <translation>&lt;Zu speichernder Installer-Schlüsselname&gt; &lt;ausführbare Datei&gt; [Argument1] [Argument2] [...]</translation>
</message>
<message>
<source>Needed installer object in %1 operation is empty.</source>
@@ -960,27 +984,23 @@
<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>
<name>QInstaller::CopyDirectoryOperation</name>
<message>
<source>&lt;source&gt; &lt;target&gt; [&quot;forceOverwrite&quot;]</source>
- <translation> (&lt;Quelle&gt; &lt;Ziel&gt; [forceOverwrite])</translation>
+ <translation>(&lt;Quelle&gt; &lt;Ziel&gt; [forceOverwrite])</translation>
</message>
<message>
<source>Invalid argument in %1: Third argument needs to be forceOverwrite, if specified.</source>
- <translation>Ungültiges Argument in %1: Drittes Argument muss forceOverwrite sein, wenn es angegeben wird</translation>
+ <translation>Ungültiges Argument in %1: Drittes Argument muss forceOverwrite sein, wenn es angegeben wird.</translation>
</message>
<message>
<source>Invalid argument in %1: Directory &quot;%2&quot; is invalid.</source>
- <translation type="unfinished"></translation>
+ <translation>Ungültiges Argument in %1: Verzeichnis &quot;%2&quot; ist ungültig.</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
@@ -988,11 +1008,11 @@
</message>
<message>
<source>Failed to overwrite &quot;%1&quot;.</source>
- <translation>Konnte Datei &quot;%1&quot; nicht überschreiben</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht überschreiben.</translation>
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation>Konnte &quot;%1&quot; nicht nach &quot;%1&quot; kopieren: %3</translation>
+ <translation>Konnte &quot;%1&quot; nicht nach &quot;%2&quot; kopieren: %3</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;.</source>
@@ -1007,15 +1027,15 @@
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Konnte Quelle &apos;%1&apos; nicht zum Lesen öffnen: %2.</translation>
+ <translation>Konnte Quelle &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for writing: %2</source>
- <translation>Konnte Ziel &apos;%1&apos; nicht zum Schreiben öffnen: %2.</translation>
+ <translation>Konnte Ziel &quot;%1&quot; nicht zum Schreiben öffnen: %2</translation>
</message>
<message>
<source>Writing to file &quot;%1&quot; failed: %2</source>
- <translation>Konnte Datei &apos;%1&apos; nicht zum Schreiben öffnen: %2</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Schreiben öffnen: %2</translation>
</message>
</context>
<context>
@@ -1037,11 +1057,11 @@
<name>QInstaller::CreateLinkOperation</name>
<message>
<source>Cannot create link from &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation>Konnte keinen Link von &quot;%1&quot; nach &quot;%1&quot; erstellen.</translation>
+ <translation>Konnte keinen Link von &quot;%1&quot; nach &quot;%2&quot; erstellen.</translation>
</message>
<message>
<source>Cannot remove link from &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation>Konnte Link von &quot;%1&quot; nach &quot;%1&quot; nicht entfernen.</translation>
+ <translation>Konnte Link von &quot;%1&quot; nach &quot;%2&quot; nicht entfernen.</translation>
</message>
</context>
<context>
@@ -1055,8 +1075,12 @@
<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;%1&quot; verschieben: %3</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht nach &quot;%2&quot; verschieben: %3</translation>
</message>
<message>
<source>Installer at &quot;%1&quot; needs to be an offline one.</source>
@@ -1064,11 +1088,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Konnte Pfad &quot;%1&quot; nicht erstellen.</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Konnte Verzeichnis &quot;%1&quot; nicht entfernen.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1088,26 +1112,30 @@
</message>
<message>
<source>Unknown exception caught: %1.</source>
- <translation>Unbekannte Ausnahmebedingung: %1</translation>
+ <translation>Unbekannter Ausnahmefehler: %1.</translation>
</message>
<message>
<source>Removing file &quot;%1&quot;.</source>
- <translation>Datei %0 wird entfernt</translation>
+ <translation>Datei %1 wird entfernt.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;.</source>
- <translation>Konnte Datei %0 nicht löschen.</translation>
+ <translation>Konnte Datei %1 nicht löschen.</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Konnte Verzeichnis &quot;%1&quot; nicht löschen: %2</translation>
</message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>Konnte kein Archiv &quot;%1&quot; anlegen: %2</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 type="unfinished"></translation>
+ <translation>&lt;Ziel&gt; &lt;Link Location&gt; [Zielargumente] [&quot;workingDirectory=...&quot;] [&quot;iconPath=...&quot;] [&quot;iconId=...&quot;] [&quot;description=...&quot;]</translation>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
@@ -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>
@@ -1166,6 +1186,80 @@ Fehler beim Laden von %2</translation>
<source>Cannot find component for %1.</source>
<translation>Konnte keine Komponente für Datei %1 finden.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 von %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 heruntergeladen.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n Tag, </numerusform>
+ <numerusform>%n Tage, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n Stunde, </numerusform>
+ <numerusform>%n Stunden, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n Minute</numerusform>
+ <numerusform>%n Minuten</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n Sekunde</numerusform>
+ <numerusform>%n Sekunden</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 verbleibend.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - verbleibende Zeit unbekannt.</translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation>Total: </translation>
+ </message>
+ <message>
+ <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>
@@ -1181,12 +1275,12 @@ Fehler beim Laden von %2</translation>
<message>
<source>File &quot;%1&quot; not open for writing: %2</source>
<extracomment>%2 is a sentence describing the error.</extracomment>
- <translation>Datei konnte nicht zum Schreiben geöffnet werden.</translation>
+ <translation>Datei %1 ist nicht zum Schreiben geöffnet: %2</translation>
</message>
<message>
<source>Writing to file &quot;%1&quot; failed: %2</source>
<extracomment>%2 is a sentence describing the error.</extracomment>
- <translation>Schreiben in Datei &apos;%1&apos; fehlgeschlagen: %2.</translation>
+ <translation>Schreiben in Datei &quot;%1&quot; fehlgeschlagen: %2</translation>
</message>
<message>
<source>Redirect loop detected for &quot;%1&quot;.</source>
@@ -1212,14 +1306,14 @@ Fehler beim Laden von %2</translation>
<message>
<source>Invalid source URL &quot;%1&quot;: %2</source>
<extracomment>%2 is a sentence describing the error</extracomment>
- <translation>Ungültige Quelle &apos;%1&apos;. Fehler: %2.</translation>
+ <translation>Ungültige Quelle &quot;%1&quot;. Fehler: %2</translation>
</message>
</context>
<context>
<name>QInstaller::ElevatedExecuteOperation</name>
<message>
<source>Cannot start detached: &quot;%1&quot;</source>
- <translation>Konnte &quot;%1&quot; nicht losgelöst starten.</translation>
+ <translation>Konnte &quot;%1&quot; nicht im Hintergrund starten</translation>
</message>
<message>
<source>Cannot start: &quot;%1&quot;: %2</source>
@@ -1231,29 +1325,30 @@ Fehler beim Laden von %2</translation>
</message>
<message>
<source>Execution failed (Unexpected exit code: %1): &quot;%2&quot;</source>
- <translation type="unfinished"></translation>
+ <translation>Ausführung fehlgeschlagen (Unerwarteter Exit-Code: %1): &quot;%2&quot;</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation</name>
<message>
<source>Extracting &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <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>
-</context>
-<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
<message>
<source>Cannot open archive &quot;%1&quot; for reading: %2</source>
- <translation>Konnte Datei &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
+ <translation>Konnte Archiv &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Fehler beim Auspacken von &apos;%1&apos;: %2</translation>
+ <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>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Beim Auspacken von &quot;%1&quot; ist eine unbekannte Ausnahmebedingung aufgetreten.</translation>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Lösche von &quot;%1&quot; ausgepackte Dateien</translation>
</message>
</context>
<context>
@@ -1325,15 +1420,15 @@ Fehler beim Laden von %2</translation>
<context>
<name>QInstaller::FinishedPage</name>
<message>
- <source>Completing the %1 Wizard</source>
- <translation>Den %1-Assistent abschließen.</translation>
+ <source>Finished the %1 Setup</source>
+ <translation>Den %1-Assistent abschließen</translation>
</message>
<message>
<source>Finished</source>
<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>
@@ -1345,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>
@@ -1364,13 +1459,17 @@ Fehler beim Laden von %2</translation>
<name>QInstaller::InstallIconsOperation</name>
<message>
<source>&lt;source path&gt; [vendor prefix]</source>
- <translation> (Quellpfad, [Vendorprefix])</translation>
+ <translation>(Quellpfad, [Vendorprefix])</translation>
</message>
<message>
<source>Invalid Argument: source directory must not be empty.</source>
<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>
@@ -1390,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>
@@ -1422,13 +1521,13 @@ 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>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>Es gibt eine wichtige Aktualisierung. Bitte wählen Sie zuerst &apos;%1&apos; aus</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1437,6 +1536,12 @@ Fehler beim Laden von %2</translation>
<translation>Lizenzabkommen</translation>
</message>
<message>
+ <source>Alt+A</source>
+ <comment>Agree license</comment>
+ <translatorcomment>Lizenz akzeptieren</translatorcomment>
+ <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>Bitte lesen Sie das folgende Lizenzabkommen. Sie müssen die Bedingungen in diesem Abkommen akzeptieren, um die Installation fortsetzen zu können.</translation>
</message>
@@ -1452,11 +1557,6 @@ Fehler beim Laden von %2</translation>
<source>I accept the licenses.</source>
<translation>Ich akzeptiere die Lizenzvereinbarungen.</translation>
</message>
- <message>
- <source>Alt+A</source>
- <comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
- </message>
</context>
<context>
<name>QInstaller::LicenseOperation</name>
@@ -1472,24 +1572,20 @@ 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>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>Ungültiges Argument in %1: Leeres Suchargument wird nicht unterstützt.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Konnte Datei &apos;%1&apos; nicht zum Lesen öffnen.</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for writing: %2</source>
- <translation>Konnte Datei &apos;%1&apos; nicht zum Schreiben öffnen.</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Schreiben öffnen: %2</translation>
</message>
</context>
<context>
@@ -1499,14 +1595,14 @@ 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>
<message>
+ <source>Metadata download canceled.</source>
+ <translation>Herunterladen der Metainformationen abgebrochen.</translation>
+ </message>
+ <message>
<source>Unknown exception during extracting.</source>
<translation>Beim Auspacken ist eine unbekannte Ausnahmebedingung aufgetreten.</translation>
</message>
@@ -1535,28 +1631,51 @@ 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>
+ <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>Retrieving meta information from remote repository... </source>
- <translation>Metainformationen werden vom Installationsserver empfangen ... </translation>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Fehler beim Auspacken des Archives &quot;%1&quot;: %2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Fehler beim auspacken des Archives &quot;%1&quot;:</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>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Beim Auspacken von &quot;%1&quot; ist eine unbekannte Ausnahmebedingung aufgetreten.</translation>
+ <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>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Kann die Datei &quot;%1&quot; nicht zum Lesen öffnen: %2</translation>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Unbekannte Ausnahmebedingung beim Aktualisieren des Caches</translation>
</message>
<message>
- <source>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1566,26 +1685,28 @@ 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>
- <translation>Installation durch den Benutzer abgebrochen</translation>
+ <translation>Installation durch den Benutzer abgebrochen.</translation>
</message>
<message>
<source>All downloads finished.</source>
<translation>Alle Herunterladeprozesse abgeschlossen.</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation>Der Installationsvorgang wird abgebrochen</translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>Autentifizierungsfehler</translation>
</message>
<message>
<source>Some components could not be removed completely because administrative rights could not be acquired: %1.</source>
- <translation>Einige Komponenten konnten nicht vollständig entfernt werden, weil die nötigen Administratorrechte nicht erlangt werden konnten: %1</translation>
+ <translation>Einige Komponenten konnten nicht vollständig entfernt werden, weil die nötigen Administratorrechte nicht erlangt werden konnten: %1.</translation>
</message>
<message>
<source>Unknown error.</source>
@@ -1597,7 +1718,7 @@ Pakete werden heruntergeladen ...</translation>
</message>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>Eine Benutzereingabe ist erforderlich, aber das Ausgabegerät ist nicht mit einem Terminal verbunden.</translation>
</message>
<message>
<source>The directory you selected already exists and contains an installation. Choose a different target for installation.</source>
@@ -1655,7 +1776,7 @@ Möchten Sie trotzdem fortsetzen?</translation>
</message>
<message>
<source>The installation path must not contain &quot;%1&quot;, please specify a valid directory.</source>
- <translation>Der Installationspfad darf nicht &quot;%1&quot; enthalten, bitte geben Sie einen gültigen Verzeichnis ein.</translation>
+ <translation>Der Installationspfad darf nicht &quot;%1&quot; enthalten, bitte geben Sie ein gültiges Verzeichnis an.</translation>
</message>
<message>
<source>Application not running in Package Manager mode.</source>
@@ -1666,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 type="unfinished"></translation>
- </message>
- <message>
<source>Application running in Uninstaller mode.</source>
<translation>Die Anwendung läuft im Deinstallationsmodus.</translation>
</message>
@@ -1682,36 +1799,28 @@ 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>
+ <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 installed only as automatic dependency to %2.
-</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>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 type="unfinished"></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 type="unfinished"></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 type="unfinished"></translation>
- </message>
- <message>
- <source>Running processes found.</source>
- <translation type="unfinished"></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>
- <translation type="unfinished"></translation>
+ <translation>Bei der Ausführung über die Befehlszeile konnten die Zugriffsrechte nicht erhöht werden. Bitte starten Sie die Anwendung als Administrator neu.</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1722,50 +1831,64 @@ Möchten Sie trotzdem fortsetzen?</translation>
<translation>Fehler</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>Nicht genügend Festplattenplatz für temporäre Dateien und die Installation! Verfügbarer Platz: %1, mindestens benötigt: %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>Nicht genügend Festplattenplatz für alle ausgewählten Komponenten! 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 type="unfinished"></translation>
+ <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>
<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>Das für die Installation ausgewählte Laufwerk scheint über genügend Speicherplatz für die Installation zu verfügen, aber anschließend sind weniger als 100&#xa0;MB verfügbar.</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
<translation>Die Installation wird %1 Festplattenplatz verwenden.</translation>
</message>
<message>
+ <source>Invalid</source>
+ <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>
+ </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>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>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>Zu löschende Komponenten:</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. 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>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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>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>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Die zu deinstallierenden Komponenten konnten nicht aufgelöst werden.</translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Invalid</source>
- <translation type="unfinished"></translation>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>Der erstellte Installer wird %1 Festplattenplatz verwenden.</translation>
</message>
</context>
<context>
@@ -1844,7 +1967,7 @@ Möchten Sie trotzdem fortsetzen?</translation>
</message>
<message>
<source>Creating Maintenance Tool</source>
- <translation></translation>
+ <translation>Wartungstool wird erstellt.</translation>
</message>
<message>
<source>These processes should be stopped to continue:
@@ -1856,15 +1979,15 @@ Möchten Sie trotzdem fortsetzen?</translation>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>Anzahl der Wiederholungsversuche überschritten</translation>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Temporäre Datendatei &quot;%1&quot; konnte nicht entfernt werden: %2</translation>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>Offline-Basis-Binary wird geschrieben.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1876,23 +1999,19 @@ Möchten Sie trotzdem fortsetzen?</translation>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Offline-Binary konnte nicht in &quot;%1&quot; geschrieben werden: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></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>
@@ -1903,54 +2022,56 @@ 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>
+ <translation>Deinstallation erfolgreich abgeschlossen.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>Deinstallation abgebrochen.</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>Das Zielverzeichnis für den Installer konnte nicht erstellt werden.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>Offline-Generierung wird vorbereitet...</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>Konfiguration des Installers wird vorbereitet...</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>Installer wird vorbereitet...</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>Offline-Installer konnte nicht erstellt werden. %1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Temporäres Verzeichnis &quot;%1&quot; konnte nicht entfernt werden.</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>Offline-Generierung erfolgreich abgeschlossen.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></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>
@@ -1964,7 +2085,21 @@ Komponente %1 wird installiert</translation>
</message>
<message>
<source>Done</source>
- <translation type="unfinished"></translation>
+ <translation>Fertig</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>Kann Deinstallation nicht vorbereiten</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>Kann Deinstallation nicht starten</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>Fehler bei der Deinstallation:
+%1</translation>
</message>
<message>
<source>Unknown error</source>
@@ -1972,21 +2107,17 @@ Komponente %1 wird installiert</translation>
</message>
<message>
<source>Cannot retrieve remote tree %1.</source>
- <translation>Kann entfernten Baum nicht empfangen %1</translation>
+ <translation>Kann entfernten Baum nicht empfangen %1.</translation>
</message>
<message>
<source>Failure to read packages from %1.</source>
- <translation>Fehler beim Lesen der Pakete von %1</translation>
+ <translation>Fehler beim Lesen der Pakete von %1.</translation>
</message>
<message>
<source>Cannot retrieve meta information: %1</source>
<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>
@@ -1995,25 +2126,48 @@ Komponente %1 wird installiert</translation>
<translation>Zyklische Abhängigkeit zwischen Komponenten entdeckt: &apos;%1&apos; und &apos;%2&apos;.</translation>
</message>
<message>
- <source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <source>Preparing to unpack components...</source>
+ <translation>Bereite Auspacken der Komponenten vor...</translation>
</message>
<message>
- <source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%1 von %2 Schritten fertiggestellt.</translation>
</message>
<message>
- <source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <source>Unpacking components...</source>
+ <translation>Packe Komponenten aus...</translation>
</message>
<message>
- <source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 von %2 Schritten rückgängig gemacht.</translation>
</message>
<message>
- <source>Error during removal process:
-%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2031,6 +2185,10 @@ Komponente %1 wird installiert</translation>
<translation>Möchten Sie den Installationsprozess abbrechen?</translation>
</message>
<message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>Möchten Sie den Deinstallationsprozess abbrechen?</translation>
+ </message>
+ <message>
<source>Do you want to quit the installer application?</source>
<translation>Möchten Sie die Installationsanwendung beenden?</translation>
</message>
@@ -2047,12 +2205,12 @@ Komponente %1 wird installiert</translation>
<translation>%1 Frage</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
<source>Specify proxy settings and configure repositories for add-on components.</source>
- <translation type="unfinished"></translation>
+ <translation>Geben Sie Proxy-Einstellungen an und konfigurieren Sie Repositories für Zusatzkomponenten.</translation>
</message>
<message>
<source>Error</source>
@@ -2064,10 +2222,6 @@ Please copy the installer to a local drive</source>
<translation>Es ist nicht möglich, von einem Netzwerk-Speicherort aus zu installieren.
Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
- <message>
- <source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>QInstaller::PerformInstallationForm</name>
@@ -2112,11 +2266,23 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>Wird aktualisiert</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2147,14 +2313,14 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
<message>
<source>Proxy Credentials</source>
- <translation type="unfinished"></translation>
+ <translation>Proxy-Anmeldedaten</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>Eine Benutzereingabe ist erforderlich, aber das Ausgabegerät ist nicht mit einem Terminal verbunden.</translation>
</message>
</context>
<context>
@@ -2168,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>
@@ -2180,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>
@@ -2192,12 +2358,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2222,19 +2400,19 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<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>Beim aktuellen Suchargument ist der Aufruf von &quot;%1&quot; mit leerem Suchargument nicht unterstützt.</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>Beim aktuellen Modus ist der Aufruf von &quot;%1&quot; mit den Argumenten &quot;%2&quot; nicht unterstützt. Bitte Zeichenkette oder regulären Ausdruck verwenden.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Konnte Datei &quot;%1&quot; nicht zum Lesen öffnen</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Lesen öffnen: %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</translation>
+ <translation>Konnte Datei &quot;%1&quot; nicht zum Schreiben öffnen: %2</translation>
</message>
</context>
<context>
@@ -2255,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>
@@ -2275,7 +2453,7 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
<message>
<source>on line number: </source>
- <translation type="unfinished"></translation>
+ <translation>in Zeile: </translation>
</message>
</context>
<context>
@@ -2285,12 +2463,12 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<translation>Das für die Anweisung &apos;%1&apos; benötigte Installer-Objekt ist leer.</translation>
</message>
<message>
- <source>Self Restart: Invalid arguments</source>
- <translation>Automatischer Neustart: Ungültige Argumente</translation>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>Automatischer Neustart: Nur im Aktualisierungs- und Pakatverwaltungs-Modus erlaubt.</translation>
</message>
<message>
- <source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>Automatischer Neustart: Ungültige Argumente</translation>
</message>
</context>
<context>
@@ -2324,7 +2502,7 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</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 type="unfinished"></translation>
+ <translation>Aufruf von &quot;%1&quot; mit den Argumenten &quot;%2&quot; nicht unterstützt. Bitte set, remove, add_array_value; oder remove_array_value verwenden.</translation>
</message>
</context>
<context>
@@ -2368,21 +2546,22 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
<translation>Bitte geben Sie das Verzeichnis an, in dem %1 installiert werden soll.</translation>
</message>
<message>
+ <source>Alt+R</source>
+ <comment>Browse file system to choose a file</comment>
+ <translatorcomment>Dateisystem durchsuchen, um eine Datei auszuwählen</translatorcomment>
+ <translation>Alt+D</translation>
+ </message>
+ <message>
<source>B&amp;rowse...</source>
<translation>&amp;Durchsuchen ...</translation>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>Installationsverzeichnis vom Dateisystem auswählen.</translation>
</message>
<message>
<source>Select Installation Folder</source>
- <translation>Installationsordner auswählen.</translation>
- </message>
- <message>
- <source>Alt+R</source>
- <comment>Browse file system to choose a file</comment>
- <translation type="unfinished"></translation>
+ <translation>Installationsordner auswählen</translation>
</message>
</context>
<context>
@@ -2401,15 +2580,15 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
<message>
<source>Timeout while testing repository &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Zeitüberschreitung beim Testen des Repositorys &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot parse Updates.xml: %1</source>
- <translation>Ungültiges Format der Updates.xml: %1.</translation>
+ <translation>Ungültiges Format der Updates.xml: %1</translation>
</message>
<message>
<source>Cannot open Updates.xml for reading: %1</source>
- <translation>Konnte Updates.xml nicht zum Lesen öffnen.</translation>
+ <translation>Konnte Updates.xml nicht zum Lesen öffnen: %1</translation>
</message>
<message>
<source>Authentication failed.</source>
@@ -2417,46 +2596,46 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
<message>
<source>Unknown error while testing repository &quot;%1&quot;.</source>
- <translation>Unbekannte Fehler beim Testen des Repository &quot;%1&quot;</translation>
+ <translation>Unbekannte Fehler beim Testen des Repository &quot;%1&quot;.</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>Error acquiring admin rights</source>
- <translation>Fehler beim Erlangen von Administratorrechten.</translation>
+ <translation>Fehler beim Erlangen von Administratorrechten</translation>
</message>
<message>
<source>Another %1 instance is already running. Wait until it finishes, close it, or restart your system.</source>
- <translation type="unfinished"></translation>
+ <translation>Eine weitere %1 Instanz wird bereits ausgeführt. Warten Sie, bis diese beendet ist, schließen Sie sie oder starten Sie Ihr System neu.</translation>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>Installer-Binary kann nicht als Updater gestartet werden.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>Installer-Binary kann nicht als Paketmanager gestartet werden.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>Installer-Binary kann nicht als Uninstaller gestartet werden.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Leere Repository-Liste für Option &apos;addRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Leere Repository-Liste für Option &apos;addTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Leere Repository-Liste für Option &apos;setTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Leere Repository-Liste für Option &apos;installCompressedRepository&apos;.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2464,19 +2643,27 @@ Bitte kopieren Sie den Installer auf ein lokales Laufwerk</translation>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>Argumente fehlen für Option %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>Ungültiger Button-Wert %1 </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>Falsche Argumente für %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 type="unfinished"></translation>
+ <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>
@@ -2504,7 +2691,7 @@ als root aufrufen und dann &quot;Ok&quot; auswählen.</translation>
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>Konnte die Autorisierung, die zur Fortsetzung der Installation nötig ist, nicht erhalten. Bitte starten Sie das Setup-Programm als Benutzer mit entsprechenden Rechten. Oder akzeptieren Sie die Anhebung der Zugriffsrechte, wenn die Aufforderung erscheint.</translation>
</message>
</context>
<context>
@@ -2521,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 type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>Kategorien</translation>
</message>
</context>
<context>
@@ -2600,6 +2787,10 @@ or accept the elevation of access rights if being asked.</source>
<translation>Passwort eintragen, um sich gegenüber der Quelle zu authentifizieren.</translation>
</message>
<message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>Adresse angeben, die auf eine gültige Quelle zeigt.</translation>
+ </message>
+ <message>
<source>An error occurred while testing this repository.</source>
<translation>Beim Testen der Quelle ist ein Fehler aufgetreten.</translation>
</message>
@@ -2656,8 +2847,28 @@ or accept the elevation of access rights if being asked.</source>
<translation>Alle abwählen</translation>
</message>
<message>
- <source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2709,4 +2920,189 @@ or accept the elevation of access rights if being asked.</source>
<translation>Verbleibende Datei &quot;%1&quot; wegen &quot;%2&quot;: %3</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>Es konnte kein Handler-Objekt für das Archiv &quot;%1&quot; erstellt werden: &quot;%2&quot;.</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 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 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>
+</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 3ad9e4646..69369064f 100644
--- a/src/sdk/translations/ifw_es.ts
+++ b/src/sdk/translations/ifw_es.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="es">
+<TS version="2.1" language="es_ES" sourcelanguage="en_GB">
<context>
<name>AuthenticationRequiredException</name>
<message>
@@ -84,7 +84,7 @@
</message>
<message>
<source>Cannot remove already existing symlink %1.</source>
- <translation>No se puede quitar el symlink existente %1.</translation>
+ <translation>No se puede quitar el enlace simbólico existente %1.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for writing: %2</source>
@@ -92,22 +92,22 @@
</message>
<message>
<source>Cannot create symlink at &quot;%1&quot;. Another one is already existing.</source>
- <translation>No se puede crear el symlink en &quot;%1&quot;. Ya existe otro.</translation>
+ <translation>No se puede crear el enlace simbólico en &quot;%1&quot;. Ya existe otro.</translation>
</message>
<message>
<source>Cannot read symlink target from file &quot;%1&quot;.</source>
- <translation>No se puede leer el destino del symlink en el archivo &quot;%1&quot;.</translation>
+ <translation>No se puede leer el destino del enlace simbólico en el archivo &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot create symlink at %1: %2</source>
- <translation>No se puede crear el symlink en %1: %2</translation>
+ <translation>No se puede crear el enlace simbólico en %1: %2</translation>
</message>
</context>
<context>
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede iniciar el instalador</translation>
</message>
</context>
<context>
@@ -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>
@@ -235,28 +247,28 @@
<source>%n day(s), </source>
<translation>
<numerusform>%n día(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n día(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s), </source>
<translation>
<numerusform>%n hora(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n hora(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation>
<numerusform>%n minuto(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n minuto(s)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n second(s)</source>
<translation>
<numerusform>%n segundo(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n segundo(s)</numerusform>
</translation>
</message>
<message>
@@ -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>
@@ -454,7 +470,7 @@
<source>%n update(s) found.</source>
<translation>
<numerusform>%n actualizaciones encontradas.</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n actualizaciones encontradas.</numerusform>
</translation>
</message>
<message>
@@ -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>
@@ -520,6 +532,14 @@
<context>
<name>Lib7z</name>
<message>
+ <source>Internal code: %1</source>
+ <translation>código interno: %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>no hay suficiente memoria</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Error: %1</translation>
</message>
@@ -583,14 +603,6 @@
<source>Unknown exception caught (%1)</source>
<translation>Se ha producido una excepción desconocida (%1)</translation>
</message>
- <message>
- <source>Internal code: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not enough memory</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>LocalPackageHub</name>
@@ -734,7 +746,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede copiar el archivo &quot;%1&quot; a &quot;%2&quot;.</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -742,7 +754,11 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -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>
@@ -781,11 +785,31 @@
</message>
<message>
<source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></translation>
+ <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>There was an error loading the selected component. This component cannot be updated.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -834,44 +858,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<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 type="unfinished"></translation>
+ <translation>Selecciona los componentes predeterminados en la vista de árbol.</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 type="unfinished"></translation>
+ <translation>Restablece todos los componentes a su estado de selección original en la vista de árbol.</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 type="unfinished"></translation>
+ <translation>Selecciona todos los componentes en la vista de árbol.</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 type="unfinished"></translation>
+ <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>
+ <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>
<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>
+ <source>Filter the enabled repository categories</source>
+ <translation>Filtra las categorías de repositorio habilitadas para la selección</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -898,36 +922,36 @@
<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 type="unfinished"></translation>
+ <translation>Los componentes obligatorios deben actualizarse primero antes de poder seleccionar otros componentes para actualizarlos.</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Search</source>
+ <translation>Buscar</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Examinar archivos &amp;QBSP</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Select</source>
+ <translation>Seleccionar</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Error</source>
+ <translation>Error</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -945,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>
@@ -1049,11 +1069,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede crear la ruta &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede quitar el directorio &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1087,6 +1107,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>No se puede eliminar el directorio &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <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>
@@ -1122,14 +1150,6 @@
<translation>Error de descarga</translation>
</message>
<message>
- <source>Hash verification while downloading failed. This is a temporary error, please retry.</source>
- <translation>Error de verificación del hash durante la descarga. Es un error temporal, vuelva a intentarlo.</translation>
- </message>
- <message>
- <source>Cannot verify Hash</source>
- <translation>No se puede verificar el hash</translation>
- </message>
- <message>
<source>Cannot download archive %1: %2</source>
<translation>No se puede descargar el archivo %1: %2</translation>
</message>
@@ -1151,6 +1171,80 @@ Error al descargar %2</translation>
<source>Cannot find component for %1.</source>
<translation>No se puede encontrar el componente para %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 de %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 descargado.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n día(s), </numerusform>
+ <numerusform>%n día(s), </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n hora(s), </numerusform>
+ <numerusform>%n hora(s), </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuto(s)</numerusform>
+ <numerusform>%n minuto(s)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n segundo(s)</numerusform>
+ <numerusform>%n segundo(s)</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 restante.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - tiempo restante desconocido.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>Archivo: </translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation>Total: </translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>Se superó el recuento de reintentos (%1)</translation>
+ </message>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.
+
+Expected: %1
+Downloaded: %2</source>
+ <translation>Error de verificación del hash durante la descarga. Es un error temporal, vuelva a intentarlo.
+
+Esperados: %1
+Descargado: %2</translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash
+Expected: %1
+Downloaded: %2</source>
+ <translation>No se puede verificar el hash
+Esperados: %1
+Descargado: %2</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1220,21 +1314,6 @@ Error al descargar %2</translation>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <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 extracting archive &quot;%1&quot;: %2</source>
- <translation>Error al extraer el archivo &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Se ha producido una excepción desconocida al extraer &quot;%1&quot;.</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1267,28 +1346,28 @@ Error al descargar %2</translation>
<source>%n day(s), </source>
<translation>
<numerusform>%n día(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n día(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s), </source>
<translation>
<numerusform>%n hora(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n hora(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation>
<numerusform>%n minuto(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n minuto(s)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n second(s)</source>
<translation>
<numerusform>%n segundo(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n segundo(s)</numerusform>
</translation>
</message>
<message>
@@ -1303,15 +1382,15 @@ 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>
<source>Finished</source>
- <translation type="unfinished"></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>
@@ -1323,7 +1402,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>
@@ -1364,15 +1443,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>
@@ -1400,13 +1483,13 @@ 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>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>Hay una actualización importante disponible. Por favor seleccione &apos;%1&apos; primero</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1415,6 +1498,11 @@ Error al descargar %2</translation>
<translation>Contrato de licencia</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>Lea el siguiente contrato de licencia. Debe aceptar los términos contenidos en este contrato antes de continuar con la instalación.</translation>
</message>
@@ -1430,11 +1518,6 @@ Error al descargar %2</translation>
<source>I accept the licenses.</source>
<translation>Acepto las licencias.</translation>
</message>
- <message>
- <source>Alt+A</source>
- <comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
- </message>
</context>
<context>
<name>QInstaller::LicenseOperation</name>
@@ -1450,16 +1533,12 @@ 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>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>Argumento inválido en %1: No se admite el argumento de búsqueda vacío.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1477,14 +1556,14 @@ 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>
<message>
+ <source>Metadata download canceled.</source>
+ <translation>Descarga de metadatos cancelada.</translation>
+ </message>
+ <message>
<source>Unknown exception during extracting.</source>
<translation>Se ha producido una excepción durante la extracción.</translation>
</message>
@@ -1513,28 +1592,51 @@ 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>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Error al extraer el archivo &quot;%1&quot;: %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>Retrieving meta information from remote repository... </source>
- <translation>Recuperando información de metadatos del repositorio remoto... </translation>
+ <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>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Error al extraer el archivo &quot;%1&quot;: %2</translation>
+ <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>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Se ha producido una excepción desconocida al extraer el archivo &quot;%1&quot;.</translation>
+ <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>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>
+ <source>Unknown exception during updating cache.</source>
+ <translation>Excepción desconocida durante la actualización de caché.</translation>
</message>
<message>
- <source>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1544,10 +1646,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>
@@ -1558,6 +1658,10 @@ Descargando paquetes...</translation>
<translation>Se han completado todas las descargas.</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation>Cancelando el instalador</translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>Error de autenticación</translation>
</message>
@@ -1652,36 +1756,28 @@ 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>
+ <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 installed only as automatic dependency to %2.
-</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>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>Component %1 already installed
-</source>
- <translation type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>El componente %1 ya está instalado</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>No se puede instalar %1. El componente es virtual.</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>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>
- <translation type="unfinished"></translation>
+ <translation>No se pueden elevar los derechos de acceso mientras se ejecuta desde la línea de comandos. Por favor, reinicie la aplicación como administrador.</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1692,58 +1788,68 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
<translation>Error</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>No hay suficiente espacio en disco para almacenar los archivos temporales y la instalación. Se dispone de %1 y se requiere al menos un espacio de %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>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>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>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>
<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>El volumen seleccionado para la instalación parece tener espacio suficiente para la instalación, pero después habrá menos de 100&#xa0;MB disponibles.</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
<translation>La instalación usará %1 de espacio de disco.</translation>
</message>
<message>
+ <source>Invalid</source>
+ <translation>no válido</translation>
+ </message>
+ <message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <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 type="unfinished"></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 type="unfinished"></translation>
+ <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>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>Componentes a punto de ser removidos:</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. 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>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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>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>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>No se pueden resolver los componentes para desinstalar.</translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Invalid</source>
- <translation type="unfinished"></translation>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>El instalador creado utilizará %1 del espacio en disco.</translation>
</message>
</context>
<context>
@@ -1786,7 +1892,7 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>Recuento de intentos superado</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
@@ -1814,7 +1920,7 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede eliminar el archivo de datos temporal &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1822,7 +1928,7 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>Escritura del binario base fuera de línea.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1834,11 +1940,11 @@ No es recomendable instalar en este directorio, ya que la instalación podría g
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede escribir el binario fuera de línea en &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede eliminar el archivo temporal &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1861,16 +1967,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>
@@ -1881,54 +1983,56 @@ 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>
+ <translation>La desinstalación se ha completado correctamente.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>Desinstalación cancelada.</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede crear el directorio de destino para el instalador.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>Preparando la generación fuera de línea...</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>Preparando la configuración del instalador...</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>Creando el instalador...</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>No se ha podido crear el instalador fuera de línea. %1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede eliminar el directorio temporal &quot;%1&quot;:</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>Generación fuera de línea completada con éxito.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></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>
@@ -1942,7 +2046,21 @@ Instalando componente %1</translation>
</message>
<message>
<source>Done</source>
- <translation type="unfinished"></translation>
+ <translation>Completado</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>No se puede preparar la desinstalación</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>No se puede iniciar la desinstalación</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>Error durante el proceso de desinstalación:
+%1</translation>
</message>
<message>
<source>Unknown error</source>
@@ -1961,10 +2079,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>
@@ -1973,25 +2087,48 @@ Instalando componente %1</translation>
<translation>Se ha detectado un ciclo de dependencia entre componentes los &quot;%1&quot; y &quot;%2&quot;.</translation>
</message>
<message>
- <source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <source>Preparing to unpack components...</source>
+ <translation>Preparándose para desempaquetar componentes...</translation>
</message>
<message>
- <source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%1 de %2 operaciones completadas.</translation>
</message>
<message>
- <source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <source>Unpacking components...</source>
+ <translation>Desempaquetando componentes...</translation>
</message>
<message>
- <source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 de %2 operaciones revertidas.</translation>
</message>
<message>
- <source>Error during removal process:
-%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2009,6 +2146,10 @@ Instalando componente %1</translation>
<translation>¿Desea cancelar el proceso de instalación?</translation>
</message>
<message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>¿Desea cancelar el proceso de desinstalación?</translation>
+ </message>
+ <message>
<source>Do you want to quit the installer application?</source>
<translation>¿Desea salir de la aplicación del instalador?</translation>
</message>
@@ -2025,12 +2166,12 @@ Instalando componente %1</translation>
<translation>%1 pregunta</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Configuración</translation>
</message>
<message>
<source>Specify proxy settings and configure repositories for add-on components.</source>
- <translation type="unfinished"></translation>
+ <translation>Especifique la configuración del proxy y configure los repositorios para los componentes complementarios.</translation>
</message>
<message>
<source>Error</source>
@@ -2040,11 +2181,7 @@ Instalando componente %1</translation>
<source>It is not possible to install from network location.
Please copy the installer to a local drive</source>
<translation>No es posible instalar desde una ubicación de red.
-Copie el instalador en una unidad local.</translation>
- </message>
- <message>
- <source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></translation>
+Copie el instalador en una unidad local</translation>
</message>
</context>
<context>
@@ -2086,15 +2223,27 @@ Copie el instalador en una unidad local.</translation>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>Instalando</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>Actualizando</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2139,7 +2288,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>
@@ -2151,7 +2300,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>
@@ -2163,12 +2312,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2193,11 +2354,11 @@ Copie el instalador en una unidad local.</translation>
<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>El argumento de búsqueda actual que llama a &quot;%1&quot; con un argumento de búsqueda vacío no es compatible.</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>El argumento de búsqueda actual que llama a &quot;%1&quot; con argumentos &quot;%2&quot; no es compatible. Por favor, utilice una cadena o regex.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2226,7 +2387,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>
@@ -2256,12 +2417,12 @@ Copie el instalador en una unidad local.</translation>
<translation>El objeto de instalador necesario en la operación %1 está vacío.</translation>
</message>
<message>
- <source>Self Restart: Invalid arguments</source>
- <translation>Auto-reinicio: argumentos no válidos</translation>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>Auto-reinicio: solo es válido en el modo de actualización o de administrador de paquetes.</translation>
</message>
<message>
- <source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>Auto-reinicio: argumentos no válidos</translation>
</message>
</context>
<context>
@@ -2295,7 +2456,7 @@ Copie el instalador en una unidad local.</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 type="unfinished"></translation>
+ <translation>L’argument de la méthode actuelle qui appelle &amp;amp;quot;%1&amp;amp;quot; avec les arguments &amp;amp;quot;%2&amp;amp;quot; n’est pas pris en charge. Utilisez la propriété set, remove, add_array_value ou remove_array_value.</translation>
</message>
</context>
<context>
@@ -2339,22 +2500,22 @@ Copie el instalador en una unidad local.</translation>
<translation>Especifique el directorio en el que se instalará %1.</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>Examina&amp;r...</translation>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>Examine el sistema de archivos para elegir el directorio de instalación.</translation>
</message>
<message>
<source>Select Installation Folder</source>
<translation>Seleccionar carpeta de instalación</translation>
</message>
- <message>
- <source>Alt+R</source>
- <comment>Browse file system to choose a file</comment>
- <translation type="unfinished">Alt+R</translation>
- </message>
</context>
<context>
<name>QInstaller::TestRepository</name>
@@ -2403,31 +2564,31 @@ Copie el instalador en una unidad local.</translation>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede iniciar el binario del instalador como actualizador.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede iniciar el binario del instalador como administrador de paquetes.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>No se puede iniciar el binario del instalador como desinstalador.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositorios vacía para la opción &apos;addRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositorios vacía para la opción &apos;addTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositorios vacía para la opción &apos;setTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Lista de repositorios vacía para la opción &apos;installCompressedRepository&apos;.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2435,19 +2596,27 @@ Copie el instalador en una unidad local.</translation>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>Faltan argumentos para la opción %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>Valor del botón %1 inválido </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>Argumentos incorrectos para %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 type="unfinished"></translation>
+ <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>
@@ -2475,7 +2644,10 @@ como usuario con los derechos adecuados y, luego, haga clic en Aceptar.</transla
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>No se puede obtener una autorización que se necesita para continuar con la instalación.
+
+Inicie el programa de instalación como usuario con los derechos necesarios.
+O bien acepte la elevación de los derechos de acceso si se le pide.</translation>
</message>
</context>
<context>
@@ -2492,8 +2664,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>No se puede abrir el archivo de configuración %1 para la lectura: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>Categorías</translation>
</message>
</context>
<context>
@@ -2571,6 +2743,10 @@ or accept the elevation of access rights if being asked.</source>
<translation>Agregue la contraseña para autenticar en el servidor.</translation>
</message>
<message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>Dirección URL de los servidores que contiene un repositorio válido.</translation>
+ </message>
+ <message>
<source>An error occurred while testing this repository.</source>
<translation>Se produjo un error al probar este repositorio.</translation>
</message>
@@ -2624,11 +2800,31 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation>Anular seleccionar todo</translation>
</message>
<message>
- <source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2665,14 +2861,14 @@ or accept the elevation of access rights if being asked.</source>
<source>Invalid arguments in %1: %n arguments given, %2 arguments expected.</source>
<translation>
<numerusform>Argumentos no válidos en %1: se han proporcionado %n argumentos, se esperaban %2.</numerusform>
- <numerusform></numerusform>
+ <numerusform>Argumentos inválidos en %1: %n argumentos dados, %2 argumentos esperados.</numerusform>
</translation>
</message>
<message numerus="yes">
<source>Invalid arguments in %1: %n arguments given, %2 arguments expected in the form: %3.</source>
<translation>
<numerusform>Argumentos no válidos en %1: se han proporcionado %n argumentos, se esperaban %2 con la forma: %3.</numerusform>
- <numerusform></numerusform>
+ <numerusform>Argumentos inválidos en %1: %n argumentos dados, %2 argumentos esperados en la forma: %3.</numerusform>
</translation>
</message>
<message>
@@ -2684,29 +2880,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>Filtro</translation>
</message>
<message>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Información</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation</name>
<message>
<source>Extracting &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <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>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>Se requiere la entrada del usuario pero el dispositivo de salida no está asociado a un terminal.</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>No se puede crear el objeto controlador para el archivo &quot;%1&quot;: &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 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 open archive for reading: %1</source>
+ <translation>No se puede abrir 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>
+</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 2c9b8f5c5..2f2bd5bf5 100644
--- a/src/sdk/translations/ifw_fr.ts
+++ b/src/sdk/translations/ifw_fr.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="fr">
+<TS version="2.1" language="fr_FR" sourcelanguage="en_GB">
<context>
<name>AuthenticationRequiredException</name>
<message>
@@ -39,7 +39,7 @@
</message>
<message>
<source>Unexpected mismatch of meta resources. Read %1, expected: %2.</source>
- <translation>Non-concordance inattendue des méta-ressources. %1 lu, attendu : %2.</translation>
+ <translation>Non-concordance inattendue des méta-ressources. %1 lu, attendu&#xa0;: %2.</translation>
</message>
</context>
<context>
@@ -107,7 +107,7 @@
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de démarrer le programme d&apos;installation</translation>
</message>
</context>
<context>
@@ -122,7 +122,7 @@
</message>
<message>
<source>Components that have resolved dependencies:</source>
- <translation>Composants qui ont résolu les dépendances :</translation>
+ <translation>Composants avec dépendances résolues&#xa0;:</translation>
</message>
<message>
<source>Selected components without dependencies:</source>
@@ -130,12 +130,24 @@
</message>
<message>
<source>Recursion detected, component &quot;%1&quot; already added with reason: &quot;%2&quot;</source>
- <translation>Récursion détectée, composant &quot;%1&quot; déjà ajouté avec raison : &quot;%2&quot;</translation>
+ <translation>Récursion détectée, composant &quot;%1&quot; déjà ajouté avec raison&#xa0;: &quot;%2&quot;</translation>
</message>
<message>
<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>
@@ -152,7 +164,7 @@
</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>
+ <translation>Impossible d’ouvrir le fichier &quot;%1&quot; en écriture&#xa0;: %2</translation>
</message>
<message>
<source>Cannot find backup file for &quot;%1&quot;.</source>
@@ -164,7 +176,7 @@
</message>
<message>
<source>Cannot restore backup file for &quot;%1&quot;: %2</source>
- <translation>Impossible de restaurer le fichier de sauvegarde pour &quot;%1&quot; : %2</translation>
+ <translation>Impossible de restaurer le fichier de sauvegarde pour &quot;%1&quot;&#xa0;: %2</translation>
</message>
</context>
<context>
@@ -175,34 +187,34 @@
</message>
<message>
<source>Cannot copy a non-existent file: %1</source>
- <translation>Impossible de copier un fichier qui n’existe pas : %1</translation>
+ <translation>Impossible de copier un fichier qui n’existe pas&#xa0;: %1</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
- <translation>Impossible de supprimer le fichier &quot;%1&quot; : %2</translation>
+ <translation>Impossible de supprimer le fichier &quot;%1&quot;&#xa0;: %2</translation>
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation>Impossible de copier le fichier &quot;%1&quot; vers &quot;%2&quot; : %3</translation>
+ <translation>Impossible de copier le fichier &quot;%1&quot; vers &quot;%2&quot;&#xa0;: %3</translation>
</message>
<message>
<source>Cannot delete file &quot;%1&quot;: %2</source>
- <translation>Impossible de supprimer le fichier &quot;%1&quot; : %2</translation>
+ <translation>Impossible de supprimer le fichier &quot;%1&quot;&#xa0;: %2</translation>
</message>
<message>
<source>Cannot restore backup file into &quot;%1&quot;: %2</source>
- <translation>Impossible de restaurer le fichier de sauvegarde dans &quot;%1&quot; : %2</translation>
+ <translation>Impossible de restaurer le fichier de sauvegarde dans &quot;%1&quot;&#xa0;: %2</translation>
</message>
</context>
<context>
<name>KDUpdater::DeleteOperation</name>
<message>
<source>Cannot create backup of file &quot;%1&quot;: %2</source>
- <translation>Impossible de créer une sauvegarde du fichier &quot;%1&quot; : %2</translation>
+ <translation>Impossible de créer une sauvegarde du fichier &quot;%1&quot;&#xa0;: %2</translation>
</message>
<message>
<source>Cannot restore backup file for &quot;%1&quot;: %2</source>
- <translation>Impossible de restaurer le fichier de sauvegarde pour &quot;%1&quot; : %2</translation>
+ <translation>Impossible de restaurer le fichier de sauvegarde pour &quot;%1&quot;&#xa0;: %2</translation>
</message>
</context>
<context>
@@ -235,28 +247,28 @@
<source>%n day(s), </source>
<translation>
<numerusform>%n jour(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n jour(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s), </source>
<translation>
<numerusform>%n heure(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n heure(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation>
<numerusform>%n minute(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n minute(s)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n second(s)</source>
<translation>
<numerusform>%n seconde(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n seconde(s)</numerusform>
</translation>
</message>
<message>
@@ -272,11 +284,11 @@
<name>KDUpdater::HttpDownloader</name>
<message>
<source>Cannot download %1. Writing to file &quot;%2&quot; failed: %3</source>
- <translation>Impossible de télécharger %1. L’écriture dans le fichier &quot;%2&quot; a échoué : %3</translation>
+ <translation>Impossible de télécharger %1. L’écriture dans le fichier &quot;%2&quot; a échoué&#xa0;: %3</translation>
</message>
<message>
<source>Cannot download %1. Cannot create file &quot;%2&quot;: %3</source>
- <translation>Impossible de télécharger %1. Impossible de créer le fichier &quot;%2&quot; : %3</translation>
+ <translation>Impossible de télécharger %1. Impossible de créer le fichier &quot;%2&quot;&#xa0;: %3</translation>
</message>
<message>
<source>%1 at %2</source>
@@ -292,7 +304,7 @@
</message>
<message>
<source>There was an error during connection to: %1.</source>
- <translation>Une erreur s’est produite lors de la connexion à : %1.</translation>
+ <translation>Une erreur s’est produite lors de la connexion à&#xa0;: %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>
@@ -306,27 +318,31 @@
<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>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Impossible d’ouvrir le fichier &quot;%1&quot; en lecture : %2</translation>
+ <translation>Impossible d’ouvrir le fichier &quot;%1&quot; en lecture&#xa0;: %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>
+ <translation>Impossible d’ouvrir le fichier &quot;%1&quot; en écriture&#xa0;: %2</translation>
</message>
<message>
<source>Writing to file &quot;%1&quot; failed: %2</source>
- <translation>L’écriture dans le fichier &quot;%1&quot; a échoué : %2</translation>
+ <translation>L’écriture dans le fichier &quot;%1&quot; a échoué&#xa0;: %2</translation>
</message>
</context>
<context>
<name>KDUpdater::MkdirOperation</name>
<message>
<source>Cannot create directory &quot;%1&quot;: %2</source>
- <translation>Impossible de créer le répertoire &quot;%1&quot; : %2</translation>
+ <translation>Impossible de créer le répertoire &quot;%1&quot;&#xa0;: %2</translation>
</message>
<message>
<source>Unknown error.</source>
@@ -334,7 +350,7 @@
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;: %2</source>
- <translation>Impossible de supprimer le répertoire &quot;%1&quot; : %2</translation>
+ <translation>Impossible de supprimer le répertoire &quot;%1&quot;&#xa0;: %2</translation>
</message>
</context>
<context>
@@ -345,11 +361,11 @@
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
- <translation>Impossible de supprimer le fichier &quot;%1&quot; : %2</translation>
+ <translation>Impossible de supprimer le fichier &quot;%1&quot;&#xa0;: %2</translation>
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation>Impossible de copier le fichier &quot;%1&quot; vers &quot;%2&quot; : %3</translation>
+ <translation>Impossible de copier le fichier &quot;%1&quot; vers &quot;%2&quot;&#xa0;: %3</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;.</source>
@@ -357,7 +373,7 @@
</message>
<message>
<source>Cannot restore backup file for &quot;%1&quot;: %2</source>
- <translation>Impossible de restaurer le fichier de sauvegarde pour &quot;%1&quot; : %2</translation>
+ <translation>Impossible de restaurer le fichier de sauvegarde pour &quot;%1&quot;&#xa0;: %2</translation>
</message>
</context>
<context>
@@ -454,7 +470,7 @@
<source>%n update(s) found.</source>
<translation>
<numerusform>%n mise(s) à jour trouvée(s).</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n mise(s) à jour trouvée(s).</numerusform>
</translation>
</message>
<message>
@@ -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>
@@ -520,6 +532,14 @@
<context>
<name>Lib7z</name>
<message>
+ <source>Internal code: %1</source>
+ <translation>code interne : %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>mémoire insuffisante</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Erreur : %1</translation>
</message>
@@ -565,7 +585,7 @@
</message>
<message>
<source>Cannot create archive &quot;%1&quot;</source>
- <translation>Impossible de créer l’archive &quot;%1&quot;.</translation>
+ <translation>Impossible de créer l’archive &quot;%1&quot;</translation>
</message>
<message>
<source>Cannot create archive &quot;%1&quot;: %2</source>
@@ -583,14 +603,6 @@
<source>Unknown exception caught (%1)</source>
<translation>Exception inconnue détectée (%1)</translation>
</message>
- <message>
- <source>Internal code: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not enough memory</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>LocalPackageHub</name>
@@ -734,7 +746,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de copier le fichier &quot;%1&quot; vers &quot;%2&quot;.</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -742,7 +754,11 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -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>
@@ -781,11 +785,31 @@
</message>
<message>
<source>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></translation>
+ <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>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>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>
@@ -834,44 +858,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<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 type="unfinished"></translation>
+ <translation>Sélectionner les composants par défaut dans l&apos;arborescence.</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 type="unfinished"></translation>
+ <translation>Réinitialiser tous les composants à leur état de sélection d&apos;origine dans l&apos;arborescence.</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 type="unfinished"></translation>
+ <translation>Sélectionner tous les composants dans l&apos;arborescence.</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 type="unfinished"></translation>
+ <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>
+ <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>
<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>
+ <source>Filter the enabled repository categories</source>
+ <translation>Filtrer les catégories de référentiel activées à sélectionner.</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -898,36 +922,36 @@
<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 type="unfinished"></translation>
+ <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>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Search</source>
+ <translation>Recherche</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>Parcourir les fichiers QBSP</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Select</source>
+ <translation>Sélectionner</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Error</source>
+ <translation>Erreur</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -945,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>
@@ -1049,11 +1069,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de créer le chemin &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de supprimer le répertoire &quot;%1&quot;.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1087,6 +1107,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Impossible de supprimer le répertoire &quot;%1&quot; : %2</translation>
</message>
+ <message>
+ <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>
@@ -1151,6 +1171,80 @@ Erreur lors du chargement de %2</translation>
<source>Cannot find component for %1.</source>
<translation>Composant introuvable pour %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 sur %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 téléchargé.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n jour(s), </numerusform>
+ <numerusform>%n jour(s), </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n heure(s), </numerusform>
+ <numerusform>%n heure(s), </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minute(s)</numerusform>
+ <numerusform>%n minute(s)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n seconde(s)</numerusform>
+ <numerusform>%n seconde(s)</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 restants.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - temps restant inconnu.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>Archive: </translation>
+ </message>
+ <message>
+ <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>
@@ -1220,21 +1314,6 @@ Erreur lors du chargement de %2</translation>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <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 extracting archive &quot;%1&quot;: %2</source>
- <translation>Erreur lors de l’extraction de l’archive &quot;%1&quot; : %2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Exception inconnue détectée lors de l’extraction de &quot;%1&quot;.</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1267,28 +1346,28 @@ Erreur lors du chargement de %2</translation>
<source>%n day(s), </source>
<translation>
<numerusform>%n jour(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n jour(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s), </source>
<translation>
<numerusform>%n heure(s), </numerusform>
- <numerusform></numerusform>
+ <numerusform>%n heure(s), </numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation>
<numerusform>%n minute(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n minute(s)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n second(s)</source>
<translation>
<numerusform>%n seconde(s)</numerusform>
- <numerusform></numerusform>
+ <numerusform>%n seconde(s)</numerusform>
</translation>
</message>
<message>
@@ -1303,15 +1382,15 @@ 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>
<source>Finished</source>
- <translation type="unfinished"></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>
@@ -1323,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>
@@ -1364,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>
@@ -1400,13 +1483,13 @@ 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>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>Une mise a jour importante est disponible. Merci de commencer par sélectioner &apos;%1&apos;</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1415,6 +1498,11 @@ Erreur lors du chargement de %2</translation>
<translation>Contrat de licence</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>Lisez le contrat de licence suivant. Vous devez accepter les termes contenus dans ce contrat avant de poursuivre l’installation.</translation>
</message>
@@ -1430,11 +1518,6 @@ Erreur lors du chargement de %2</translation>
<source>I accept the licenses.</source>
<translation>J’accepte les licences.</translation>
</message>
- <message>
- <source>Alt+A</source>
- <comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
- </message>
</context>
<context>
<name>QInstaller::LicenseOperation</name>
@@ -1450,16 +1533,12 @@ 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>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>Argument invalide dans %1 : L&apos;argument de recherche vide n&apos;est pas pris en charge.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1477,14 +1556,14 @@ 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>
<message>
+ <source>Metadata download canceled.</source>
+ <translation>Le téléchargement des métadonnées a été annulé.</translation>
+ </message>
+ <message>
<source>Unknown exception during extracting.</source>
<translation>Exception inconnue au cours de l’extraction.</translation>
</message>
@@ -1513,28 +1592,51 @@ 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>
+ <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>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Extraction des métadonnées depuis le référentiel distant... </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>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Erreur lors de l’extraction de l’archive &quot;%1&quot; : %2</translation>
+ <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>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Exception inconnue détectée lors de l’extraction de l’archive &quot;%1&quot;.</translation>
+ <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>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Impossible d’ouvrir le fichier &quot;%1&quot; en lecture : %2</translation>
+ <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>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1544,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>
@@ -1558,6 +1658,10 @@ Téléchargement des paquetages...</translation>
<translation>Tous les téléchargements sont terminés.</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation>Annulation du programme d’installation</translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>Erreur d’authentification</translation>
</message>
@@ -1652,36 +1756,28 @@ 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>
- </message>
- <message>
- <source>Cannot install component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></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>Component %1 already installed
-</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>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 %1. Component is virtual.
-</source>
- <translation type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>Composant %1 déjà installé</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>Impossible d&apos;installer %1. Le composant est virtuel.</translation>
</message>
<message>
- <source>Running processes found.</source>
- <translation type="unfinished"></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>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;élever les droits d&apos;accès lors de l&apos;exécution à partir de la ligne de commande. Veuillez redémarrer l&apos;application en tant qu&apos;administrateur.</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1692,58 +1788,68 @@ Souhaitez-vous continuer ?</translation>
<translation>Erreur</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>L’espace disque est insuffisant pour stocker les fichiers temporaires et l’installation. %1 sont disponibles, alors qu’au moins %2 sont nécessaires.</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
+ <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>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>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>
<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>Le volume que vous avez sélectionné pour l&apos;installation semble avoir suffisamment d&apos;espace pour l&apos;installation, mais il y aura moins de 100&#xa0;Mo disponibles par la suite.</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
<translation>L’installation va utiliser %1 de l’espace disque.</translation>
</message>
<message>
+ <source>Invalid</source>
+ <translation>non valide</translation>
+ </message>
+ <message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></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 type="unfinished"></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>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>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>Canceling the Installer</source>
- <translation type="unfinished"></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. Component is not checkable, meaning you have to select one of the subcomponents.
-</source>
- <translation type="unfinished"></translation>
+ <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>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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>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>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Impossible de résoudre les composants à désinstaller.</translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Invalid</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1786,7 +1892,7 @@ Souhaitez-vous continuer ?</translation>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>Nombre de tentatives dépassé</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
@@ -1814,7 +1920,7 @@ Souhaitez-vous continuer ?</translation>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de supprimer le fichier de données temporaire &quot;%1&quot; : %2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1822,7 +1928,7 @@ Souhaitez-vous continuer ?</translation>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>Écriture du binaire de base hors ligne.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1834,11 +1940,11 @@ Souhaitez-vous continuer ?</translation>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d&apos;écrire le binaire hors ligne vers &quot;%1&quot; : %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de supprimer le fichier temporaire &quot;%1&quot; : %2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1861,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>
@@ -1881,54 +1983,56 @@ 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>
+ <translation>La désinstallation a réussi.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>Désinstallation abandonnée.</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de créer le répertoire cible pour le programme d&apos;installation.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>Préparation de la génération hors ligne...</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>Préparation de la configuration du programme d&apos;installation...</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>Création du programme d&apos;installation...</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>Échec de la création du programme d&apos;installation hors ligne. %1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de supprimer le fichier temporaire &quot;%1&quot;.</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>La génération hors ligne a été effectuée avec succès.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></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>
@@ -1942,7 +2046,21 @@ Installation du composant %1</translation>
</message>
<message>
<source>Done</source>
- <translation type="unfinished"></translation>
+ <translation>Fait</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>Impossible de préparer la désinstallation</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>Impossible de démarrer la désinstallation</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>Une erreur s’est produite au cours de la désinstallation :
+%1</translation>
</message>
<message>
<source>Unknown error</source>
@@ -1961,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>
@@ -1973,25 +2087,48 @@ Installation du composant %1</translation>
<translation>Cycle de dépendance entre les composants &quot;%1&quot; et &quot;%2&quot; détecté.</translation>
</message>
<message>
- <source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <source>Preparing to unpack components...</source>
+ <translation>Préparation du déballage des composants...</translation>
</message>
<message>
- <source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%1 opérations sur %2 terminées.</translation>
</message>
<message>
- <source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <source>Unpacking components...</source>
+ <translation>Déballage des composants...</translation>
</message>
<message>
- <source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%1 des %2 opérations annulées.</translation>
</message>
<message>
- <source>Error during removal process:
-%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2009,6 +2146,10 @@ Installation du composant %1</translation>
<translation>Voulez-vous annuler l’installation ?</translation>
</message>
<message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>Voulez-vous annuler la désinstallation ?</translation>
+ </message>
+ <message>
<source>Do you want to quit the installer application?</source>
<translation>Voulez-vous quitter le programme d’installation ?</translation>
</message>
@@ -2025,12 +2166,12 @@ Installation du composant %1</translation>
<translation>Question %1</translation>
</message>
<message>
- <source>Settings</source>
+ <source>&amp;Settings</source>
<translation>Réglages</translation>
</message>
<message>
<source>Specify proxy settings and configure repositories for add-on components.</source>
- <translation type="unfinished"></translation>
+ <translation>Spécifier les paramètres de proxy et configurer les référentiels pour les composants complémentaires.</translation>
</message>
<message>
<source>Error</source>
@@ -2042,10 +2183,6 @@ Please copy the installer to a local drive</source>
<translation>Installation impossible à partir d’une localisation de réseau.
Copiez le programme d’installation sur un disque local</translation>
</message>
- <message>
- <source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>QInstaller::PerformInstallationForm</name>
@@ -2086,15 +2223,27 @@ Copiez le programme d’installation sur un disque local</translation>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>Installation</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>Mise à jour</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2139,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>
@@ -2151,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>
@@ -2163,12 +2312,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2193,11 +2354,11 @@ Copiez le programme d’installation sur un disque local</translation>
<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>L&apos;argument de recherche actuel appelant &quot;%1&quot; avec un argument de recherche vide n&apos;est pas pris en charge.</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>L&apos;argument du mode actuel appelant &quot;%1&quot; avec les arguments &quot;%2&quot; n&apos;est pas pris en charge. Veuillez utiliser une chaîne ou une expression régulière.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2226,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>
@@ -2256,12 +2417,12 @@ Copiez le programme d’installation sur un disque local</translation>
<translation>L’objet du programme d’installation requis dans l’opération %1 est vide.</translation>
</message>
<message>
- <source>Self Restart: Invalid arguments</source>
- <translation>Redémarrage automatique : arguments non valides</translation>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>Redémarrage automatique : valide uniquement en mode de mise à jour ou de gestionnaire de paquetages.</translation>
</message>
<message>
- <source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>Redémarrage automatique : arguments non valides</translation>
</message>
</context>
<context>
@@ -2295,7 +2456,7 @@ Copiez le programme d’installation sur un disque local</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 type="unfinished"></translation>
+ <translation>L’argument de la méthode actuelle qui appelle &amp;quot;%1&amp;quot; avec les arguments &amp;quot;%2&amp;quot; n’est pas pris en charge. Utilisez la propriété set, remove, add_array_value ou remove_array_value.</translation>
</message>
</context>
<context>
@@ -2339,22 +2500,22 @@ Copiez le programme d’installation sur un disque local</translation>
<translation>Spécifiez le répertoire dans lequel %1 va être installé.</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>P&amp;arcourir...</translation>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>Parcourir le système de fichiers pour choisir le répertoire d&apos;installation.</translation>
</message>
<message>
<source>Select Installation Folder</source>
<translation>Sélectionner le dossier d’installation</translation>
</message>
- <message>
- <source>Alt+R</source>
- <comment>Browse file system to choose a file</comment>
- <translation type="unfinished">Alt+R</translation>
- </message>
</context>
<context>
<name>QInstaller::TestRepository</name>
@@ -2403,31 +2564,31 @@ Copiez le programme d’installation sur un disque local</translation>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de démarrer le binaire d&apos;installation en tant que programme de mise à jour.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de démarrer le binaire d&apos;installation en tant que gestionnaire de packages.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible de démarrer le binaire d&apos;installation en tant que programme de désinstallation.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Liste de référentiels vide pour l&apos;option &apos;addRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Liste de référentiels vide pour l&apos;option &apos;addTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Liste de référentiels vide pour l&apos;option &apos;setTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Liste de référentiels vide pour l&apos;option &apos;installCompressedRepository&apos;.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2435,19 +2596,27 @@ Copiez le programme d’installation sur un disque local</translation>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>Arguments manquants pour l&apos;option %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>Valeur de bouton non valide %1 </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>Arguments incorrects pour %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 type="unfinished"></translation>
+ <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>
@@ -2475,7 +2644,12 @@ en tant qu’utilisateur doté des droits appropriés, puis cliquez sur OK.</tra
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>Impossible d’obtenir l’autorisation requise pour poursuivre l’installation.
+
+
+Démarrez le programme d’installation en tant qu’utilisateur doté des droits appropriés.
+
+Ou acceptez l’élévation des droits d’accès si un message vous y invite.</translation>
</message>
</context>
<context>
@@ -2492,8 +2666,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>Impossible d’ouvrir le fichier de paramètres %1 en lecture : %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>Catégories</translation>
</message>
</context>
<context>
@@ -2571,6 +2745,10 @@ or accept the elevation of access rights if being asked.</source>
<translation>Ajoutez le mot de passe à authentifier sur le serveur.</translation>
</message>
<message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>L’URL des serveurs qui contient un référentiel valide.</translation>
+ </message>
+ <message>
<source>An error occurred while testing this repository.</source>
<translation>Une erreur s’est produite pendant le test du référentiel.</translation>
</message>
@@ -2620,15 +2798,35 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation>Tout sélectionner</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation>Tout désélectionner</translation>
</message>
<message>
- <source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2665,14 +2863,14 @@ or accept the elevation of access rights if being asked.</source>
<source>Invalid arguments in %1: %n arguments given, %2 arguments expected.</source>
<translation>
<numerusform>Arguments non valides dans %1 : %n arguments fournis, %2 arguments attendus.</numerusform>
- <numerusform></numerusform>
+ <numerusform>Arguments invalides dans %1 : %n arguments donnés, %2 arguments attendus.</numerusform>
</translation>
</message>
<message numerus="yes">
<source>Invalid arguments in %1: %n arguments given, %2 arguments expected in the form: %3.</source>
<translation>
<numerusform>Arguments non valides dans %1 : %n arguments fournis, %2 arguments attendus dans le formulaire : %3.</numerusform>
- <numerusform></numerusform>
+ <numerusform>Arguments invalides dans %1 : %n arguments donnés, %2 arguments attendus dans le formulaire : %3.</numerusform>
</translation>
</message>
<message>
@@ -2684,29 +2882,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>Filtre</translation>
</message>
<message>
<source>Error</source>
<translation>Erreur</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Informations</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation</name>
<message>
<source>Extracting &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <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>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
+ <translation>Une saisie par l’utilisateur est requise mais le périphérique de sortie n&apos;est pas associé à un terminal.</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>Impossible d’ouvrir l’archive &quot;%1&quot; en lecture : %2</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>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</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 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 f0bf9f5c6..5152944d3 100644
--- a/src/sdk/translations/ifw_ja.ts
+++ b/src/sdk/translations/ifw_ja.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="ja">
+<TS version="2.1" language="ja_JP" sourcelanguage="en_GB">
<context>
<name>AuthenticationRequiredException</name>
<message>
@@ -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>
@@ -107,7 +107,7 @@
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>インストーラーを起動できません</translation>
</message>
</context>
<context>
@@ -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>
@@ -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>
@@ -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>
@@ -515,6 +527,14 @@
<context>
<name>Lib7z</name>
<message>
+ <source>Internal code: %1</source>
+ <translation>内部コード: %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>メモリが足りません</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>エラー: %1</translation>
</message>
@@ -578,14 +598,6 @@
<source>Unknown exception caught (%1)</source>
<translation>不明な例外が発生しました (%1)</translation>
</message>
- <message>
- <source>Internal code: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not enough memory</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>LocalPackageHub</name>
@@ -729,7 +741,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>ファイル &quot;%1&quot; を &quot;%2&quot; にコピーできません。</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -737,7 +749,11 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -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>
@@ -776,11 +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 ファイル &quot;%1&quot; を開けません: %2.
+
+%3 &quot;%4&quot;</translation>
</message>
<message>
- <source>There was an error loading the selected component. This component cannot be updated.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -829,44 +853,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<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 type="unfinished"></translation>
+ <translation>ツリー表示でデフォルトのコンポーネントを選択します。</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 type="unfinished"></translation>
+ <translation>ツリー表示ですべてのコンポーネントを元の選択状態にリセットします。</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 type="unfinished"></translation>
+ <translation>ツリー表示ですべてのコンポーネントを選択します。</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 type="unfinished"></translation>
+ <translation>ツリー表示ですべてのコンポーネントの選択を解除します。</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>QBSP ファイルの参照 (&amp;B)</translation>
+ <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>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>
+ <source>Filter the enabled repository categories</source>
+ <translation>有効なリポジトリカテゴリをフィルタリングして選択します。</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -893,36 +917,36 @@
<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 type="unfinished"></translation>
+ <translation>更新したい他のコンポーネントを選択する前に必須コンポーネントを更新する必要があります。</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt + A</translation>
+ <source>Search</source>
+ <translation>検索</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt + R</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>QBSPファイルを検索</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt + S</translation>
+ <source>Select</source>
+ <translation>選択</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt + D</translation>
+ <source>Error</source>
+ <translation>エラー</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -940,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>
@@ -1044,11 +1064,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>パス &quot;%1&quot; を作成できません。</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>ディレクトリ &quot;%1&quot; を削除できません。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1082,6 +1102,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<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>
@@ -1146,6 +1174,58 @@ Error while loading %2</source>
<source>Cannot find component for %1.</source>
<translation>%1 用のコンポーネントが見つかりません。</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1/%2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 がダウンロードされました。</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n 日、 </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n 時間、 </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n 分</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n 秒</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation>- 残り %1%2%3%4</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation>- 残り時間不明</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>アーカイブ</translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <translation>合計</translation>
+ </message>
+ <message>
+ <source>Retry count (%1) exceeded</source>
+ <translation>再試行回数 (%1) を超えました</translation>
+ </message>
</context>
<context>
<name>QInstaller::Downloader</name>
@@ -1215,21 +1295,6 @@ Error while loading %2</source>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <message>
- <source>Cannot open archive &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>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>&quot;%1&quot; の抽出中に不明な例外が発生しました。</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1284,25 +1349,25 @@ 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>
<source>Finished</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1314,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>
@@ -1355,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>
@@ -1391,13 +1460,13 @@ 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>重要な更新が見つかりました。まず&apos;%1&apos; を選択してください</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1406,6 +1475,11 @@ Error while loading %2</source>
<translation>使用許諾契約</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>次の使用許諾契約をお読みください。 インストール処理に進む前に、この契約に記載された利用条件に同意する必要があります。</translation>
</message>
@@ -1421,11 +1495,6 @@ Error while loading %2</source>
<source>I accept the licenses.</source>
<translation>使用許諾に同意します。</translation>
</message>
- <message>
- <source>Alt+A</source>
- <comment>Agree license</comment>
- <translation type="unfinished">Alt + A</translation>
- </message>
</context>
<context>
<name>QInstaller::LicenseOperation</name>
@@ -1441,16 +1510,12 @@ 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>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>%1 に無効な引数があります:空の検索引数はサポートされていません。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1468,14 +1533,14 @@ 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>
<message>
+ <source>Metadata download canceled.</source>
+ <translation>メタデータのダウンロードがキャンセルされました。</translation>
+ </message>
+ <message>
<source>Unknown exception during extracting.</source>
<translation>抽出中に不明な例外が発生しました。</translation>
</message>
@@ -1504,28 +1569,50 @@ 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>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>アーカイブ &quot;%1&quot; の抽出中に不明な例外が発生しました。</translation>
+ <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>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>読み取り用のファイル &quot;%1&quot; を開けません: %2</translation>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>キャッシュディレクトリを空にしてアプリケーションを再起動すると、この問題が解決する場合があります。</translation>
</message>
<message>
- <source>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1535,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>
@@ -1549,6 +1634,10 @@ Downloading packages...</source>
<translation>ダウンロードがすべて終了しました。</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation>インストーラーをキャンセルしています</translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>認証エラー</translation>
</message>
@@ -1643,36 +1732,28 @@ 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 type="unfinished"></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 type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>コンポーネント %1 はすでにインストールされています</translation>
</message>
<message>
- <source>Cannot install %1. Component is virtual.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>%1 をインストールできません。コンポーネントは仮想です。</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>%1 をインストールできません。コンポーネントが見つかりません。</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>コマンドラインから実行しているときはアクセス権限を昇格できません。管理者としてアプリケーションを再起動してください。</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1683,58 +1764,68 @@ Do you want to continue?</source>
<translation>エラー</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>十分なディスク空き容量がないため、一時ファイルとインストール内容を格納できません。%2 が最低限必要な場合は、%1 を利用できます。</translation>
+ </message>
+ <message>
+ <source>Not enough disk space to store all selected components! %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 type="unfinished"></translation>
+ <translation>インストール用に選択されたボリュームにはインストールに十分な空き容量があるようですが、後から使用可能な空き容量はボリュームの 1% 未満です。</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>インストール用に選択されたボリュームにはインストールに十分な空き容量があるようですが、インストール後使用可能なのは 100 MB 未満です。</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
<translation>ディスク空き容量の %1 がインストールに使用されます。</translation>
</message>
<message>
+ <source>Invalid</source>
+ <translation>無効</translation>
+ </message>
+ <message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>ユーザー入力が必要ですが、出力デバイスが端末に関連づけられていません。</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %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 type="unfinished"></translation>
+ <translation>インストーラの推定サイズ %1 は、実行可能ファイルのサイズ制限 %2 を超えています。アプリケーションが実行できない場合があります。</translation>
</message>
<message>
- <source>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>削除されるコンポーネント: </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. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>コンポーネント %1をインストールできません。このコンポーネントのロードに問題があったため、不安定と記され、選択できません。</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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>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>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>アンインストール対象のコンポーネントを解決できません。</translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>%1を選択できません。エイリアスは仮想として記され、手動で選択できません。</translation>
</message>
<message>
- <source>Invalid</source>
- <translation type="unfinished"></translation>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>作成されるインストーラーはディスク容量の %1 を使用します。</translation>
</message>
</context>
<context>
@@ -1777,7 +1868,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>再試行回数を超過しました</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
@@ -1805,7 +1896,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>一時データファイル &quot;%1&quot; を削除できません:%2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1813,7 +1904,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>オフラインベースバイナリを書き込んでいます。</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1825,11 +1916,11 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>オフラインバイナリを &quot;%1&quot; に書き込めません: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>一時ファイル &quot;%1&quot; を削除できません:%2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1852,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>
@@ -1872,54 +1959,56 @@ 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>
+ <translation>アンインストールが正常に完了しました。</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>アンインストールが中止されました。</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>インストーラーのターゲットディレクトリを作成できません。</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>オフライン生成を準備しています…</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>インストーラー構成を準備しています…</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>インストーラーを作成しています…</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>オフラインインストーラーの作成に失敗しました。%1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>一時ディレクトリ &quot;%1&quot; を削除できません:</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>オフライン生成が正常に完了しました。</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1933,7 +2022,21 @@ Installing component %1</source>
</message>
<message>
<source>Done</source>
- <translation type="unfinished"></translation>
+ <translation>完了</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>アンインストールを準備できません</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>アンインストールを開始できません</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>アンインストール処理中にエラーが発生しました:
+%1</translation>
</message>
<message>
<source>Unknown error</source>
@@ -1952,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>
@@ -1964,25 +2063,48 @@ Installing component %1</source>
<translation>コンポーネント &quot;%1&quot; と &quot;%2&quot; との依存サイクルが検出されました。</translation>
</message>
<message>
- <source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <source>Preparing to unpack components...</source>
+ <translation>コンポーネントを開梱する準備をしています。</translation>
</message>
<message>
- <source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%2 中 %1 の操作が完了しました。</translation>
</message>
<message>
- <source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <source>Unpacking components...</source>
+ <translation>コンポーネントを開梱しています。</translation>
</message>
<message>
- <source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%2 中 %1 の操作がロールバックされました。</translation>
</message>
<message>
- <source>Error during removal process:
-%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2000,6 +2122,10 @@ Installing component %1</source>
<translation>インストール処理をキャンセルしますか?</translation>
</message>
<message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>アンインストール処理をキャンセルしますか?</translation>
+ </message>
+ <message>
<source>Do you want to quit the installer application?</source>
<translation>インストーラー アプリケーションを終了しますか?</translation>
</message>
@@ -2016,12 +2142,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 type="unfinished"></translation>
+ <translation>プロキシ設定を指定し、アドオン コンポーネントのリポジトリを構成します。</translation>
</message>
<message>
<source>Error</source>
@@ -2033,10 +2159,6 @@ Please copy the installer to a local drive</source>
<translation>ネットワーク ロケーションからインストールできません。
インストーラーをローカル ドライブにコピーしてください。</translation>
</message>
- <message>
- <source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>QInstaller::PerformInstallationForm</name>
@@ -2077,15 +2199,27 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>インストールしています</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>更新しています</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2130,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>
@@ -2142,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>
@@ -2154,12 +2288,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2184,11 +2330,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>空の検索引数で &quot;%1&quot; を呼び出す現在の検索引数はサポートされていません。</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>引数 &quot;%2&quot; で &quot;%1&quot; を呼び出す現在のモード引数はサポートされていません。文字列または正規表現を使用してください。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2217,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>
@@ -2247,12 +2393,12 @@ Please copy the installer to a local drive</source>
<translation>操作 %1 に必要なインストーラー オブジェクトが空です。</translation>
</message>
<message>
- <source>Self Restart: Invalid arguments</source>
- <translation>自動再起動: 引数が無効です</translation>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>自動再起動: アップデーターまたはパッケージ マネージャー モード内でのみ有効です。</translation>
</message>
<message>
- <source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>自動再起動: 引数が無効です</translation>
</message>
</context>
<context>
@@ -2286,7 +2432,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>引数 &amp;quot;%2&amp;quot; で &amp;quot;%1&amp;quot; を呼び出すメソッドの引数は現在サポートされていません。 set、remove、add_array_value、または remove_array_value を使用してください。</translation>
</message>
</context>
<context>
@@ -2330,22 +2476,22 @@ Please copy the installer to a local drive</source>
<translation>%1 をインストールするディレクトリを指定してください。</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;R)...</translation>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>ファイルシステムを参照し、インストールディレクトリを選択します</translation>
</message>
<message>
<source>Select Installation Folder</source>
<translation>インストール フォルダーの選択</translation>
</message>
- <message>
- <source>Alt+R</source>
- <comment>Browse file system to choose a file</comment>
- <translation type="unfinished">Alt + R</translation>
- </message>
</context>
<context>
<name>QInstaller::TestRepository</name>
@@ -2394,31 +2540,31 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>アップデーターとしてインストーラーバイナリを起動できません。</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>パッケージマネージャーとしてインストーラーバイナリを起動できません。</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>アンインストーラーとしてインストーラーバイナリを起動できません。</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>オプション &apos;addRepository’ のリポジトリリストが空です。</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>オプション &apos;addTempRepository’ のリポジトリリストが空です。</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>オプション &apos;setTempRepository’ のリポジトリリストが空です。</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>オプション &apos;installCompressedRepository’ のリポジトリリストが空です</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2426,19 +2572,27 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>オプション %1 の引数がありません</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>ボタン値 %1 が無効です </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>%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 type="unfinished"></translation>
+ <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>
@@ -2466,7 +2620,10 @@ as a user with the appropriate rights and then clicking OK.</source>
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>インストールの続行に必要な認証を取得できません。
+
+適切な権限を持つユーザーとしてセットアッププログラムを開始してください。
+または、要求された場合は、アクセス権限の昇格を承認してください。</translation>
</message>
</context>
<context>
@@ -2483,8 +2640,8 @@ or accept the elevation of access rights if being asked.</source>
<translation>読み取り用の設定ファイル %1 を開けません: %2</translation>
</message>
<message>
- <source>Select Categories</source>
- <translation type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>カテゴリを選択</translation>
</message>
</context>
<context>
@@ -2562,6 +2719,10 @@ or accept the elevation of access rights if being asked.</source>
<translation>サーバー上で認証を行うパスワードを追加します。</translation>
</message>
<message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>有効なリポジトリを含むサーバーのURL。</translation>
+ </message>
+ <message>
<source>An error occurred while testing this repository.</source>
<translation>このリポジトリのテスト中にエラーが発生しました。</translation>
</message>
@@ -2611,15 +2772,35 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation>すべて選択</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation>すべての選択を解除</translation>
</message>
<message>
- <source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2673,29 +2854,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>フィルター</translation>
</message>
<message>
<source>Error</source>
<translation>エラー</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>コンポーネント情報</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation</name>
<message>
<source>Extracting &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <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>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>ユーザー入力が必要ですが、出力デバイスが端末に関連づけられていません。</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>アーカイブ &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 extracting archive &quot;%1&quot;: %2</source>
+ <translation>アーカイブ &quot;%1&quot; の抽出中にエラーが発生しました: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</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>
+</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
new file mode 100644
index 000000000..39bd1ff85
--- /dev/null
+++ b/src/sdk/translations/ifw_ko.ts
@@ -0,0 +1,3093 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ko_KR" sourcelanguage="en_GB">
+<context>
+ <name>QInstaller::ProxyCredentialsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>대화창</translation>
+ </message>
+ <message>
+ <source>The proxy %1 requires a username and password.</source>
+ <translation>프록시 1%에 사용자 이름과 비밀번호가 필요합니다.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>사용자 이름:</translation>
+ </message>
+ <message>
+ <source>Username</source>
+ <translation>사용자 이름</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>비밀번호:</translation>
+ </message>
+ <message>
+ <source>Password</source>
+ <translation>비밀번호</translation>
+ </message>
+ <message>
+ <source>Proxy Credentials</source>
+ <translation>프록시 자격 증명</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ServerAuthenticationDialog</name>
+ <message>
+ <source>Server Requires Authentication</source>
+ <translation>서버 인증이 필요함</translation>
+ </message>
+ <message>
+ <source>You need to supply a username and password to access this site.</source>
+ <translation>이 사이트에 접근하려면 사용자 이름과 비밀번호가 필요합니다.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>사용자 이름:</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>비밀번호:</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%2의 %1</translation>
+ </message>
+</context>
+<context>
+ <name>Dialog</name>
+ <message>
+ <source>Http authentication required</source>
+ <translation>HTTP 인증 필요</translation>
+ </message>
+ <message>
+ <source>You need to supply a Username and Password to access this site.</source>
+ <translation>이 사이트에 접근하려면 사용자 이름과 비밀번호가 필요합니다.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>사용자 이름:</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>비밀번호:</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%2의 %1</translation>
+ </message>
+</context>
+<context>
+ <name>SettingsDialog</name>
+ <message>
+ <source>Settings</source>
+ <translation>설정</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>네트워크</translation>
+ </message>
+ <message>
+ <source>No proxy</source>
+ <translation>프록시 없음</translation>
+ </message>
+ <message>
+ <source>System proxy settings</source>
+ <translation>시스템 프록시 설정</translation>
+ </message>
+ <message>
+ <source>Manual proxy configuration</source>
+ <translation>수동 프록시 구성</translation>
+ </message>
+ <message>
+ <source>HTTP proxy:</source>
+ <translation>HTTP 프록시:</translation>
+ </message>
+ <message>
+ <source>Port:</source>
+ <translation>포트:</translation>
+ </message>
+ <message>
+ <source>FTP proxy:</source>
+ <translation>FTP 프록시:</translation>
+ </message>
+ <message>
+ <source>Repositories</source>
+ <translation>저장소</translation>
+ </message>
+ <message>
+ <source>Add Username and Password for authentication if needed.</source>
+ <translation>필요하면 인증을 위한 사용자 이름과 비밀번호를 추가하십시오.</translation>
+ </message>
+ <message>
+ <source>Use temporary repositories only</source>
+ <translation>임시 저장소만 사용</translation>
+ </message>
+ <message>
+ <source>Add</source>
+ <translation>추가</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>제거</translation>
+ </message>
+ <message>
+ <source>Test</source>
+ <translation>테스트</translation>
+ </message>
+ <message>
+ <source>Select All</source>
+ <translation>모두 선택</translation>
+ </message>
+ <message>
+ <source>Deselect All</source>
+ <translation>모두 선택 해제</translation>
+ </message>
+ <message>
+ <source>Show Passwords</source>
+ <translation>비밀번호 표시</translation>
+ </message>
+ <message>
+ <source>Check this to use repository during fetch.</source>
+ <translation>가져오는 중에 저장소를 사용하려면 확인하십시오.</translation>
+ </message>
+ <message>
+ <source>Add the username to authenticate on the server.</source>
+ <translation>서버를 인증하려면 사용자 이름을 추가하십시오.</translation>
+ </message>
+ <message>
+ <source>Add the password to authenticate on the server.</source>
+ <translation>서버를 인증하려면 비밀번호를 추가하십시오.</translation>
+ </message>
+ <message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>유효한 저장소가 포함되어 있는 서버 URL입니다.</translation>
+ </message>
+ <message>
+ <source>An error occurred while testing this repository.</source>
+ <translation>이 저장소를 테스트하는 중에 오류가 발생했습니다.</translation>
+ </message>
+ <message>
+ <source>The repository was tested successfully.</source>
+ <translation>저장소를 성공적으로 테스트했습니다.</translation>
+ </message>
+ <message>
+ <source>Do you want to disable the repository?</source>
+ <translation>이 저장소를 비활성화하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>Do you want to enable the repository?</source>
+ <translation>이 저장소를 활성화하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>Hide Passwords</source>
+ <translation>비밀번호 숨기기</translation>
+ </message>
+ <message>
+ <source>Use</source>
+ <translation>사용</translation>
+ </message>
+ <message>
+ <source>Username</source>
+ <translation>사용자 이름</translation>
+ </message>
+ <message>
+ <source>Password</source>
+ <translation>비밀번호</translation>
+ </message>
+ <message>
+ <source>Repository</source>
+ <translation>저장소</translation>
+ </message>
+ <message>
+ <source>Default repositories</source>
+ <translation>기본 저장소</translation>
+ </message>
+ <message>
+ <source>Temporary repositories</source>
+ <translation>임시 저장소</translation>
+ </message>
+ <message>
+ <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>QInstaller</name>
+ <message>
+ <source>Invalid content in &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;에 올바르지 않은 내용이 있음</translation>
+ </message>
+ <message>
+ <source>No marker found, stopped after %1.</source>
+ <translation>마커를 찾을 수 없습니다. %1 이후에 중지되었습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open 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>Read failed after %1 bytes: %2</source>
+ <translation>%1바이트 이후 읽을 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Copy failed: %1</source>
+ <translation>복사할 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Write failed after %1 bytes: %2</source>
+ <translation>%1바이트 이후 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>bytes</source>
+ <translation>바이트</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>&quot;1%&quot; 파일을 제거할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot copy file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 복사할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Cannot move file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 이동할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot open temporary file: %1</source>
+ <translation>임시 파일을 열 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open temporary file for template %1: %2</source>
+ <translation>%1 템플릿에 대한 임시 파일을 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 복사할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 복사할 수 없음:</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Error acquiring admin rights</source>
+ <translation>관리자 권한 획득 중에 오류 발생</translation>
+ </message>
+ <message>
+ <source>Another %1 instance is already running. Wait until it finishes, close it, or restart your system.</source>
+ <translation>다른 %1 인스턴스가 이미 실행 중입니다. 완료될 때까지 기다린 다음 닫거나 시스템을 다시 시작하십시오.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as updater.</source>
+ <translation>설치 관리자 바이너리를 업데이터로서 시작할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as package manager.</source>
+ <translation>설치 관리자 바이너리를 패키지 관리자로서 시작할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as uninstaller.</source>
+ <translation>설치 관리자 바이너리를 설치 제거 관리자로서 시작할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;addRepository&apos;.</source>
+ <translation>옵션 &apos;addRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;addTempRepository&apos;.</source>
+ <translation>옵션 &apos;addTempRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;setTempRepository&apos;.</source>
+ <translation>옵션 &apos;setTempRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
+ <translation>옵션 &apos;installCompressedRepository&apos;에 대한 저장소 목록이 비어있습니다.</translation>
+ </message>
+ <message>
+ <source>The file %1 does not exist.</source>
+ <translation>%1 파일이 없습니다.</translation>
+ </message>
+ <message>
+ <source>Arguments missing for option %1</source>
+ <translation>옵션 %1에 대한 인수가 누락되었습니다.</translation>
+ </message>
+ <message>
+ <source>Invalid button value %1 </source>
+ <translation>올바르지 않은 버튼 값 %1 </translation>
+ </message>
+ <message>
+ <source>Incorrect arguments for %1</source>
+ <translation>%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>현재 사용자가 &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>
+ <message>
+ <source>Cannot seek to %1 to read the embedded meta data count.</source>
+ <translation>%1을(를) 찾아서 내장된 메타데이터 개수를 읽을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot seek to %1 to read the resource collection segment.</source>
+ <translation>%1을(를) 찾아서 리소스 컬렉션 세그먼트를 읽을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Unexpected mismatch of meta resources. Read %1, expected: %2.</source>
+ <translation>메타 리소스에 예상과 다르게 일치하지 않는 사항이 있습니다. 읽음: %1, 예상: %2.</translation>
+ </message>
+</context>
+<context>
+ <name>BinaryContent</name>
+ <message>
+ <source>Cannot seek to %1 to read the operation data.</source>
+ <translation>%1을(를) 찾아서 작업 데이터를 읽을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot seek to %1 to read the resource collection block.</source>
+ <translation>%1을(를) 찾아서 리소스 컬렉션 블록을 읽을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open meta resource %1.</source>
+ <translation>메타 소스(%1)를 열 수 없습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Resource</name>
+ <message>
+ <source>Cannot open resource %1 for reading.</source>
+ <translation>리소스(%1)를 읽기 위해 열 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Read failed after %1 bytes: %2</source>
+ <translation>%1바이트 이후 읽을 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Write failed after %1 bytes: %2</source>
+ <translation>%1바이트 이후 쓸 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>ResourceCollectionManager</name>
+ <message>
+ <source>Cannot open resource %1: %2</source>
+ <translation>리소스(%1)를 열 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Component</name>
+ <message>
+ <source>Components cannot have children in updater mode.</source>
+ <translation>업데이터 모드에서는 구성요소에 하위 요소가 있으면 안 됩니다.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>오류</translation>
+ </message>
+ <message>
+ <source>Error: Operation %1 does not exist.</source>
+ <translation>오류: %1 작업이 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve isDefault in %1</source>
+ <translation>%1의 isDefault를 해결할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Update Info: </source>
+ <translation>업데이트 정보: </translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Component is marked for installation.</source>
+ <translation>구성요소가 설치를 위해 표시되었습니다.</translation>
+ </message>
+ <message>
+ <source>Component is marked for uninstallation.</source>
+ <translation>구성요소가 설치 제거를 위해 표시되었습니다.</translation>
+ </message>
+ <message>
+ <source>Component is installed.</source>
+ <translation>구성요소가 설치되었습니다.</translation>
+ </message>
+ <message>
+ <source>Component is not installed.</source>
+ <translation>구성요소가 설치되지 않았습니다.</translation>
+ </message>
+ <message>
+ <source>Component Name</source>
+ <translation>구성요소 이름</translation>
+ </message>
+ <message>
+ <source>Action</source>
+ <translation>조치</translation>
+ </message>
+ <message>
+ <source>Installed Version</source>
+ <translation>설치된 버전</translation>
+ </message>
+ <message>
+ <source>New Version</source>
+ <translation>새 버전</translation>
+ </message>
+ <message>
+ <source>Release Date</source>
+ <translation>출시일</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>크기</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ComponentSelectionPage</name>
+ <message>
+ <source>Default</source>
+ <translation>기본:</translation>
+ </message>
+ <message>
+ <source>Select default components in the tree view.</source>
+ <translation>트리 보기에서 기본 구성요소를 선택합니다.</translation>
+ </message>
+ <message>
+ <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>Select All</source>
+ <translation>모두 선택</translation>
+ </message>
+ <message>
+ <source>Select all components in the tree view.</source>
+ <translation>트리 보기에서 모든 구성요소를 선택합니다.</translation>
+ </message>
+ <message>
+ <source>Deselect All</source>
+ <translation>모두 선택 해제</translation>
+ </message>
+ <message>
+ <source>Deselect all components in the tree view.</source>
+ <translation>트리 보기에서 모든 구성요소를 선택 해제합니다.</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>
+ </message>
+ <message>
+ <source>Filter the enabled repository categories</source>
+ <translation>활성화된 저장소 범주를 필터링합니다.</translation>
+ </message>
+ <message>
+ <source>This component will occupy approximately %1 on your hard disk drive.</source>
+ <translation>이 구성요소는 하드디스크 드라이브의 약 %1 정도를 차지합니다.</translation>
+ </message>
+ <message>
+ <source>Open File</source>
+ <translation>파일 열기</translation>
+ </message>
+ <message>
+ <source>Select Components</source>
+ <translation>구성요소 선택</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to update.</source>
+ <translation>업데이트하려는 구성요소를 선택하십시오.</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to install.</source>
+ <translation>설치하려는 구성요소를 선택하십시오.</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to uninstall.</source>
+ <translation>설치 제거하려는 구성요소를 선택하십시오.</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>설치할 구성요소를 선택하십시오. 설치 제거할 설치된 구성요소를 선택 해제하십시오. 이미 설치된 모든 구성요소는 업데이트되지 않습니다.</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>
+ <message>
+ <source>Filter</source>
+ <translation>필터</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">구성요소 정보</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>오류</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;저장할 설치 관리자 키 이름&gt; &lt;실행 가능&gt; [argument1] [argument2] [...]</translation>
+ </message>
+ <message>
+ <source>Needed installer object in %1 operation is empty.</source>
+ <translation>&quot;%1&quot; 작업에 필요한 설치 개체가 비어 있습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot save the output of &quot;%1&quot; to an empty installer key value.</source>
+ <translation>빈 설치 관리자 키 값에 &quot;%1&quot;의 출력을 저장할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Failed to run command: &quot;%1&quot;: %2</source>
+ <translation>명령을 수행할 수 없습니다.: &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CopyDirectoryOperation</name>
+ <message>
+ <source>&lt;source&gt; &lt;target&gt; [&quot;forceOverwrite&quot;]</source>
+ <translation>&lt;소스&gt; &lt;대상&gt; [&quot;forceOverwrite&quot;]</translation>
+ </message>
+ <message>
+ <source>Invalid argument in %1: Third argument needs to be forceOverwrite, if specified.</source>
+ <translation>%1에 유효하지 않은 인수: 지정될 경우 세 번째 인수는 forceOverwrite해야 합니다.</translation>
+ </message>
+ <message>
+ <source>Invalid argument in %1: Directory &quot;%2&quot; is invalid.</source>
+ <translation>%1에 유효하지 않은 인수: &quot;%2&quot; 디렉터리가 유효하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;을(를) 덮어쓸 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 복사할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음:</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CopyFileTask</name>
+ <message>
+ <source>Invalid task item count.</source>
+ <translation>작업 아이템 개수가 유효하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open 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>Writing to file &quot;%1&quot; failed: %2</source>
+ <translation>&quot;%1&quot; 파일에 쓰기 실패: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateDesktopEntryOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 백업할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite file &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;을(를) 덮어쓸 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot write desktop entry to &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;에 데스크톱 항목을 쓸 수 없습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateLinkOperation</name>
+ <message>
+ <source>Cannot create link from &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 대한 링크를 생성할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove link from &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 대한 링크를 제거할 수 없습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateLocalRepositoryOperation</name>
+ <message>
+ <source>Cannot set permissions for file &quot;%1&quot;.</source>
+ <translation>파일 &quot;%1&quot;에 대한 권한을 설정할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>파일 &quot;%1&quot;을(를) &quot;%2&quot;(으)로 옮길 수 없습니다. %3</translation>
+ </message>
+ <message>
+ <source>Installer at &quot;%1&quot; needs to be an offline one.</source>
+ <translation>&quot;%1&quot;의 설치 관리자는 오프라인용이어야 합니다.</translation>
+ </message>
+ <message>
+ <source>Cannot create path &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 경로를 생성할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 디렉터리를 제거할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading.</source>
+ <translation>&quot;%1&quot; 파일을 읽기 위해 열 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot read file &quot;%1&quot;: %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 create target directory: &quot;%1&quot;.</source>
+ <translation>대상 디렉터리를 생성할 수 없음: &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught: %1.</source>
+ <translation>알 수 없는 예외 발생: %1.</translation>
+ </message>
+ <message>
+ <source>Removing file &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 파일을 제거합니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음:</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <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>
+ <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;대상&gt; &lt;링크 위치&gt; [대상 인수] [&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>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;을(를) 덮어쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create link &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 링크를 생성할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::DownloadArchivesJob</name>
+ <message>
+ <source>Canceled</source>
+ <translation>취소됨</translation>
+ </message>
+ <message>
+ <source>Downloading hash signature failed.</source>
+ <translation>해시 서명을 다운로드하지 못했습니다.</translation>
+ </message>
+ <message>
+ <source>Download Error</source>
+ <translation>다운로드 오류</translation>
+ </message>
+ <message>
+ <source>Cannot download archive %1: %2</source>
+ <translation>%1 아카이브를 다운로드할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot fetch archives: %1
+Error while loading %2</source>
+ <translation>아카이브를 가져올 수 없음: %1
+%2 로드 중 오류 발생</translation>
+ </message>
+ <message>
+ <source>Downloading archive &quot;%1&quot; for component %2.</source>
+ <translation>구성요소 %2용 아카이브 &quot;%1&quot; 다운로드 중입니다.</translation>
+ </message>
+ <message>
+ <source>Scheme %1 not supported (URL: %2).</source>
+ <translation>%1 스킴을 지원하지 않습니다(URL: %2).</translation>
+ </message>
+ <message>
+ <source>Cannot find component for %1.</source>
+ <translation>%1용 구성요소를 찾을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1/%2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 다운로드가 완료되었습니다.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n일, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n시간, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n분</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n초</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - 남은 시간: %1%2%3%4</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - 남은 시간: 알 수 없음</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>아카이브:</translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <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>
+ <name>QInstaller::Downloader</name>
+ <message>
+ <source>Target file &quot;%1&quot; already exists but is not a file.</source>
+ <translation>대상 파일(&quot;%1&quot;)이 이미 있지만 파일이 아닙니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <extracomment>%2 is a sentence describing the error</extracomment>
+ <translation>&quot;%1&quot; 파일을 쓰기 위해 열 수 없음: %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; 파일을 쓰기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Writing to file &quot;%1&quot; failed: %2</source>
+ <extracomment>%2 is a sentence describing the error.</extracomment>
+ <translation>&quot;%1&quot; 파일에 쓰기 실패: %2</translation>
+ </message>
+ <message>
+ <source>Redirect loop detected for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;에 대한 리디렉션 루프가 감지되었습니다.</translation>
+ </message>
+ <message>
+ <source>Network error while downloading &apos;%1&apos;: %2.</source>
+ <translation>&quot;%1&quot; 다운로드 중에 네트워크 오류 발생: %2.</translation>
+ </message>
+ <message>
+ <source>Unknown network error while downloading &quot;%1&quot;.</source>
+ <extracomment>%1 is a sentence describing the error</extracomment>
+ <translation>&quot;%1&quot; 다운로드 중에 네트워크 오류 발생:</translation>
+ </message>
+ <message>
+ <source>Network transfers canceled.</source>
+ <translation>네트워크 전송이 취소되었습니다.</translation>
+ </message>
+ <message>
+ <source>Pause and resume not supported by network transfers.</source>
+ <translation>네트워크 전송은 일시 중지하거나 다시 시작할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Invalid source URL &quot;%1&quot;: %2</source>
+ <extracomment>%2 is a sentence describing the error</extracomment>
+ <translation>유효하지 않은 소스 URL &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>AuthenticationRequiredException</name>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%2의 %1</translation>
+ </message>
+ <message>
+ <source>Proxy requires authentication.</source>
+ <translation>프록시는 인증이 필요합니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ElevatedExecuteOperation</name>
+ <message>
+ <source>Cannot start detached: &quot;%1&quot;</source>
+ <translation>분리된 항목을 시작할 수 없음: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot start: &quot;%1&quot;: %2</source>
+ <translation>시작할 수 없음: &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Program crashed: &quot;%1&quot;</source>
+ <translation>프로그램이 충돌함: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Execution failed (Unexpected exit code: %1): &quot;%2&quot;</source>
+ <translation>실행하지 못함(예상치 못한 종료 코드: %1): &quot;%2&quot;</translation>
+ </message>
+</context>
+<context>
+ <name>UpdateOperation</name>
+ <message>
+ <source>Cannot write to registry path %1.</source>
+ <translation>레지스트리 경로(%1)를 쓸 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Registry path %1 is not writable.</source>
+ <translation>레지스트리 경로(%1)를 쓸 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>exactly %1</source>
+ <translation>정확히 %1</translation>
+ </message>
+ <message>
+ <source>at least %1</source>
+ <translation>최소 %1</translation>
+ </message>
+ <message>
+ <source>not more than %1</source>
+ <translation>%1 이하</translation>
+ </message>
+ <message>
+ <source>%1 or %2</source>
+ <translation>%1 또는 %2</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1~%2</translation>
+ </message>
+ <message numerus="yes">
+ <source>Invalid arguments in %1: %n arguments given, %2 arguments expected.</source>
+ <translation>
+ <numerusform>%1에 유효하지 않은 인수: %n개의 인수 입력, %2개의 인수 필요.</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Invalid arguments in %1: %n arguments given, %2 arguments expected in the form: %3.</source>
+ <translation>
+ <numerusform>%1에 유효하지 않은 인수: %n개의 인수 입력, 양식에 %2개의 인수 필요: %3.</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Renaming file &quot;%1&quot; to &quot;%2&quot; failed: %3</source>
+ <translation>파일 명을 &quot;%1&quot;에서 &quot;%2&quot;(으)로 변경하늦 중에 오류 발생: %3</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation</name>
+ <message>
+ <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>
+ <message>
+ <source>Cannot get package manager core.</source>
+ <translation>패키지 관리자 코어를 가져올 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>This process should be stopped before continuing: %1</source>
+ <translation>계속하기 전에 중지해야 하는 프로세스: %1</translation>
+ </message>
+ <message>
+ <source>These processes should be stopped before continuing: %1</source>
+ <translation>계속하기 전에 중지해야 하는 프로세스: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::GlobalSettingsOperation</name>
+ <message>
+ <source>Settings are not writable.</source>
+ <translation>설정을 쓸 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Failed to write settings.</source>
+ <translation>설정을 쓰지 못했습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>InstallerCalculator</name>
+ <message>
+ <source>Components added as automatic dependencies:</source>
+ <translation>구성요소가 자동 종속성으로 추가됨:</translation>
+ </message>
+ <message>
+ <source>Components added as dependency for &quot;%1&quot;:</source>
+ <translation>구성요소가 &quot;%1&quot;용 자동 종속성으로 추가됨:</translation>
+ </message>
+ <message>
+ <source>Components that have resolved dependencies:</source>
+ <translation>종속성을 해결한 구성요소:</translation>
+ </message>
+ <message>
+ <source>Selected components without dependencies:</source>
+ <translation>종속성 없이 선택된 구성요소:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component &quot;%1&quot; already added with reason: &quot;%2&quot;</source>
+ <translation>회귀가 감지됨. 구성요소(&quot;%1&quot;)가 다음 사유로 이미 추가됨: &quot;%2&quot;</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>&lt;source path&gt; [vendor prefix]</source>
+ <translation>&lt;소스 경로&gt; [벤더 접두사]</translation>
+ </message>
+ <message>
+ <source>Invalid Argument: source directory must not be empty.</source>
+ <translation>유효하지 않은 인수: 소스 디렉터리를 입력해야 합니다.</translation>
+ </message>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 백업할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;을(를) 덮어쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Failed to copy file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 복사할 수 없음: %2</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Internal code: %1</source>
+ <translation>내부 코드: %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>메모리 부족</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>오류: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve property %1 for item %2.</source>
+ <translation>항목 %2에 대한 %1 속성을 검색할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Property %1 for item %2 not of type VT_FILETIME but %3.</source>
+ <translation>항목 %2에 대한 %1 속성은 VT_FILETIME 유형이 아니라 %3입니다.</translation>
+ </message>
+ <message>
+ <source>Cannot convert UTC file time to system time.</source>
+ <translation>UTC 파일 시간을 시스템 시간으로 변환할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot load codecs.</source>
+ <translation>코덱을 로드할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 아카이브를 열 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve number of items in archive.</source>
+ <translation>아카이브의 항목 개수를 검색할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve path of archive item &quot;%1&quot;.</source>
+ <translation>아카이브 항목 &quot;%1&quot;의 경로를 검색할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught (%1).</source>
+ <translation>알 수 없는 예외가 발생했습니다(%1).</translation>
+ </message>
+ <message>
+ <source>Cannot create temporary file: %1</source>
+ <translation>임시 파일을 생성할 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Unsupported archive type.</source>
+ <translation>아카이브 유형이 지원되지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;</source>
+ <translation>&quot;%1&quot; 아카이브를 생성할 수 없음</translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 아카이브를 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove old archive &quot;%1&quot;: %2</source>
+ <translation>이전 아카이브 &quot;%1&quot; 제거 불가: %2</translation>
+ </message>
+ <message>
+ <source>Cannot rename temporary archive &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>임시 아카이브 &quot;%1&quot;의 이름을 &quot;%2&quot;(으)로 변경할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught (%1)</source>
+ <translation>알 수 없는 예외 발생(%1)</translation>
+ </message>
+</context>
+<context>
+ <name>DirectoryGuard</name>
+ <message>
+ <source>Path &quot;%1&quot; exists but is not a directory.</source>
+ <translation>&quot;%1&quot; 경로가 존재하지만 디렉터리가 아닙니다.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>ExtractCallbackImpl</name>
+ <message>
+ <source>Cannot retrieve path of archive item %1.</source>
+ <translation>아카이브 항목 &quot;%1&quot;의 경로를 검색할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove already existing symlink %1.</source>
+ <translation>이미 존재하는 symlink %1을(를) 제거할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <translation>&quot;%1&quot; 파일을 쓰기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create symlink at &quot;%1&quot;. Another one is already existing.</source>
+ <translation>&quot;%1&quot;에서 symlink를 생성할 수 없습니다. 다른 symlink가 이미 있습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot read symlink target from file &quot;%1&quot;.</source>
+ <translation>파일 &quot;%1&quot;에서 symlink 대상을 읽을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot create symlink at %1: %2</source>
+ <translation>&quot;%1&quot;에서 symlink를 생성할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LicenseOperation</name>
+ <message>
+ <source>No license files found to copy.</source>
+ <translation>복사할 라이선스 파일을 찾을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Needed installer object in %1 operation is empty.</source>
+ <translation>&quot;%1&quot; 작업에 필요한 설치 개체가 비어 있습니다.</translation>
+ </message>
+ <message>
+ <source>Can not write license file &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 라이선스 파일을 쓸 수 없습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LineReplaceOperation</name>
+ <message>
+ <source>Invalid argument in %1: Empty search argument is not supported.</source>
+ <translation>%1에 유효하지 않은 인수: 빈 인수는 지원되지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open 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>
+</context>
+<context>
+ <name>QInstaller::MetadataJob</name>
+ <message>
+ <source>Missing package manager core engine.</source>
+ <translation>패키지 관리자 코어 엔진이 누락되었습니다.</translation>
+ </message>
+ <message>
+ <source>Unpacking compressed repositories. This may take a while...</source>
+ <translation>압축된 저장소의 압축을 해제합니다. 약간의 시간이 걸릴 수 있습니다...</translation>
+ </message>
+ <message>
+ <source>Metadata download canceled.</source>
+ <translation>메타데이터 다운로드가 취소되었습니다.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during extracting.</source>
+ <translation>추출 중에 알 수 없는 예외가 발생했습니다.</translation>
+ </message>
+ <message>
+ <source>Missing proxy credentials.</source>
+ <translation>프록시 자격 증명이 누락되었습니다.</translation>
+ </message>
+ <message>
+ <source>Authentication failed.</source>
+ <translation>인증하지 못했습니다.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during download.</source>
+ <translation>다운로드 중에 알 수 없는 예외가 발생했습니다.</translation>
+ </message>
+ <message>
+ <source>Failure to fetch repositories.</source>
+ <translation>저장소를 가져올 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Extracting meta information...</source>
+ <translation>메타 정보 추출 중...</translation>
+ </message>
+ <message>
+ <source>Checksum mismatch detected for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;에 대한 체크섬 불일치가 감지되었습니다.</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %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>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::FileTaskObserver</name>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1/%2</translation>
+ </message>
+ <message>
+ <source>%1 received.</source>
+ <translation>%1을(를) 받았습니다.</translation>
+ </message>
+ <message>
+ <source>(%1/sec)</source>
+ <translation>(%1/초)</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n일, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n시간, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n분</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n초</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - 남은 시간: %1%2%3%4</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - 남은 시간: 알 수 없음</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PackageManagerCore</name>
+ <message>
+ <source>Error writing Maintenance Tool</source>
+ <translation>유지 보수 도구를 쓰는 중에 오류 발생</translation>
+ </message>
+ <message>
+ <source>Downloading packages...</source>
+ <translation>패키지 다운로드 중...</translation>
+ </message>
+ <message>
+ <source>Installation canceled by user.</source>
+ <translation>사용자가 설치를 취소했습니다.</translation>
+ </message>
+ <message>
+ <source>All downloads finished.</source>
+ <translation>모든 다운로드가 완료되었습니다.</translation>
+ </message>
+ <message>
+ <source>Canceling the Installer</source>
+ <translation>설치 관리자 취소 중</translation>
+ </message>
+ <message>
+ <source>Authentication Error</source>
+ <translation>인증 오류</translation>
+ </message>
+ <message>
+ <source>Some components could not be removed completely because administrative rights could not be acquired: %1.</source>
+ <translation>관리 권한을 획득하지 못해 일부 구성요소를 완전히 제거하지 못했습니다. %1.</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>알 수 없는 오류입니다.</translation>
+ </message>
+ <message>
+ <source>Some components could not be removed completely because an unknown error happened.</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>Error</source>
+ <translation>오류</translation>
+ </message>
+ <message>
+ <source>The directory you selected already exists and contains an installation. Choose a different target for installation.</source>
+ <translation>선택한 디렉터리가 이미 존재하며 설치 항목도 포함되어 있습니다. 설치하려면 다른 디렉토리를 선택하십시오.</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>경고</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>파일이 이미 있는 기존 디렉터리를 설치 디렉토리로 선택하셨습니다.
+이 애플리케이션을 제거할 때 디렉토리가 완전히 삭제되오니 유의하십시오.
+설치가 실패할 수 있으므로 이 디렉토리에 설치하는 것은 권장하지 않습니다.
+계속하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>You have selected an existing file or symlink, please choose a different target for installation.</source>
+ <translation>기존 파일 또는 symlink를 선택하셨습니다. 설치할 다른 대상을 선택하십시오.</translation>
+ </message>
+ <message>
+ <source>The installation path cannot be empty, please specify a valid directory.</source>
+ <translation>설치 경로가 비어 있으면 안 됩니다. 유효한 디렉터리를 선택하십시오.</translation>
+ </message>
+ <message>
+ <source>The installation path cannot be relative, please specify an absolute path.</source>
+ <translation>상대적인 경로를 설치 경로로 지정하면 안 됩니다. 절대 경로를 지정하십시오.</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>설치 경로 또는 디렉터리에 ASCII 문자가 아닌 문자가 포함되어 있습니다. 현재 이는 지원되지 않습니다! 다른 설치 경로나 디렉토리를 선택하십시오.</translation>
+ </message>
+ <message>
+ <source>As the install directory is completely deleted, installing in %1 is forbidden.</source>
+ <translation>설치 경로가 완전히 삭제되었으므로 %1에 설치할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is too long, please make sure to specify a valid path.</source>
+ <translation>입력하신 경로가 너무 깁니다. 유효한 경로를 지정하십시오.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is not valid, please make sure to specify a valid target.</source>
+ <translation>입력하신 경로가 유효하지 않습니다. 유효한 경로를 지정하십시오.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is not valid, please make sure to specify a valid drive.</source>
+ <translation>입력하신 경로가 유효하지 않습니다. 유효한 드라이브를 지정하십시오.</translation>
+ </message>
+ <message>
+ <source>The installation path must not end with &apos;.&apos;, please specify a valid directory.</source>
+ <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>
+ </message>
+ <message>
+ <source>Application not running in Package Manager mode.</source>
+ <translation>패키지 관리자 모드에서 애플리케이션이 실행되지 않고 있습니다.</translation>
+ </message>
+ <message>
+ <source>No installed packages found.</source>
+ <translation>설치된 패키지를 찾을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Application running in Uninstaller mode.</source>
+ <translation>애플리케이션이 설치 제거 관리자 모드로 실행 중입니다.</translation>
+ </message>
+ <message>
+ <source>There is an important update available, please run the updater first.</source>
+ <translation>중요한 업데이트가 있습니다. 업데이터를 먼저 실행하십시오.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve all dependencies.</source>
+ <translation>모든 종속성을 해결할 수 없습니다.</translation>
+ </message>
+ <message>
+ <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>
+ </message>
+ <message>
+ <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>
+ </message>
+ <message>
+ <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>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
+ <translation>명령줄에서 실행할 때 접근 원한을 상승시킬 수 없습니다. 관리자로서 애플리케이션을 재시작하십시오.</translation>
+ </message>
+ <message>
+ <source>Error while elevating access rights.</source>
+ <translation>접근 권한을 상승시키는 중에 오류가 발생했습니다.</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>디스크 공간이 부족하여 임시 파일과 설치 파일을 저장할 수 없습니다. %1은(는) 사용 가능하지만 최소한 %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>디스크 공간이 부족하여 선택한 구성요소를 모두 저장할 수 없습니다! %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>
+ <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>설치를 위해 선택한 볼륨은 설치 공간이 충분한 것으로 보이지만, 설치 후에 남은 공간이 100MB 미만일 것으로 예상됩니다.</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>
+ <message>
+ <source>Installation will use %1 of disk space.</source>
+ <translation>설치 관리자가 디스크 공간의 %1을(를) 사용할 것입니다.</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Unresolved dependencies</source>
+ <translation>해결되지 않은 종속성</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>오류</translation>
+ </message>
+ <message>
+ <source>Access error</source>
+ <translation>접근 오류</translation>
+ </message>
+ <message>
+ <source>Format error</source>
+ <translation>형식 오류</translation>
+ </message>
+ <message>
+ <source>Cannot write installer configuration to %1: %2</source>
+ <translation>설치 관리자 구성을 %1에 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Stop Processes</source>
+ <translation>프로세스 중지</translation>
+ </message>
+ <message>
+ <source>These processes should be stopped to continue:
+
+%1</source>
+ <translation>계속하기 전에 중지해야 하는 프로세스:
+
+%1</translation>
+ </message>
+ <message>
+ <source>Installation canceled by user</source>
+ <translation>사용자가 설치를 취소함</translation>
+ </message>
+ <message>
+ <source>Retry count exceeded</source>
+ <translation>재시도 횟수 초과</translation>
+ </message>
+ <message>
+ <source>Writing maintenance tool.</source>
+ <translation>유지 보수 도구를 쓰는 중입니다.</translation>
+ </message>
+ <message>
+ <source>Failed to seek in file %1: %2</source>
+ <translation>%1 파일에서 찾지 못함: %2</translation>
+ </message>
+ <message>
+ <source>Maintenance tool is not a bundle</source>
+ <translation>유지 보수 도구가 번들이 아님</translation>
+ </message>
+ <message>
+ <source>Cannot remove data file &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 데이터 파일을 제거할 수 없음 %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool data to %1: %2</source>
+ <translation>%1에 유지 보수 도구 데이터를 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool to &quot;%1&quot;: %2</source>
+ <translation>%1에 유지 보수 도구를 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
+ <translation>임시 디렉터리 &quot;%1&quot; 제거가 불가능합니다. %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool binary data to %1: %2</source>
+ <translation>%1에 유지 보수 도구 바이너리 데이터를 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Writing offline base binary.</source>
+ <translation>오프라인 기본 바이너리를 쓰는 중입니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 디렉터리를 생성할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot write offline binary to &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;에 오프라인 바이너리를 쓸 수 없습니다. %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary file &quot;%1&quot;: %2</source>
+ <translation>임시 디렉터리 &quot;%1&quot; 제거가 불가능합니다. %2</translation>
+ </message>
+ <message>
+ <source>Variable &apos;TargetDir&apos; not set.</source>
+ <translation>변수 &apos;TargetDir&apos;이 설정되지 않았습니다.</translation>
+ </message>
+ <message>
+ <source>Preparing the installation...</source>
+ <translation>설치 준비 중...</translation>
+ </message>
+ <message>
+ <source>It is not possible to install from network location</source>
+ <translation>네트워크 위치에서 설치할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Creating local repository</source>
+ <translation>로컬 저장소 생성 중</translation>
+ </message>
+ <message>
+ <source>Creating Maintenance Tool</source>
+ <translation>유지 보수 도구 생성 중</translation>
+ </message>
+ <message>
+ <source>Installation finished!</source>
+ <translation>설치가 완료되었습니다!</translation>
+ </message>
+ <message>
+ <source>Installation aborted!</source>
+ <translation>설치가 중단되었습니다!</translation>
+ </message>
+ <message>
+ <source>It is not possible to run that operation from a network location</source>
+ <translation>네트워크 위치에서 이 작업을 실행할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Removing deselected components...</source>
+ <translation>선택 취소한 구성요소 제거 중...</translation>
+ </message>
+ <message>
+ <source>Update finished!</source>
+ <translation>업데이트가 완료되었습니다!</translation>
+ </message>
+ <message>
+ <source>Update aborted!</source>
+ <translation>업데이트가 중단되었습니다!</translation>
+ </message>
+ <message>
+ <source>Removal completed successfully.</source>
+ <translation>성공적으로 설치 제거했습니다.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>설치 제거가 중단되었습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot create target directory for installer.</source>
+ <translation>설치 관리자에 사용할 대상 디렉터리를 생성할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Preparing offline generation...</source>
+ <translation>오프라인 생성 준비 중...</translation>
+ </message>
+ <message>
+ <source>Preparing installer configuration...</source>
+ <translation>설치 관리자 구성 요소 준비 중...</translation>
+ </message>
+ <message>
+ <source>Creating the installer...</source>
+ <translation>설치 관리자 생성 중...</translation>
+ </message>
+ <message>
+ <source>Failed to create offline installer. %1</source>
+ <translation>오프라인 설치 관리자를 생성할 수 없습니다. %1</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary directory &quot;%1&quot;.</source>
+ <translation>임시 디렉터리 &quot;%1&quot; 제거에 실패했습니다.</translation>
+ </message>
+ <message>
+ <source>Offline generation completed successfully.</source>
+ <translation>성공적으로 오프라인 생성을 완료했습니다.</translation>
+ </message>
+ <message>
+ <source>Offline generation aborted!</source>
+ <translation>오프라인 생성이 중단되었습니다!</translation>
+ </message>
+ <message>
+ <source>Installing component %1</source>
+ <translation>구성요소 %1 설치 중</translation>
+ </message>
+ <message>
+ <source>Installer Error</source>
+ <translation>설치 관리자 오류</translation>
+ </message>
+ <message>
+ <source>Error during installation process (%1):
+%2</source>
+ <translation>설치 프로세스 중 오류 발생(%1):
+%2</translation>
+ </message>
+ <message>
+ <source>Done</source>
+ <translation>완료</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>설치 제거를 준비할 수 없음</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>설치 제거를 시작할 수 없음</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>설치 해제 프로세스 중에 오류 발생:
+%1</translation>
+ </message>
+ <message>
+ <source>Unknown error</source>
+ <translation>알 수 없는 오류</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve remote tree %1.</source>
+ <translation>원격 트리 %1을(를) 검색할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Failure to read packages from %1.</source>
+ <translation>%1에서 패키지를 읽을 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve meta information: %1</source>
+ <translation>메타 정보를 검색할 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot find any update source information.</source>
+ <translation>어떠한 업데이트 소스 정보도 추가할 수 없습니다.</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>%1 Setup</source>
+ <translation>%1 설정</translation>
+ </message>
+ <message>
+ <source>Maintain %1</source>
+ <translation>%1 유지</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the installation process?</source>
+ <translation>설치 프로세스를 취소하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>설치 제거 프로세스를 취소하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the installer application?</source>
+ <translation>설치 관리자 애플리케이션을 종료하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the uninstaller application?</source>
+ <translation>설치 제거 관리자 애플리케이션을 종료하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the maintenance application?</source>
+ <translation>유지 보수 애플리케이션을 종료하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>%1 Question</source>
+ <translation>%1 질문</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>설정</translation>
+ </message>
+ <message>
+ <source>Specify proxy settings and configure repositories for add-on components.</source>
+ <translation>애드온 구성요소를 위한 프록시 설정과 구성 저장소를 지정하십시오.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>오류</translation>
+ </message>
+ <message>
+ <source>It is not possible to install from network location.
+Please copy the installer to a local drive</source>
+ <translation>네트워크 위치에서 설치할 수 없습니다.
+설치 관리자를 로컬 드라이브에 복사하십시오.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::IntroductionPage</name>
+ <message>
+ <source>Welcome</source>
+ <translation>환영</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 Setup.</source>
+ <translation>%1 설정 마법사에 오신 것을 환영합니다.</translation>
+ </message>
+ <message>
+ <source>&amp;Add or remove components</source>
+ <translation>구성요소 추가 또는 제거(&amp;A)</translation>
+ </message>
+ <message>
+ <source>&amp;Update components</source>
+ <translation>구성요소 업데이트(&amp;U)</translation>
+ </message>
+ <message>
+ <source>&amp;Remove all components</source>
+ <translation>모든 구성요소 제거(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote installation sources...</source>
+ <translation>원격 설치 소스에서 정보 검색 중...</translation>
+ </message>
+ <message>
+ <source>At least one valid and enabled repository required for this action to succeed.</source>
+ <translation>이 작업을 성공적으로 수행하려면 최소 1개의 유효하고 활성화된 저장소가 필요합니다.</translation>
+ </message>
+ <message>
+ <source>No updates 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>중요한 업데이트가 있습니다. 먼저 &amp;apos;%1&amp;apos; 을(를) 선택해 주십시오.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LicenseAgreementPage</name>
+ <message>
+ <source>License Agreement</source>
+ <translation>라이선스 계약</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>다음 라이선스 계약을 읽으십시오. 설치를 계속하려면 이 계약 조항에 동의하셔야 합니다.</translation>
+ </message>
+ <message>
+ <source>I accept the license.</source>
+ <translation>라이선스 조항에 동의합니다.</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>다음 라이선스 계약을 읽으십시오. 설치를 계속하려면 이 계약 조항에 동의하셔야 합니다.</translation>
+ </message>
+ <message>
+ <source>I accept the licenses.</source>
+ <translation>이 라이선스에 동의합니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::TargetDirectoryPage</name>
+ <message>
+ <source>Installation Folder</source>
+ <translation>설치 폴더</translation>
+ </message>
+ <message>
+ <source>Please specify the directory where %1 will be installed.</source>
+ <translation>%1이(가) 설치될 디렉터리를 지정하십시오.</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;R)...</translation>
+ </message>
+ <message>
+ <source>Browse file system to choose the installation directory.</source>
+ <translation>파일 시스템을 탐색하여 설치 디렉터리를 선택합니다.</translation>
+ </message>
+ <message>
+ <source>Select Installation Folder</source>
+ <translation>설치 폴더 선택</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::StartMenuDirectoryPage</name>
+ <message>
+ <source>Start Menu shortcuts</source>
+ <translation>메뉴 바로 가기 시작</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>프로그램 바로 가기를 생성하려는 시작 메뉴를 선택합니다. 이름을 직접 입력하여 새 디렉터리를 생성할 수도 있습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ReadyForInstallationPage</name>
+ <message>
+ <source>U&amp;ninstall</source>
+ <translation>설치 제거(&amp;N)</translation>
+ </message>
+ <message>
+ <source>Ready to Uninstall</source>
+ <translation>설치 제거 준비 완료</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>컴퓨터에 %1 제거를 시작할 준비가 되었습니다.&lt;br&gt;&lt;font color=&quot;red&quot;&gt;%2 프로그램 디렉터리는 모두 삭제되며&lt;/font&gt;, 해당 디렉토리에 포함된 모든 콘텐츠도 삭제됩니다!</translation>
+ </message>
+ <message>
+ <source>U&amp;pdate</source>
+ <translation>업데이트(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Ready to Update Packages</source>
+ <translation>패키지 업데이트 준비 완료</translation>
+ </message>
+ <message>
+ <source>All required information is now available to begin updating your installation.</source>
+ <translation>이제 설치 업데이트를 시작할 준비가 되었습니다.</translation>
+ </message>
+ <message>
+ <source>&amp;Install</source>
+ <translation>설치(&amp;I)</translation>
+ </message>
+ <message>
+ <source>Ready to Install</source>
+ <translation>설치 준비 완료</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>U&amp;ninstall</source>
+ <translation>설치 제거(&amp;N)</translation>
+ </message>
+ <message>
+ <source>Uninstalling %1</source>
+ <translation>%1 설치 제거</translation>
+ </message>
+ <message>
+ <source>&amp;Update</source>
+ <translation>업데이트(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Updating components of %1</source>
+ <translation>%1의 구성요소 업데이트 중</translation>
+ </message>
+ <message>
+ <source>&amp;Install</source>
+ <translation>설치(&amp;I)</translation>
+ </message>
+ <message>
+ <source>Installing %1</source>
+ <translation>%1 설치 중</translation>
+ </message>
+ <message>
+ <source>Installing</source>
+ <translation>설치 중</translation>
+ </message>
+ <message>
+ <source>Updating</source>
+ <translation>업데이트 중</translation>
+ </message>
+ <message>
+ <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>Finished the %1 Setup</source>
+ <translation>%1 마법사 완료 중</translation>
+ </message>
+ <message>
+ <source>Finished</source>
+ <translation>완료됨</translation>
+ </message>
+ <message>
+ <source>Click %1 to exit the %2 Setup.</source>
+ <translation>%2 마법사를 종료하려면 %1을(를) 클릭하십시오.</translation>
+ </message>
+ <message>
+ <source>Restart</source>
+ <translation>다시 시작</translation>
+ </message>
+ <message>
+ <source>Run %1 now.</source>
+ <translation>지금 %1을(를) 실행하십시오.</translation>
+ </message>
+ <message>
+ <source>The %1 Setup failed.</source>
+ <translation>%1 마법사가 실패했습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RestartPage</name>
+ <message>
+ <source>Finished the %1 Setup</source>
+ <translation>%1 설정 마법사 완료 중</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PerformInstallationForm</name>
+ <message>
+ <source>&amp;Show Details</source>
+ <translation>상세 정보 표시(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Hide Details</source>
+ <translation>상세 정보 숨기기(&amp;H)</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RegisterFileTypeOperation</name>
+ <message>
+ <source>Registering file types is only supported on Windows.</source>
+ <translation>등록하려는 파일 유형이 Windows에서만 지원됩니다.</translation>
+ </message>
+ <message>
+ <source>Register File Type: Invalid arguments</source>
+ <translation>등록 파일 유형: 유효하지 않은 인수</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteClient</name>
+ <message>
+ <source>Cannot get authorization.</source>
+ <translation>권한 부여를 받을 수 없습니다.</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>설치를 계속하기 위해 필요한 권한 부여를 받을 수 없습니다.
+ 설치를 중단하거나 임시 해결책으로 적절한 권한이 있는 사용자로
+
+%1을(를)
+
+실행한 다음 ‘확인’을 클릭하십시오.</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>설치를 계속하기 위해 필요한 권한 부여를 받을 수 없습니다.
+
+적절한 권한이 있는 사용자로서 설정 프로그램을 시작하십시오.
+또는 요청 시 접근 권한 상승을 수락하십시오.</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>다음 명령 전송 후 모든 데이터를 읽을 수 없음: %1. 예상된 바이트: %2, 수신한 바이트: %3. 오류: %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>빈 검색 인수로 &quot;%1&quot;을(를) 호출하는 검색 인수는 지원되지 않습니다.</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>&quot;%2&quot; 인수로 &quot;%1&quot;을(를) 호출하는 현재 모드는 지원되지 않습니다. 문자열이나 regex를 사용하십시오.</translation>
+ </message>
+ <message>
+ <source>Cannot open 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>
+</context>
+<context>
+ <name>QInstaller::QFileDialogProxy</name>
+ <message>
+ <source>User input is required but the output device is not associated with a terminal.</source>
+ <translation>사용자 입력이 필요하지만 출력 기기가 터미널과 연결되지 않았습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ScriptEngine</name>
+ <message>
+ <source>Cannot open script file at %1: %2</source>
+ <translation>%1에서 스크립트 파일을 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Exception while loading the component script &quot;%1&quot;: %2</source>
+ <translation>구성요소 스크립트 &quot;%1&quot; 로드 중에 예외 발생: %2</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>알 수 없는 오류입니다.</translation>
+ </message>
+ <message>
+ <source>on line number: </source>
+ <translation>온라인 번호: </translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::SelfRestartOperation</name>
+ <message>
+ <source>Installer object needed in operation %1 is empty.</source>
+ <translation>&quot;%1&quot; 작업에 필요한 설치 개체가 비어 있습니다.</translation>
+ </message>
+ <message>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>자가 재시작: 업데이터 또는 패키지 관리자 모드에서만 사용 가능합니다.</translation>
+ </message>
+ <message>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>자가 재시작: 유효하지 않은 인수</translation>
+ </message>
+</context>
+<context>
+ <name>Settings</name>
+ <message>
+ <source>Cannot open settings file %1 for reading: %2</source>
+ <translation>설정 파일 &quot;%1&quot;을(를) 읽기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Categories</source>
+ <translation type="unfinished">범주 선택</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>&quot;%3&quot; 인수가 있는 %2를 호출하는 &quot;%1&quot; 인수가 누락되었습니다.</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>&quot;%2&quot; 인수로 &quot;%1&quot;을(를) 호출하는 현재 모드는 지원되지 않습니다. set, remove, add_array_value or remove_array_value를 사용하십시오.</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>인수는 모두 입력해야 합니다: 소스 &quot;%1&quot;, 대상 &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>대상 파일이 존재하며 제거할 수 없으므로 &quot;%1&quot;에서 &quot;%2&quot;에 파일을 옮길 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>파일 &quot;%1&quot;을(를) &quot;%2&quot;(으)로 옮길 수 없습니다. %3</translation>
+ </message>
+ <message>
+ <source>Moving file &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>파일 &quot;%1&quot;을(를) &quot;%2&quot;으(로) 옮깁니다.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::TestRepository</name>
+ <message>
+ <source>Missing package manager core engine.</source>
+ <translation>패키지 관리자 코어 엔진이 누락되었습니다.</translation>
+ </message>
+ <message>
+ <source>Empty repository URL.</source>
+ <translation>저장소 URL이 비었습니다.</translation>
+ </message>
+ <message>
+ <source>Download canceled.</source>
+ <translation>다운로드가 취소되었습니다.</translation>
+ </message>
+ <message>
+ <source>Timeout while testing repository &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 저장소를 테스트하는 중에 시간이 초과되었습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot parse Updates.xml: %1</source>
+ <translation>Updates.xml을 파싱할 수 없습니다. %1</translation>
+ </message>
+ <message>
+ <source>Cannot open Updates.xml for reading: %1</source>
+ <translation>Updates.xml 파일을 읽기 위해 열 수 없습니다. %1</translation>
+ </message>
+ <message>
+ <source>Authentication failed.</source>
+ <translation>인증하지 못했습니다.</translation>
+ </message>
+ <message>
+ <source>Unknown error while testing repository &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 저장소를 테스트하는 중에 알 수 없는 오류가 발생했습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::FileDownloader</name>
+ <message>
+ <source>Download finished.</source>
+ <translation>다운로드가 완료되었습니다.</translation>
+ </message>
+ <message>
+ <source>Cryptographic hashes do not match.</source>
+ <translation>암호화된 해시가 일치하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Download canceled.</source>
+ <translation>다운로드가 취소되었습니다.</translation>
+ </message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1/%2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 다운로드가 완료되었습니다.</translation>
+ </message>
+ <message>
+ <source>(%1/sec)</source>
+ <translation>(%1/초)</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n일, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n시간, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n분</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n초</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - 남은 시간: %1%2%3%4</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - 남은 시간: 알 수 없음</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::LocalFileDownloader</name>
+ <message>
+ <source>Cannot open 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>Writing to file &quot;%1&quot; failed: %2</source>
+ <translation>&quot;%1&quot; 파일에 쓰기 실패: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::ResourceFileDownloader</name>
+ <message>
+ <source>Cannot read resource file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 리소스 파일을 읽을 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::HttpDownloader</name>
+ <message>
+ <source>Cannot download %1. Writing to file &quot;%2&quot; failed: %3</source>
+ <translation>%1을(를) 다운로드할 수 없습니다. &quot;%2&quot; 파일에 쓰기 실패: %3</translation>
+ </message>
+ <message>
+ <source>Cannot download %1. Cannot create file &quot;%2&quot;: %3</source>
+ <translation>%1을(를) 다운로드할 수 없습니다. &quot;%2&quot; 파일을 생성할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%2의 %1</translation>
+ </message>
+ <message>
+ <source>Authentication request canceled.</source>
+ <translation>인증 요청이 취소되었습니다.</translation>
+ </message>
+ <message>
+ <source>Secure Connection Failed</source>
+ <translation>보안 연결 실패</translation>
+ </message>
+ <message>
+ <source>There was an error during connection to: %1.</source>
+ <translation>다음에 연결 중 오류 발생: %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>서버 구성에 문제가 있거나 타인이 서버를 가장하는 것으로 보입니다.</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>이전에 이 서버에 성공적으로 연결한 적이 있거나 이 서버를 신뢰하는 경우에는 일시적인 오류일 수 있으며, 다시 시도할 수 있습니다.</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Canceled</source>
+ <translation>취소됨</translation>
+ </message>
+</context>
+<context>
+ <name>LocalPackageHub</name>
+ <message>
+ <source>%1 contains invalid content: %2</source>
+ <translation>%1에 올바르지 않은 콘텐츠가 포함됨: %2</translation>
+ </message>
+ <message>
+ <source>The file %1 does not exist.</source>
+ <translation>%1 파일이 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot open %1.</source>
+ <translation>%1을(를) 열 수 없습니다.</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 &apos;Packages&apos;.</source>
+ <translation>%1 루트 요소는 예상하지 못했습니다. &apos;Packages&apos;여야 합니다.</translation>
+ </message>
+</context>
+<context>
+ <name>LockFile</name>
+ <message>
+ <source>Cannot create lock file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일 잠금을 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write PID to lock file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 잠그기 위해 PID를 쓸 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot obtain the lock for file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 위한 잠금을 수행할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot release the lock for file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 위한 잠금을 해제할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::Task</name>
+ <message>
+ <source>%1 started</source>
+ <translation>%1 시작됨</translation>
+ </message>
+ <message>
+ <source>%1 cannot be stopped</source>
+ <translation>%1을(를) 중지할 수 없음</translation>
+ </message>
+ <message>
+ <source>Cannot stop task %1</source>
+ <translation>%1 작업을 중지할 수 없음</translation>
+ </message>
+ <message>
+ <source>%1 cannot be paused</source>
+ <translation>%1을(를) 일시 중지할 수 없음</translation>
+ </message>
+ <message>
+ <source>Cannot pause task %1</source>
+ <translation>%1 작업을 일시 중지할 수 없음</translation>
+ </message>
+ <message>
+ <source>Cannot resume task %1</source>
+ <translation>%1 작업을 다시 시작할 수 없음</translation>
+ </message>
+ <message>
+ <source>%1 done</source>
+ <translation>%1 완료</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::UpdateFinder</name>
+ <message>
+ <source>Cannot access the package information of this application.</source>
+ <translation>이 애플리케이션의 패키지 정보에 액세스할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>No package sources set for this application.</source>
+ <translation>이 애플리케이션에 설정된 패키지 소스가 없습니다.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n update(s) found.</source>
+ <translation>
+ <numerusform>%n개의 업데이트를 찾았습니다.</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Downloading Updates.xml from update sources.</source>
+ <translation>업데이트 소스에서 Updates.xml을 다운로드합니다.</translation>
+ </message>
+ <message>
+ <source>Cannot download package source %1 from &quot;%2&quot;.</source>
+ <translation>&quot;%2&quot;에서 패키지 소스(%1)를 다운로드할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Updates.xml file(s) downloaded from update sources.</source>
+ <translation>업데이트 소스에서 Updates.xml 파일이 다운로드되었습니다.</translation>
+ </message>
+ <message>
+ <source>Computing applicable updates.</source>
+ <translation>적용 가능한 업데이트를 계산합니다.</translation>
+ </message>
+ <message>
+ <source>Application updates computed.</source>
+ <translation>적용 가능한 업데이트를 계산했습니다.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::CopyOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 파일을 백업할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot copy a non-existent file: %1</source>
+ <translation>존재하지 않는 파일을 복사할 수 없음: %1</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 복사할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Cannot delete file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일을 삭제할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file into &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::MoveOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot; 파일을 백업할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>&quot;%1&quot;에서 &quot;%2&quot;에 파일을 복사할 수 없음: %3</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>&quot;1%&quot; 파일을 제거할 수 없음:</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::DeleteOperation</name>
+ <message>
+ <source>Cannot create backup of file &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 파일의 백업을 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::MkdirOperation</name>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot; 디렉터리를 생성할 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>알 수 없는 오류입니다.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <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>
+ </message>
+ <message>
+ <source>The directory does not exist.</source>
+ <translation>이 디렉터리가 존재하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot recreate directory &quot;%1&quot;: %2</source>
+ <translation>&quot;1%&quot; 디렉터리를 다시 생성할 수 없습니다. %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::AppendFileOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %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 find backup file for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;의 백업 파일을 찾을 수 없음:</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음:</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::PrependFileOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %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 open file &quot;%1&quot; for writing: %2</source>
+ <translation>&quot;%1&quot; 파일을 쓰기 위해 열 수 없음: %2</translation>
+ </message>
+ <message>
+ <source>Cannot find backup file for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;의 백업 파일을 찾을 수 없음:</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;.</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음:</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>&quot;%1&quot;의 백업 파일을 복원할 수 없음: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::UpdatesInfoData</name>
+ <message>
+ <source>Updates.xml contains invalid content: %1</source>
+ <translation>Updates.xml 파일에 올바르지 않은 콘텐츠가 포함됨: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read &quot;%1&quot;</source>
+ <translation>&quot;%1&quot;을(를) 읽을 수 없음</translation>
+ </message>
+ <message>
+ <source>Root element %1 unexpected, should be &quot;Updates&quot;.</source>
+ <translation>%1 루트 요소는 예상하지 못했습니다. &apos;Updates&apos;여야 합니다.</translation>
+ </message>
+ <message>
+ <source>ApplicationName element is missing.</source>
+ <translation>ApplicationName 요소가 누락되었습니다.</translation>
+ </message>
+ <message>
+ <source>ApplicationVersion element is missing.</source>
+ <translation>ApplicationVersion 요소가 누락되었습니다.</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without Name</source>
+ <translation>PackageUpdate 요소에 Name이 없음</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without Version</source>
+ <translation>PackageUpdate 요소에 Version이 없음</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without ReleaseDate</source>
+ <translation>PackageUpdate 요소에 ReleaseDate가 없음</translation>
+ </message>
+</context>
+<context>
+ <name>InstallerBase</name>
+ <message>
+ <source>Unable to start installer</source>
+ <translation>설치 관리자를 시작할 수 없음</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>&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 extracting archive &quot;%1&quot;: %2</source>
+ <translation>아카이브 &quot;%1&quot; 추출 중에 오류 발생: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</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>
+</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 b3305c605..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,11 +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>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>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>
@@ -839,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>
@@ -903,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>
@@ -950,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>
@@ -1054,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 +1112,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Nie można usunąć katalogu &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <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>
@@ -1156,6 +1184,66 @@ Błąd podczas wczytywania %2</translation>
<source>Cannot find component for %1.</source>
<translation>Nie można znaleźć elementu dla %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 z %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>Pobrano: %1.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n d, </numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n godz., </numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n min</numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n s</numerusform>
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> — %1%2%3%4 pozostało.</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>
<context>
<name>QInstaller::Downloader</name>
@@ -1225,21 +1313,6 @@ Błąd podczas wczytywania %2</translation>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <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 extracting archive &quot;%1&quot;: %2</source>
- <translation>Błąd podczas wyodrębniania archiwum &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Zarejestrowano nieznany wyjątek podczas wyodrębniania &quot;%1&quot;.</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1312,15 +1385,15 @@ 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>
<source>Finished</source>
- <translation type="unfinished"></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>
@@ -1332,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>
@@ -1373,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>
@@ -1409,13 +1486,13 @@ 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>Dostępna jest ważna aktualizacja. Wybierz najpierw &apos;%1&apos; </translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1442,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>
@@ -1459,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>
@@ -1486,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>
@@ -1522,29 +1591,57 @@ 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>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Błąd podczas wyodrębniania archiwum &quot;%1&quot;: %2</translation>
</message>
<message>
- <source>Retrieving meta information from remote repository... </source>
- <translation>Pobieranie metainformacji z repozytorium zdalnego... </translation>
+ <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>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>Błąd podczas wyodrębniania archiwum &quot;%1&quot;: %2</translation>
+ <source>Metadata download canceled.</source>
+ <translation>Anulowano pobieranie metadanych.</translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Zarejestrowano nieznany wyjątek podczas wyodrębniania archiwum &quot;%1&quot;.</translation>
+ <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>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>Nie można otworzyć pliku &quot;%1&quot; do odczytu: %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>
+ <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">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>
@@ -1553,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>
@@ -1661,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>
@@ -1702,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>
@@ -1714,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>
@@ -1786,7 +1887,7 @@ Czy chcesz kontynuować?</translation>
%1</source>
<translation>Poniższe procesy powinny być zatrzymane, aby kontynuować:
-
+
%1</translation>
</message>
<message>
@@ -1795,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>
@@ -1823,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>
@@ -1831,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>
@@ -1843,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>
@@ -1870,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>
@@ -1890,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>
@@ -1951,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>
@@ -1970,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>
@@ -1983,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>
@@ -2034,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>
@@ -2053,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>
@@ -2095,14 +2227,26 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>Instalowanie</translation>
</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>
@@ -2148,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>
@@ -2160,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>
@@ -2172,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>
@@ -2202,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>
@@ -2235,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>
@@ -2270,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>
@@ -2304,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>
@@ -2353,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>
@@ -2362,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>
@@ -2408,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>
@@ -2444,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>
@@ -2484,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>
@@ -2501,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>
@@ -2629,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>
@@ -2695,28 +2886,229 @@ 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>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>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>Nie można otworzyć archiwum &quot;%1&quot; do odczytu: %2</translation>
+ </message>
+ <message>
+ <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 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>
diff --git a/src/sdk/translations/ifw_pt_BR.ts b/src/sdk/translations/ifw_pt_BR.ts
index aa60e6237..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>
@@ -300,39 +332,39 @@
</message>
<message>
<source>bytes</source>
- <translation></translation>
+ <translation>bytes</translation>
</message>
<message>
<source>KB</source>
- <translation type="unfinished"></translation>
+ <translation>KB</translation>
</message>
<message>
<source>MB</source>
- <translation type="unfinished"></translation>
+ <translation>MB</translation>
</message>
<message>
<source>GB</source>
- <translation type="unfinished"></translation>
+ <translation>GB</translation>
</message>
<message>
<source>TB</source>
- <translation type="unfinished"></translation>
+ <translation>TB</translation>
</message>
<message>
<source>PB</source>
- <translation type="unfinished"></translation>
+ <translation>PB</translation>
</message>
<message>
<source>EB</source>
- <translation type="unfinished"></translation>
+ <translation>EB</translation>
</message>
<message>
<source>ZB</source>
- <translation type="unfinished"></translation>
+ <translation>ZB</translation>
</message>
<message>
<source>YB</source>
- <translation type="unfinished"></translation>
+ <translation>YB</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -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,11 +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>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>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>
@@ -536,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>
@@ -640,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>
@@ -678,6 +718,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Não é possível remover o diretório &quot;%1&quot;: %2</translation>
</message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;: %2</source>
+ <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>
<name>QInstaller::CreateShortcutOperation</name>
@@ -742,6 +790,62 @@ Erro ao carregar %2</translation>
<source>Cannot find component for %1.</source>
<translation>Não é possível encontrar o componente para %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 de %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 baixado.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dia, </numerusform>
+ <numerusform>%n dias, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n hora, </numerusform>
+ <numerusform>%n horas, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minutos</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n segundo</numerusform>
+ <numerusform>%n segundos</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 restantes.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - tempo restante desconhecido.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <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>
<context>
<name>QInstaller::Downloader</name>
@@ -871,21 +975,6 @@ Erro ao carregar %2</translation>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <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 extracting archive &quot;%1&quot;: %2</source>
- <translation>Erro ao extrair o arquivo &quot;%1&quot;: %2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>Exceção desconhecida detectada ao extrair &quot;%1&quot;.</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -937,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>
@@ -964,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 o backup do arquivo &quot;%1&quot;: %2</translation>
+ </message>
</context>
<context>
<name>Lib7z</name>
@@ -1033,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>
@@ -1092,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>
@@ -1119,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>
@@ -1147,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>
@@ -1167,10 +1256,6 @@ Erro ao carregar %2</translation>
<translation>Erro ao extrair o arquivo &quot;%1&quot;: %2</translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>Exceção desconhecida detectada ao extrair o arquivo &quot;%1&quot;.</translation>
- </message>
- <message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>Não é possível abrir o arquivo &quot;%1&quot; para leitura: %2</translation>
</message>
@@ -1178,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>
@@ -1237,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>
@@ -1251,6 +1373,10 @@ Baixando pacotes...</translation>
<translation>Todos os downloads terminados.</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>Erro de Autenticação</translation>
</message>
@@ -1334,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>
@@ -1345,31 +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>
+ <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>
@@ -1385,6 +1503,14 @@ Você quer continuar?</translation>
<translation>Erro</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>
+ </message>
+ <message>
+ <source>Not enough disk space to store all selected components! %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>
@@ -1397,11 +1523,15 @@ Você quer continuar?</translation>
<translation>A instalação usará %1 de espaço em disco.</translation>
</message>
<message>
+ <source>Invalid</source>
+ <translation type="unfinished"></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>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -1409,33 +1539,31 @@ Você quer continuar?</translation>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Canceling the Installer</source>
+ <source>Components about to be removed:</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. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
+ <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 and the installation. %1 are available, while the minimum required is %2.</source>
+ <source>Cannot resolve components to uninstall.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Invalid</source>
+ <source>Created installer will use %1 of disk space.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -1554,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>
@@ -1574,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>
@@ -1618,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>
@@ -1654,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>
@@ -1686,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>
@@ -1718,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>
@@ -1743,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>
@@ -1775,13 +1933,13 @@ 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>
+ <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>
@@ -1814,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>
@@ -1878,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>
@@ -1960,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>
@@ -1972,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>
@@ -1984,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>
@@ -2030,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>
@@ -2042,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>
@@ -2054,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>
@@ -2112,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>
@@ -2126,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>
@@ -2182,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>
@@ -2194,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>
@@ -2374,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>
@@ -2645,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>
@@ -2677,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>
@@ -2701,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>
@@ -2709,4 +2910,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 type="unfinished">Não é possível abrir o arquivo &quot;%1&quot; para leitura: %2</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>
+ </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 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_pt_PT.ts b/src/sdk/translations/ifw_pt_PT.ts
new file mode 100644
index 000000000..3d4cf7c50
--- /dev/null
+++ b/src/sdk/translations/ifw_pt_PT.ts
@@ -0,0 +1,3118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="pt_PT" sourcelanguage="en_GB">
+<context>
+ <name>QInstaller::ProxyCredentialsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Diálogo</translation>
+ </message>
+ <message>
+ <source>The proxy %1 requires a username and password.</source>
+ <translation>A conexão &quot;proxy&quot; %1 requer um nome de utilizador e senha.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>Nome de utilizador:</translation>
+ </message>
+ <message>
+ <source>Username</source>
+ <translation>Nome de utilizador</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>Senha:</translation>
+ </message>
+ <message>
+ <source>Password</source>
+ <translation>Senha</translation>
+ </message>
+ <message>
+ <source>Proxy Credentials</source>
+ <translation>Utilizador/Senha da conexão proxy</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ServerAuthenticationDialog</name>
+ <message>
+ <source>Server Requires Authentication</source>
+ <translation>O servidor requer Autenticação</translation>
+ </message>
+ <message>
+ <source>You need to supply a username and password to access this site.</source>
+ <translation>É necessário fornecer um nome de utilizador e senha para aceder a este site.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>Nome de utilizador:</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>Senha:</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 em %2</translation>
+ </message>
+</context>
+<context>
+ <name>Dialog</name>
+ <message>
+ <source>Http authentication required</source>
+ <translation>É necessária autenticação HTTP </translation>
+ </message>
+ <message>
+ <source>You need to supply a Username and Password to access this site.</source>
+ <translation>É necessário fornecer um nome de utilizador e senha para aceder a este site.</translation>
+ </message>
+ <message>
+ <source>Username:</source>
+ <translation>Nome de utilizador:</translation>
+ </message>
+ <message>
+ <source>Password:</source>
+ <translation>Senha:</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 em %2</translation>
+ </message>
+</context>
+<context>
+ <name>SettingsDialog</name>
+ <message>
+ <source>Settings</source>
+ <translation>Configurações</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Rede</translation>
+ </message>
+ <message>
+ <source>No proxy</source>
+ <translation>Sem proxy</translation>
+ </message>
+ <message>
+ <source>System proxy settings</source>
+ <translation>Configurações de conexão proxy do sistema</translation>
+ </message>
+ <message>
+ <source>Manual proxy configuration</source>
+ <translation>Configuração manual de conexão proxy</translation>
+ </message>
+ <message>
+ <source>HTTP proxy:</source>
+ <translation>Proxy HTTP:</translation>
+ </message>
+ <message>
+ <source>Port:</source>
+ <translation>Porta:</translation>
+ </message>
+ <message>
+ <source>FTP proxy:</source>
+ <translation>Proxy FTP:</translation>
+ </message>
+ <message>
+ <source>Repositories</source>
+ <translation>Repositórios</translation>
+ </message>
+ <message>
+ <source>Add Username and Password for authentication if needed.</source>
+ <translation>Se necessário insira nome de utilizador e senha para autenticação.</translation>
+ </message>
+ <message>
+ <source>Use temporary repositories only</source>
+ <translation>Usar apenas repositórios temporários</translation>
+ </message>
+ <message>
+ <source>Add</source>
+ <translation>Adicionar</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Remover</translation>
+ </message>
+ <message>
+ <source>Test</source>
+ <translation>Testar</translation>
+ </message>
+ <message>
+ <source>Show Passwords</source>
+ <translation>Mostrar Senhas</translation>
+ </message>
+ <message>
+ <source>Check this to use repository during fetch.</source>
+ <translation>Selecione para usar o repositório durante a pesquisa.</translation>
+ </message>
+ <message>
+ <source>Add the username to authenticate on the server.</source>
+ <translation>Insira o nome de utilizador para autenticação no servidor.</translation>
+ </message>
+ <message>
+ <source>Add the password to authenticate on the server.</source>
+ <translation>Insira a senha para autenticação no servidor.</translation>
+ </message>
+ <message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>URL dos servidores que conteem um repositório válido.</translation>
+ </message>
+ <message>
+ <source>An error occurred while testing this repository.</source>
+ <translation>Ocorreu um erro durante o teste deste repositório.</translation>
+ </message>
+ <message>
+ <source>The repository was tested successfully.</source>
+ <translation>O repositório foi testado com sucesso.</translation>
+ </message>
+ <message>
+ <source>Do you want to disable the repository?</source>
+ <translation>Deseja desativar o repositório?</translation>
+ </message>
+ <message>
+ <source>Do you want to enable the repository?</source>
+ <translation>Deseja ativar o repositório?</translation>
+ </message>
+ <message>
+ <source>Hide Passwords</source>
+ <translation>Ocultar Senhas</translation>
+ </message>
+ <message>
+ <source>Use</source>
+ <translation>Usar</translation>
+ </message>
+ <message>
+ <source>Username</source>
+ <translation>Nome de utilizador</translation>
+ </message>
+ <message>
+ <source>Password</source>
+ <translation>Senha</translation>
+ </message>
+ <message>
+ <source>Repository</source>
+ <translation>Repositório</translation>
+ </message>
+ <message>
+ <source>Default repositories</source>
+ <translation>Repositórios por defeito</translation>
+ </message>
+ <message>
+ <source>Temporary repositories</source>
+ <translation>Repositórios temporários</translation>
+ </message>
+ <message>
+ <source>User defined repositories</source>
+ <translation>Repositórios definidos pelo utilizador</translation>
+ </message>
+ <message>
+ <source>Select All</source>
+ <translation>Selecionar Todos</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Error acquiring admin rights</source>
+ <translation>Ocorreu um erro ao adquirir privilégios de administrador</translation>
+ </message>
+ <message>
+ <source>Another %1 instance is already running. Wait until it finishes, close it, or restart your system.</source>
+ <translation>Existe outra instância %1 em execução. Espere até que termine ou feche-a ou reinicie o sistema.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as updater.</source>
+ <translation>Não é possível iniciar o instalador para atualizar.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as package manager.</source>
+ <translation>Não é possível iniciar o instalador como gestor de pacotes.</translation>
+ </message>
+ <message>
+ <source>Cannot start installer binary as uninstaller.</source>
+ <translation>Não é possível iniciar o instalador para desinstalar.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;addRepository&apos;.</source>
+ <translation>A lista de repositórios está vazia para a opção &apos;Adicionar Repositório&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;addTempRepository&apos;.</source>
+ <translation>A lista de repositórios está vazia para a opção &apos;Adicionar Repositório Temporário&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;setTempRepository&apos;.</source>
+ <translation>A lista de repositórios está vazia para a opção &apos;Selecionar Repositório Temporário&apos;.</translation>
+ </message>
+ <message>
+ <source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
+ <translation>A lista de repositórios está vazia para a opção &apos;Instalar Repositório Comprimido&apos;.</translation>
+ </message>
+ <message>
+ <source>The file %1 does not exist.</source>
+ <translation>O ficheiro %1 não existe.</translation>
+ </message>
+ <message>
+ <source>Arguments missing for option %1</source>
+ <translation>Faltam argumentos para a opção %1</translation>
+ </message>
+ <message>
+ <source>Invalid button value %1 </source>
+ <translation>Valor de botão %1 não é válido</translation>
+ </message>
+ <message>
+ <source>Incorrect arguments for %1</source>
+ <translation>Os argumentos para %1 estão incorretos</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 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>
+ <message>
+ <source>No marker found, stopped after %1.</source>
+ <translation>Näo foi encontrado marcador.Processo Interrompido após %1.</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 open file &quot;%1&quot; for writing: %2</source>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot; para gravação: %2</translation>
+ </message>
+ <message>
+ <source>Read failed after %1 bytes: %2</source>
+ <translation>Ocorreu um erro na leitura após %1 bytes: %2</translation>
+ </message>
+ <message>
+ <source>Copy failed: %1</source>
+ <translation>Ocorreu um erro a copiar: %1</translation>
+ </message>
+ <message>
+ <source>Write failed after %1 bytes: %2</source>
+ <translation>Ocorreu um erro a guardar após %1 bytes: %2</translation>
+ </message>
+ <message>
+ <source>bytes</source>
+ <translation>bytes</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>Não é possível remover o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o diretório &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Não é possível criar o diretório &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot copy file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível copiar o ficheiro de &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Cannot move file from &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível mover o ficheiro de &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <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 open temporary file: %1</source>
+ <translation>Não é possível abrir o ficheiro temporário: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open temporary file for template %1: %2</source>
+ <translation>Não é possível abrir o ficheiro temporário para o modelo %1: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível copiar o ficheiro de &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>Não é possível copiar ficheiro &quot;%1&quot; para &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>The specified module could not be found.</source>
+ <translation>Não é possível encontrar o módulo selecionado.</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Cannot seek to %1 to read the embedded meta data count.</source>
+ <translation>Não é possível avançar até %1 para ler o numero de metadados.</translation>
+ </message>
+ <message>
+ <source>Cannot seek to %1 to read the resource collection segment.</source>
+ <translation>Não é possível avançar até %1 para ler o segmento da coleção de recursos.</translation>
+ </message>
+ <message>
+ <source>Unexpected mismatch of meta resources. Read %1, expected: %2.</source>
+ <translation>Ocorreu uma incompatibilidade inesperada de meta recursos. Formam lidos %1, eram esperados: %2.</translation>
+ </message>
+</context>
+<context>
+ <name>BinaryContent</name>
+ <message>
+ <source>Cannot seek to %1 to read the operation data.</source>
+ <translation>Não é possível avançar até %1 para ler os dados.</translation>
+ </message>
+ <message>
+ <source>Cannot seek to %1 to read the resource collection block.</source>
+ <translation>Não é possível avançar até %1 para ler o conjunto de recursos.</translation>
+ </message>
+ <message>
+ <source>Cannot open meta resource %1.</source>
+ <translation>Não é possível abrir o meta recurso %1.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Resource</name>
+ <message>
+ <source>Cannot open resource %1 for reading.</source>
+ <translation>Não é possível abrir o recurso %1 para leitura.</translation>
+ </message>
+ <message>
+ <source>Read failed after %1 bytes: %2</source>
+ <translation>Ocorreu um erro na leitura após %1 bytes: %2</translation>
+ </message>
+ <message>
+ <source>Write failed after %1 bytes: %2</source>
+ <translation>Ocorreu um erro a guardar após %1 bytes: %2</translation>
+ </message>
+</context>
+<context>
+ <name>ResourceCollectionManager</name>
+ <message>
+ <source>Cannot open resource %1: %2</source>
+ <translation>Não é possível abrir o recurso %1: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Component</name>
+ <message>
+ <source>Components cannot have children in updater mode.</source>
+ <translation>Em modo de atualização os componentes não podem descendentes.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>Error: Operation %1 does not exist.</source>
+ <translation>Erro: A operação %1 não existe.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve isDefault in %1</source>
+ <translation>Não é possível encontrar a propriedade &quot;isDefault&quot; em %1</translation>
+ </message>
+ <message>
+ <source>Update Info: </source>
+ <translation>Informação da Atualização: </translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Component is marked for installation.</source>
+ <translation>Componente está selecionado para instalação.</translation>
+ </message>
+ <message>
+ <source>Component is marked for uninstallation.</source>
+ <translation>Componente está selecionado para desinstalação.</translation>
+ </message>
+ <message>
+ <source>Component is installed.</source>
+ <translation>Componente está instalado.</translation>
+ </message>
+ <message>
+ <source>Component is not installed.</source>
+ <translation>Componente não está instalado.</translation>
+ </message>
+ <message>
+ <source>Component Name</source>
+ <translation>Nome do Componente</translation>
+ </message>
+ <message>
+ <source>Action</source>
+ <translation>Ação</translation>
+ </message>
+ <message>
+ <source>Installed Version</source>
+ <translation>Versão Instalada</translation>
+ </message>
+ <message>
+ <source>New Version</source>
+ <translation>Nova Versão</translation>
+ </message>
+ <message>
+ <source>Release Date</source>
+ <translation>Data de Lançamento</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>Tamanho</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;a salvar propriedade do instalador&gt; &lt;executável&gt; [argumento1] [argumento2] [...]</translation>
+ </message>
+ <message>
+ <source>Needed installer object in %1 operation is empty.</source>
+ <translation>O objeto de instalação necessário na operação %1 está vazio.</translation>
+ </message>
+ <message>
+ <source>Cannot save the output of &quot;%1&quot; to an empty installer key value.</source>
+ <translation>Não é possível guardar o retorno de &quot;%1&quot; numa chave de instalação vazia.</translation>
+ </message>
+ <message>
+ <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>
+ <name>QInstaller::CopyDirectoryOperation</name>
+ <message>
+ <source>&lt;source&gt; &lt;target&gt; [&quot;forceOverwrite&quot;]</source>
+ <translation>&lt;fonte&gt; &lt;destino&gt; [&quot;forceOverwrite&quot;]</translation>
+ </message>
+ <message>
+ <source>Invalid argument in %1: Third argument needs to be forceOverwrite, if specified.</source>
+ <translation>Argumento inválido em %1: Caso seja especificado, o terceiro argumento tem de ser &quot;forceOverwrite&quot;.</translation>
+ </message>
+ <message>
+ <source>Invalid argument in %1: Directory &quot;%2&quot; is invalid.</source>
+ <translation>Argumento inválido em %1: O diretório &quot;%2&quot; não é válido.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Não é possível criar o diretório &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;.</source>
+ <translation>Falha ao guardar &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível copiar o ficheiro de &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CopyFileTask</name>
+ <message>
+ <source>Invalid task item count.</source>
+ <translation>Contagem do numero de itens da tarefa não é válida.</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 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>Writing to file &quot;%1&quot; failed: %2</source>
+ <translation>Ocorreum um erro na escrita no ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateDesktopEntryOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite file &quot;%1&quot;.</source>
+ <translation>Falha ao guardar o ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot write desktop entry to &quot;%1&quot;.</source>
+ <translation>Não é possível guardar a propriedade de área de trabalho em &quot;%1&quot;.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateLinkOperation</name>
+ <message>
+ <source>Cannot create link from &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>Não é possível criar a ligação de &quot;%1&quot; para &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove link from &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>Não é possível remover a ligação de &quot;%1&quot; para &quot;%2&quot;.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::CreateLocalRepositoryOperation</name>
+ <message>
+ <source>Cannot set permissions for file &quot;%1&quot;.</source>
+ <translation>Não é possível definir permissões para o ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível mover o ficheiro &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Installer at &quot;%1&quot; needs to be an offline one.</source>
+ <translation>O instalador em &quot;%1&quot; necessita ser offline.</translation>
+ </message>
+ <message>
+ <source>Cannot create path &quot;%1&quot;.</source>
+ <translation>Não é possível criar caminho de diretórios &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;.</source>
+ <translation>Não é possível remover diretório &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for reading.</source>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot; para leitura.</translation>
+ </message>
+ <message>
+ <source>Cannot read file &quot;%1&quot;: %2</source>
+ <translation>Não é possível ler o ficheiro &quot;%1&quot;: %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 create target directory: &quot;%1&quot;.</source>
+ <translation>Não é possível criar o diretório: &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught: %1.</source>
+ <translation>Ocorreu uma exceção desconhecida: %1.</translation>
+ </message>
+ <message>
+ <source>Removing file &quot;%1&quot;.</source>
+ <translation>A remover o ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o diretório &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <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>
+ <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;destino&gt; &lt;localização da ligação&gt; [argumentos] [&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>Não é possível criar o diretório &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;: %2</source>
+ <translation>Falha ao guardar &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create link &quot;%1&quot;: %2</source>
+ <translation>Não é possível criar a ligação &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::DownloadArchivesJob</name>
+ <message>
+ <source>Canceled</source>
+ <translation>Cancelado</translation>
+ </message>
+ <message>
+ <source>Downloading hash signature failed.</source>
+ <translation>Ocorreu um erro ao descarregar assinatura do &quot;hash&quot;.</translation>
+ </message>
+ <message>
+ <source>Download Error</source>
+ <translation>Erro a descarregar</translation>
+ </message>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.</source>
+ <translation>A verificação do &quot;hash&quot; durante o descarregamento falhou. Este é um erro temporário. Por favor, tente novamente.</translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash</source>
+ <translation>Não é possível verificar o &quot;hash&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot download archive %1: %2</source>
+ <translation>Não é possível descarregar o ficheiro %1: %2</translation>
+ </message>
+ <message>
+ <source>Cannot fetch archives: %1
+Error while loading %2</source>
+ <translation>Não é possível abrir ficheiros: %1
+Erro ao carregar %2</translation>
+ </message>
+ <message>
+ <source>Downloading archive &quot;%1&quot; for component %2.</source>
+ <translation>A descarregar ficheiro &quot;%1&quot; para o componente %2.</translation>
+ </message>
+ <message>
+ <source>Scheme %1 not supported (URL: %2).</source>
+ <translation>Sintaxe %1 não suportado (URL: %2).</translation>
+ </message>
+ <message>
+ <source>Cannot find component for %1.</source>
+ <translation>Não é possível encontrar o componente para %1.</translation>
+ </message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 de %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 descarregado.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dia, </numerusform>
+ <numerusform>%n dias, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n hora, </numerusform>
+ <numerusform>%n horas, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minutos</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n segundo</numerusform>
+ <numerusform>%n segundos</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> - o tempo restante é desconhecido.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>Ficheiro Comprimido:</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Hash verification while downloading failed. This is a temporary error, please retry.
+
+Expected: %1
+Downloaded: %2</source>
+ <translation>Falhou a verificação do código hash durante o download. Este é um erro temporário. Por favor, tente novamente.
+
+Previsto: %1
+Descarregado: %2</translation>
+ </message>
+ <message>
+ <source>Cannot verify Hash
+Expected: %1
+Downloaded: %2</source>
+ <translation>Não é possível verificar o código hash
+Previsto: %1
+Descarregado: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::Downloader</name>
+ <message>
+ <source>Target file &quot;%1&quot; already exists but is not a file.</source>
+ <translation>O caminho de destino &quot;%1&quot; já existe, mas não é um ficheiro.</translation>
+ </message>
+ <message>
+ <source>Cannot open file &quot;%1&quot; for writing: %2</source>
+ <extracomment>%2 is a sentence describing the error</extracomment>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot; para escrita: %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>O ficheiro &quot;%1&quot; não foi aberto para escrita: %2</translation>
+ </message>
+ <message>
+ <source>Writing to file &quot;%1&quot; failed: %2</source>
+ <extracomment>%2 is a sentence describing the error.</extracomment>
+ <translation>Ocorreu um erro na escrita do ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Redirect loop detected for &quot;%1&quot;.</source>
+ <translation>Ciclo de redirecionamentos detectado para &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Network error while downloading &apos;%1&apos;: %2.</source>
+ <translation>Ocorreu um erro de rede durante o descarregamento de &apos;%1&apos;: %2.</translation>
+ </message>
+ <message>
+ <source>Unknown network error while downloading &quot;%1&quot;.</source>
+ <extracomment>%1 is a sentence describing the error</extracomment>
+ <translation>Ocorreu um erro de rede desconhecido durante o descarregamento de &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Network transfers canceled.</source>
+ <translation>Transferências na rede canceladas.</translation>
+ </message>
+ <message>
+ <source>Pause and resume not supported by network transfers.</source>
+ <translation>As transferências de rede não suportam a Pausa e Retoma.</translation>
+ </message>
+ <message>
+ <source>Invalid source URL &quot;%1&quot;: %2</source>
+ <extracomment>%2 is a sentence describing the error</extracomment>
+ <translation>A URL &quot;%1&quot; não é válida: %2</translation>
+ </message>
+</context>
+<context>
+ <name>AuthenticationRequiredException</name>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 em %2</translation>
+ </message>
+ <message>
+ <source>Proxy requires authentication.</source>
+ <translation>A conexão &quot;proxy&quot; requer autenticação.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ElevatedExecuteOperation</name>
+ <message>
+ <source>Cannot start detached: &quot;%1&quot;</source>
+ <translation>Não é possível iniciar isoladamente: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Cannot start: &quot;%1&quot;: %2</source>
+ <translation>Não é possível iniciar: &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Program crashed: &quot;%1&quot;</source>
+ <translation>Programa retornou abruptamente: &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <source>Execution failed (Unexpected exit code: %1): &quot;%2&quot;</source>
+ <translation>Ocorreu um erro na execução (código de saída inesperado:%1): &quot;%2&quot;</translation>
+ </message>
+</context>
+<context>
+ <name>UpdateOperation</name>
+ <message>
+ <source>Cannot write to registry path %1.</source>
+ <translation>Não é possível guardar no caminho do registro %1.</translation>
+ </message>
+ <message>
+ <source>Registry path %1 is not writable.</source>
+ <translation>O caminho do registro %1 não é gravável.</translation>
+ </message>
+ <message>
+ <source>exactly %1</source>
+ <translation>exatamente %1</translation>
+ </message>
+ <message>
+ <source>at least %1</source>
+ <translation>pelo menos %1</translation>
+ </message>
+ <message>
+ <source>not more than %1</source>
+ <translation>não mais que %1</translation>
+ </message>
+ <message>
+ <source>%1 or %2</source>
+ <translation>%1 ou %2</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 a %2</translation>
+ </message>
+ <message numerus="yes">
+ <source>Invalid arguments in %1: %n arguments given, %2 arguments expected.</source>
+ <translation>
+ <numerusform>Argumento inválido em %1: %n argumento fornecido,%2 argumentos esperados.</numerusform>
+ <numerusform>Argumentos inválidos em %1: %n argumentos fornecidos,%2 argumentos esperados.</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>Invalid arguments in %1: %n arguments given, %2 arguments expected in the form: %3.</source>
+ <translation>
+ <numerusform>Argumento inválido em %1: %n argumento fornecido,%2 argumentos esperados no formulário %3.</numerusform>
+ <numerusform>Argumentos inválidos em %1: %n argumentos fornecidos,%2 argumentos esperados no formulário %3.</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Renaming file &quot;%1&quot; to &quot;%2&quot; failed: %3</source>
+ <translation>A renomeação do ficheiro &quot;%1&quot; para &quot;%2&quot; falhou: %3</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::FakeStopProcessForUpdateOperation</name>
+ <message>
+ <source>Cannot get package manager core.</source>
+ <translation>Não é possível obter gestor de pacotes.</translation>
+ </message>
+ <message>
+ <source>This process should be stopped before continuing: %1</source>
+ <translation>Este processo tem de ser interrompido antes de continuar: %1</translation>
+ </message>
+ <message>
+ <source>These processes should be stopped before continuing: %1</source>
+ <translation>Esses processos teem de ser interrompidos antes de continuar: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::GlobalSettingsOperation</name>
+ <message>
+ <source>Settings are not writable.</source>
+ <translation>Configurações não são graváveis.</translation>
+ </message>
+ <message>
+ <source>Failed to write settings.</source>
+ <translation>Falha ao guardar configurações.</translation>
+ </message>
+</context>
+<context>
+ <name>InstallerCalculator</name>
+ <message>
+ <source>Components added as automatic dependencies:</source>
+ <translation>Componentes adicionados como dependências automáticamente:</translation>
+ </message>
+ <message>
+ <source>Components added as dependency for &quot;%1&quot;:</source>
+ <translation>Componentes adicionados como dependência para &quot;%1&quot;:</translation>
+ </message>
+ <message>
+ <source>Components that have resolved dependencies:</source>
+ <translation>Componentes que concluiram as dependências:</translation>
+ </message>
+ <message>
+ <source>Selected components without dependencies:</source>
+ <translation>Componentes selecionados sem dependências:</translation>
+ </message>
+ <message>
+ <source>Recursion detected, component &quot;%1&quot; already added with reason: &quot;%2&quot;</source>
+ <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>
+ <message>
+ <source>&lt;source path&gt; [vendor prefix]</source>
+ <translation>&lt;caminho origem&gt; [prefixo de fornecedor]</translation>
+ </message>
+ <message>
+ <source>Invalid Argument: source directory must not be empty.</source>
+ <translation>Argumento Inválido: o diretório de origem não pode estar vazio.</translation>
+ </message>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Failed to overwrite &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro ao guardar &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Failed to copy file &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro ao copiar o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Internal code: %1</source>
+ <translation>Código interno: %1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>Não há memória suficiente</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Erro: %1</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve property %1 for item %2.</source>
+ <translation>Não é possível obter a propriedade %1 do item %2.</translation>
+ </message>
+ <message>
+ <source>Property %1 for item %2 not of type VT_FILETIME but %3.</source>
+ <translation>Propriedade %1 do item %2 não é do tipo &quot;VT_FILETIME&quot;, mas %3.</translation>
+ </message>
+ <message>
+ <source>Cannot convert UTC file time to system time.</source>
+ <translation>Não é possível converter a hora do ficheiro UTC na hora do sistema.</translation>
+ </message>
+ <message>
+ <source>Cannot load codecs.</source>
+ <translation>Não é possível carregar codecs.</translation>
+ </message>
+ <message>
+ <source>Cannot open archive &quot;%1&quot;.</source>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve number of items in archive.</source>
+ <translation>Não é possível recuperar o número de itens no ficheiro.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve path of archive item &quot;%1&quot;.</source>
+ <translation>Não é possível recuperar o caminho do ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught (%1).</source>
+ <translation>Foi detectada uma exceção desconhecida (%1).</translation>
+ </message>
+ <message>
+ <source>Cannot create temporary file: %1</source>
+ <translation>Não é possível criar ficheiro temporário: %1</translation>
+ </message>
+ <message>
+ <source>Unsupported archive type.</source>
+ <translation>Tipo de ficheiro não suportado.</translation>
+ </message>
+ <message>
+ <source>Cannot create archive &quot;%1&quot;</source>
+ <translation>Não é possível criar o ficheiro &quot;%1&quot;</translation>
+ </message>
+ <message>
+ <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>Cannot remove old archive &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro antigo &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot rename temporary archive &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível renomear o ficheiro temporário &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Unknown exception caught (%1)</source>
+ <translation>Foi detectada uma exceção desconhecida (%1)</translation>
+ </message>
+</context>
+<context>
+ <name>DirectoryGuard</name>
+ <message>
+ <source>Path &quot;%1&quot; exists but is not a directory.</source>
+ <translation>O caminho &quot;%1&quot; existe, mas não é um diretório.</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Não é possível criar o diretório &quot;%1&quot;.</translation>
+ </message>
+</context>
+<context>
+ <name>ExtractCallbackImpl</name>
+ <message>
+ <source>Cannot retrieve path of archive item %1.</source>
+ <translation>Não é possível obter o caminho do item do ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove already existing symlink %1.</source>
+ <translation>Não é possível remover a ligação simbólica já existente %1.</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 create symlink at &quot;%1&quot;. Another one is already existing.</source>
+ <translation>Não é possível criar a ligação simbólica em &quot;%1&quot;. Já existe uma ligação simbólica.</translation>
+ </message>
+ <message>
+ <source>Cannot read symlink target from file &quot;%1&quot;.</source>
+ <translation>Não é possível obter o destino da ligação simbólica do ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot create symlink at %1: %2</source>
+ <translation>Não é possível criar a ligação simbólica em %1:%2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LicenseOperation</name>
+ <message>
+ <source>No license files found to copy.</source>
+ <translation>Nenhum ficheiro de licença encontrado para copiar.</translation>
+ </message>
+ <message>
+ <source>Needed installer object in %1 operation is empty.</source>
+ <translation>O objeto de instalação necessário na operação %1 está vazio.</translation>
+ </message>
+ <message>
+ <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>
+</context>
+<context>
+ <name>QInstaller::LineReplaceOperation</name>
+ <message>
+ <source>Invalid argument in %1: Empty search argument is not supported.</source>
+ <translation>Argumento em %1 não é válido : O argumento de pesquisa vazio não é compatível.</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 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>
+</context>
+<context>
+ <name>QInstaller::MetadataJob</name>
+ <message>
+ <source>Missing package manager core engine.</source>
+ <translation>O motor principal do gestor de pacotes não está disponível.</translation>
+ </message>
+ <message>
+ <source>Unpacking compressed repositories. This may take a while...</source>
+ <translation>A descompactar repositórios. Por favor espere...</translation>
+ </message>
+ <message>
+ <source>Metadata download canceled.</source>
+ <translation>Descarregamento de metadados cancelado.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during extracting.</source>
+ <translation>Ocorreu uma exceção desconhecida durante a extração.</translation>
+ </message>
+ <message>
+ <source>Missing proxy credentials.</source>
+ <translation>Falta utilizador/senha para conexão proxy.</translation>
+ </message>
+ <message>
+ <source>Authentication failed.</source>
+ <translation>Falha na autenticação.</translation>
+ </message>
+ <message>
+ <source>Unknown exception during download.</source>
+ <translation>Ocorreu uma exceção desconhecida durante o descarregamento.</translation>
+ </message>
+ <message>
+ <source>Checksum mismatch detected for &quot;%1&quot;.</source>
+ <translation>Incompatibilidade detectada na verificação para &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Failure to fetch repositories.</source>
+ <translation>Ocorreu um erro ao obter repositórios.</translation>
+ </message>
+ <message>
+ <source>Extracting meta information...</source>
+ <translation>A extrair metadados...</translation>
+ </message>
+ <message>
+ <source>Error while extracting archive &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um erro ao extrair o ficheiro &quot;%1&quot;: %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>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>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 de %2</translation>
+ </message>
+ <message>
+ <source>%1 received.</source>
+ <translation>%1 recebido.</translation>
+ </message>
+ <message>
+ <source>(%1/sec)</source>
+ <translation>(%1/segundo)</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dia, </numerusform>
+ <numerusform>%n dias, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n hora, </numerusform>
+ <numerusform>%n horas, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minutos</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n segundo</numerusform>
+ <numerusform>%n segundos</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 restantes.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - tempo restante desconhecido.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PackageManagerCore</name>
+ <message>
+ <source>Error writing Maintenance Tool</source>
+ <translation>Erro ao guardar a Ferramenta de Manutenção</translation>
+ </message>
+ <message>
+ <source>Downloading packages...</source>
+ <translation>A descarregar pacotes...</translation>
+ </message>
+ <message>
+ <source>Installation canceled by user.</source>
+ <translation>Instalação cancelada pelo utilizador.</translation>
+ </message>
+ <message>
+ <source>All downloads finished.</source>
+ <translation>Todos os descarregamentos terminados.</translation>
+ </message>
+ <message>
+ <source>Canceling the Installer</source>
+ <translation>A cancelar o Instalador</translation>
+ </message>
+ <message>
+ <source>Authentication Error</source>
+ <translation>Erro na Autenticação</translation>
+ </message>
+ <message>
+ <source>Some components could not be removed completely because administrative rights could not be acquired: %1.</source>
+ <translation>Alguns componentes não puderam ser removidos completamente porque não foi possível obter privilégios de administrador: %1.</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Erro desconhecido.</translation>
+ </message>
+ <message>
+ <source>Some components could not be removed completely because an unknown error happened.</source>
+ <translation>Alguns componentes não puderam ser removidos completamente porque ocorreu um erro desconhecido.</translation>
+ </message>
+ <message>
+ <source>The directory you selected already exists and contains an installation. Choose a different target for installation.</source>
+ <translation>O diretório selecionado já existe e contém uma instalação. Escolha um destino diferente para instalação.</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Aviso</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>Você selecionou para instalação um diretório existente que não se encontra vazio.
+O diretório será completamente apagado na desinstalação deste aplicativo.
+Não é aconselhável instalar neste diretório uma vez que a instalação pode falhar.
+De certeza que deseja continuar?</translation>
+ </message>
+ <message>
+ <source>You have selected an existing file or symlink, please choose a different target for installation.</source>
+ <translation>Você selecionou um ficheiro ou uma ligação simbólica já existente. Por favor selecione um destino diferente para a instalação.</translation>
+ </message>
+ <message>
+ <source>The installation path cannot be empty, please specify a valid directory.</source>
+ <translation>O caminho da instalação não pode estar vazio. Por favor selecione um diretório válido.</translation>
+ </message>
+ <message>
+ <source>The installation path cannot be relative, please specify an absolute path.</source>
+ <translation>O caminho da instalação não pode ser relativo. Por favor selecione um caminho absoluto.</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>O caminho ou diretório de instalação contém caracteres não ASCII. Atualmente, isso não é suportado! Por favor, escolha um caminho ou diretório de instalação diferente.</translation>
+ </message>
+ <message>
+ <source>As the install directory is completely deleted, installing in %1 is forbidden.</source>
+ <translation>Uma vez que o diretório de instalação foi removido, não é permitido a instalação em %1.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is too long, please make sure to specify a valid path.</source>
+ <translation>O caminho selecionado é muito longo, por favor, selecione um caminho válido mais pequeno.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is not valid, please make sure to specify a valid target.</source>
+ <translation>O caminho selecionado não é válido, por favor, selecione um caminho válido.</translation>
+ </message>
+ <message>
+ <source>The path you have entered is not valid, please make sure to specify a valid drive.</source>
+ <translation>O caminho selecionado não é válido, por favor, selecione uma unidade de disco válida.</translation>
+ </message>
+ <message>
+ <source>The installation path must not end with &apos;.&apos;, please specify a valid directory.</source>
+ <translation>O caminho da instalação não pode terminar com &apos;.&apos;, por favor, selecione um diretório válido.</translation>
+ </message>
+ <message>
+ <source>The installation path must not contain &quot;%1&quot;, please specify a valid directory.</source>
+ <translation>O caminho da instalação não deve conter &quot;%1&quot;, por favor, selecione um diretório válido.</translation>
+ </message>
+ <message>
+ <source>Application not running in Package Manager mode.</source>
+ <translation>Aplicação não executada no modo Gestão de Pacotes.</translation>
+ </message>
+ <message>
+ <source>No installed packages found.</source>
+ <translation>Não foi encontrado nenhum pacote instalado.</translation>
+ </message>
+ <message>
+ <source>Application running in Uninstaller mode.</source>
+ <translation>Aplicação a ser executada no modo de desinstalar.</translation>
+ </message>
+ <message>
+ <source>There is an important update available, please run the updater first.</source>
+ <translation>Existe uma atualização importante disponível. Por favor, execute primeiro o atualizador.</translation>
+ </message>
+ <message>
+ <source>Cannot resolve all dependencies.</source>
+ <translation>Não é possível obter todas as dependências.</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>
+ </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>
+ </message>
+ <message>
+ <source>Component %1 already installed</source>
+ <translation>Componente %1 já foi instalado</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>Cannot elevate access rights while running from command line. Please restart the application as administrator.</source>
+ <translation>Não foi possível obter os direitos de acesso necessários durante a execução na linha de comandos. Por favor, reinicie a aplicação com privilégios de administrador.</translation>
+ </message>
+ <message>
+ <source>Error while elevating access rights.</source>
+ <translation>Erro ao obter os privilégios de acesso.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erro</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>Não há espaço em disco suficiente para armazenar ficheiros temporários e a instalação. Estão disponíveis %1, mas é necessário no mínimo %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>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>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>
+ <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>O volume que selecionou para instalação tem espaço suficiente para instalação, mas posteriormente terá menos de 100 MB disponíveis.</translation>
+ </message>
+ <message>
+ <source>Installation will use %1 of disk space.</source>
+ <translation>É necessário %1 de espaço em disco para a instalação.</translation>
+ </message>
+ <message>
+ <source>Invalid</source>
+ <translation>inválido</translation>
+ </message>
+ <message>
+ <source>User input is required but the output device is not associated with a terminal.</source>
+ <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 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>
+ <message>
+ <source>Unresolved dependencies</source>
+ <translation>Dependências não resolvidas</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>Access error</source>
+ <translation>Ocorreu um erro de acesso</translation>
+ </message>
+ <message>
+ <source>Format error</source>
+ <translation>Ocorreu um erro de formato</translation>
+ </message>
+ <message>
+ <source>Cannot write installer configuration to %1: %2</source>
+ <translation>Não é possível guardar a configuração do instalador em %1: %2</translation>
+ </message>
+ <message>
+ <source>Stop Processes</source>
+ <translation>Interromper processos</translation>
+ </message>
+ <message>
+ <source>These processes should be stopped to continue:
+
+%1</source>
+ <translation>Esses processos devem ser interrompidos para poder continuar:
+
+%1</translation>
+ </message>
+ <message>
+ <source>Installation canceled by user</source>
+ <translation>Instalação cancelada pelo utilizador</translation>
+ </message>
+ <message>
+ <source>Retry count exceeded</source>
+ <translation>O numero de tentativas máximo foi excedido</translation>
+ </message>
+ <message>
+ <source>Writing maintenance tool.</source>
+ <translation>A guardar ferramenta de Manutenção.</translation>
+ </message>
+ <message>
+ <source>Failed to seek in file %1: %2</source>
+ <translation>Falha ao procurar no ficheiro %1: %2</translation>
+ </message>
+ <message>
+ <source>Maintenance tool is not a bundle</source>
+ <translation>A ferramenta de Manutenção não é um pacote</translation>
+ </message>
+ <message>
+ <source>Cannot remove data file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro de dados &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool data to %1: %2</source>
+ <translation>Não é possível guardar os dados da ferramenta de Manutenção em %1: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool to &quot;%1&quot;: %2</source>
+ <translation>Não é possível gravar a ferramenta de Manutenção em &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro de dados temporário &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write maintenance tool binary data to %1: %2</source>
+ <translation>Não foi possível guardar dados da ferramenta de Manutenção em %1: %2</translation>
+ </message>
+ <message>
+ <source>Writing offline base binary.</source>
+ <translation>A escrever o ficheiro binário base offline.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot create directory &quot;%1&quot;.</source>
+ <translation>Não é possível criar o diretório &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot write offline binary to &quot;%1&quot;: %2</source>
+ <translation>Não é possível guardar o ficheiro binário offline em &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro temporário &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Variable &apos;TargetDir&apos; not set.</source>
+ <translation>Variável &apos;TargetDir&apos; não está definida.</translation>
+ </message>
+ <message>
+ <source>Preparing the installation...</source>
+ <translation>A preparar a instalação...</translation>
+ </message>
+ <message>
+ <source>It is not possible to install from network location</source>
+ <translation>Não foi possível instalar a partir do local da rede</translation>
+ </message>
+ <message>
+ <source>Creating local repository</source>
+ <translation>A criar repositório local</translation>
+ </message>
+ <message>
+ <source>Creating Maintenance Tool</source>
+ <translation>A criar Ferramenta de Manutenção</translation>
+ </message>
+ <message>
+ <source>Installation finished!</source>
+ <translation>Instalação concluída!</translation>
+ </message>
+ <message>
+ <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>
+ <translation>Não é possível iniciar a operação a partir de um local de rede</translation>
+ </message>
+ <message>
+ <source>Removing deselected components...</source>
+ <translation>A remover componentes deselecionados...</translation>
+ </message>
+ <message>
+ <source>Update finished!</source>
+ <translation>Atualização concluída!</translation>
+ </message>
+ <message>
+ <source>Update aborted!</source>
+ <translation>Atualização cancelada!</translation>
+ </message>
+ <message>
+ <source>Removal completed successfully.</source>
+ <translation>Desinstalação concluída com sucesso.</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>Desinstalação cancelada.</translation>
+ </message>
+ <message>
+ <source>Cannot create target directory for installer.</source>
+ <translation>Não é possível criar o diretório de destino para o instalador.</translation>
+ </message>
+ <message>
+ <source>Preparing offline generation...</source>
+ <translation>A preparar geração offline...</translation>
+ </message>
+ <message>
+ <source>Preparing installer configuration...</source>
+ <translation>A preparar a configuração do instalador...</translation>
+ </message>
+ <message>
+ <source>Creating the installer...</source>
+ <translation>A criar o instalador...</translation>
+ </message>
+ <message>
+ <source>Failed to create offline installer. %1</source>
+ <translation>Ocorreu um erro ao criar o instalador offline. %1</translation>
+ </message>
+ <message>
+ <source>Cannot remove temporary directory &quot;%1&quot;.</source>
+ <translation>Não é possível remover o diretório temporário &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Offline generation completed successfully.</source>
+ <translation>A geração &apos;offline&apos; foi concluída com sucesso.</translation>
+ </message>
+ <message>
+ <source>Offline generation aborted!</source>
+ <translation>A geração &apos;offline&apos; foi cancelada!</translation>
+ </message>
+ <message>
+ <source>Installing component %1</source>
+ <translation>A instalar o componente %1</translation>
+ </message>
+ <message>
+ <source>Installer Error</source>
+ <translation>Erro na Instalação</translation>
+ </message>
+ <message>
+ <source>Error during installation process (%1):
+%2</source>
+ <translation>Ocorreu um erro durante o processo de instalação (%1):
+%2</translation>
+ </message>
+ <message>
+ <source>Done</source>
+ <translation>Concluído</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>Não é possível preparar a desinstalação</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>Não é possível iniciar a desinstalação</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>Ocorreu um erro durante o processo de desinstalação:
+%1</translation>
+ </message>
+ <message>
+ <source>Unknown error</source>
+ <translation>Erro desconhecido</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve remote tree %1.</source>
+ <translation>Não é possível recuperar a árvore remota %1.</translation>
+ </message>
+ <message>
+ <source>Failure to read packages from %1.</source>
+ <translation>Falha ao ler pacotes de %1.</translation>
+ </message>
+ <message>
+ <source>Cannot retrieve meta information: %1</source>
+ <translation>Não é possível recuperar metadados: %1</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>
+ <message>
+ <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>
+ <message>
+ <source>%1 Setup</source>
+ <translation>Instalação %1</translation>
+ </message>
+ <message>
+ <source>Maintain %1</source>
+ <translation>Manutenção %1</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the installation process?</source>
+ <translation>Deseja cancelar o processo de instalação?</translation>
+ </message>
+ <message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>Deseja cancelar o processo de desinstalação?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the installer application?</source>
+ <translation>Deseja sair do instalador?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the uninstaller application?</source>
+ <translation>Deseja sair do desinstalador?</translation>
+ </message>
+ <message>
+ <source>Do you want to quit the maintenance application?</source>
+ <translation>Deseja sair do aplicativo de Manutenção?</translation>
+ </message>
+ <message>
+ <source>%1 Question</source>
+ <translation>Pergunta %1</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>Configurações</translation>
+ </message>
+ <message>
+ <source>Specify proxy settings and configure repositories for add-on components.</source>
+ <translation>Configure a conexão &quot;proxy&quot; e os repositórios para componentes complementares.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>It is not possible to install from network location.
+Please copy the installer to a local drive</source>
+ <translation>Não é possível instalar a partir de um local na rede.
+Por favor, copie o instalador para uma unidade de disco local</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::IntroductionPage</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Bem-vindo</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 Setup.</source>
+ <translation>Bem-vindo ao Assistente de Configuração %1.</translation>
+ </message>
+ <message>
+ <source>&amp;Add or remove components</source>
+ <translation>&amp;Adicionar ou remover componentes</translation>
+ </message>
+ <message>
+ <source>&amp;Update components</source>
+ <translation>At&amp;ualizar componentes</translation>
+ </message>
+ <message>
+ <source>&amp;Remove all components</source>
+ <translation>&amp;Remover todos os componentes</translation>
+ </message>
+ <message>
+ <source>Retrieving information from remote installation sources...</source>
+ <translation>A recuperar informações das fontes de instalações remotas...</translation>
+ </message>
+ <message>
+ <source>At least one valid and enabled repository required for this action to succeed.</source>
+ <translation>Para que esta ação seja bem-sucedida, é necessário pelo menos um repositório válido e ativo.</translation>
+ </message>
+ <message>
+ <source>No updates available.</source>
+ <translation>Nenhuma atualização disponível.</translation>
+ </message>
+ <message>
+ <source>&amp;Quit</source>
+ <translation>Sair</translation>
+ </message>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>Está disponível uma actualização importante. Por falor selecione primeiro &apos;%1&apos;</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::LicenseAgreementPage</name>
+ <message>
+ <source>License Agreement</source>
+ <translation>Contrato de Licença</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>Por favor, leia o seguinte contrato de licença. Para continuar com a instalação, deverá aceitar os termos e condições contidos neste contrato .</translation>
+ </message>
+ <message>
+ <source>I accept the license.</source>
+ <translation>Eu aceito a licença.</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>Por favor, leia o seguinte contrato de licença. Para continuar com a instalação, deverá aceitar os termos e condições contidos neste contrato .</translation>
+ </message>
+ <message>
+ <source>I accept the licenses.</source>
+ <translation>Eu aceito as licenças.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ComponentSelectionPage</name>
+ <message>
+ <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>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>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>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>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>
+ <message>
+ <source>Filter the enabled repository categories</source>
+ <translation>Filtrar as categorias de repositório habilitadas para seleção.</translation>
+ </message>
+ <message>
+ <source>This component will occupy approximately %1 on your hard disk drive.</source>
+ <translation>Este componente ocupará aproximadamente %1 na sua unidade de disco rígido.</translation>
+ </message>
+ <message>
+ <source>Open File</source>
+ <translation>Abrir ficheiro</translation>
+ </message>
+ <message>
+ <source>Select Components</source>
+ <translation>Selecionar Componentes</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to update.</source>
+ <translation>Por favor, selecione os componentes que você deseja atualizar.</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to install.</source>
+ <translation>Por favor, selecione os componentes que você deseja instalar.</translation>
+ </message>
+ <message>
+ <source>Please select the components you want to uninstall.</source>
+ <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.&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>
+ <message>
+ <source>Installation Folder</source>
+ <translation>Pasta de Instalação</translation>
+ </message>
+ <message>
+ <source>Please specify the directory where %1 will be installed.</source>
+ <translation>Por favor selecione o diretório onde %1 será instalado.</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>P&amp;rocurar...</translation>
+ </message>
+ <message>
+ <source>Browse file system to choose the installation directory.</source>
+ <translation>Selecione o diretório de instalação.</translation>
+ </message>
+ <message>
+ <source>Select Installation Folder</source>
+ <translation>Selecione a Pasta de Instalação</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::StartMenuDirectoryPage</name>
+ <message>
+ <source>Start Menu shortcuts</source>
+ <translation>Atalhos do Menu Iniciar</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>Selecione, no Menu Iniciar, o local onde criar os atalhos do programa. Também é possível inserir um nome para criar um novo diretório.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ReadyForInstallationPage</name>
+ <message>
+ <source>U&amp;ninstall</source>
+ <translation>Desi&amp;nstalar</translation>
+ </message>
+ <message>
+ <source>Ready to Uninstall</source>
+ <translation>Pronto para Desinstalar</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>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>
+ <source>U&amp;pdate</source>
+ <translation>A&amp;tualizar</translation>
+ </message>
+ <message>
+ <source>Ready to Update Packages</source>
+ <translation>Pronto para Atualizar Pacotes</translation>
+ </message>
+ <message>
+ <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>
+ <source>&amp;Install</source>
+ <translation>&amp;Instalar</translation>
+ </message>
+ <message>
+ <source>Ready to Install</source>
+ <translation>Pronto para Instalar</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>U&amp;ninstall</source>
+ <translation>Desi&amp;nstalar</translation>
+ </message>
+ <message>
+ <source>Uninstalling %1</source>
+ <translation>A desinstalar %1</translation>
+ </message>
+ <message>
+ <source>&amp;Update</source>
+ <translation>At&amp;ualizar</translation>
+ </message>
+ <message>
+ <source>Updating components of %1</source>
+ <translation>A atualizar componentes de %1</translation>
+ </message>
+ <message>
+ <source>&amp;Install</source>
+ <translation>&amp;Instalar</translation>
+ </message>
+ <message>
+ <source>Installing %1</source>
+ <translation>A instalar %1</translation>
+ </message>
+ <message>
+ <source>Installing</source>
+ <translation>A instalar</translation>
+ </message>
+ <message>
+ <source>Updating</source>
+ <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>Finished the %1 Setup</source>
+ <translation>A concluir o Assistente %1</translation>
+ </message>
+ <message>
+ <source>Finished</source>
+ <translation>Concluído</translation>
+ </message>
+ <message>
+ <source>Click %1 to exit the %2 Setup.</source>
+ <translation>Clique em %1 para fechar o Assistente %2.</translation>
+ </message>
+ <message>
+ <source>Restart</source>
+ <translation>Reiniciar</translation>
+ </message>
+ <message>
+ <source>Run %1 now.</source>
+ <translation>Executar %1 agora.</translation>
+ </message>
+ <message>
+ <source>The %1 Setup failed.</source>
+ <translation>Ocorreu um erro no assistente %1.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RestartPage</name>
+ <message>
+ <source>Finished the %1 Setup</source>
+ <translation>A concluir o Assistente de Configuração %1</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::PerformInstallationForm</name>
+ <message>
+ <source>&amp;Show Details</source>
+ <translation>Mostrar &amp;Detalhes</translation>
+ </message>
+ <message>
+ <source>&amp;Hide Details</source>
+ <translation>&amp;Esconder Detalhes</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::RegisterFileTypeOperation</name>
+ <message>
+ <source>Registering file types is only supported on Windows.</source>
+ <translation>A alteração da aplicação predefinida só é suportado no sistema Windows.</translation>
+ </message>
+ <message>
+ <source>Register File Type: Invalid arguments</source>
+ <translation>Argumentos inválidos ao alterar aplicação predefinida!</translation>
+ </message>
+</context>
+<context>
+ <name>RemoteClient</name>
+ <message>
+ <source>Cannot get authorization.</source>
+ <translation>Não é possível autorizar.</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>Não é possível continuar a instalação. A instalação não foi autorizada.
+ Cancele a instalação ou use a solução de recurso executando
+
+%1
+
+com um utilizador com os privilégios necessários. Em seguida, carregue em OK.</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>Não é possível continuar a instalação. A instalação não foi autorizada.
+
+Por favor, inicie o programa de instalação como um utilizador com os privilégios necessários.
+Em alternativa, pode aceitar a alteração de permissões de acesso caso seja solicitado.</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>Não foi possível ler todos os dados após o executar o comando: %1. Bytes esperados: %2, Bytes recebidos: %3. Erro: %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>Não é suportado utilizar o argumento de pesquisa &quot;%1&quot; com um argumento de pesquisa vazio.</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>Não é suportado utilizar o argumento &quot;%1&quot; com os argumentos &quot;%2&quot;. Use string ou regex.</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 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>
+</context>
+<context>
+ <name>QInstaller::ScriptEngine</name>
+ <message>
+ <source>Cannot open script file at %1: %2</source>
+ <translation>Não é possível abrir o ficheiro de &quot;script&quot; em %1: %2</translation>
+ </message>
+ <message>
+ <source>Exception while loading the component script &quot;%1&quot;: %2</source>
+ <translation>Ocorreu um exceção ao carregar o &quot;script&quot; do componente &quot;%1&quot; %2</translation>
+ </message>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Ocorreu um erro desconhecido.</translation>
+ </message>
+ <message>
+ <source>on line number: </source>
+ <translation>na linha número: </translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::SelfRestartOperation</name>
+ <message>
+ <source>Installer object needed in operation %1 is empty.</source>
+ <translation>O objeto de instalação necessário na operação %1 está vazio.</translation>
+ </message>
+ <message>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>O Reinício Automático só é válido no modo &quot;updater&quot; ou &quot;packagemanager&quot;.</translation>
+ </message>
+ <message>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>Existe argumentos inválidos na operação de Reinício Automático</translation>
+ </message>
+</context>
+<context>
+ <name>Settings</name>
+ <message>
+ <source>Cannot open settings file %1 for reading: %2</source>
+ <translation>Não é possível abrir o ficheiro de configurações %1 para leitura: %2</translation>
+ </message>
+ <message>
+ <source>Categories</source>
+ <translation>Categorias</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>O(s) Argumento(s) &quot;%1&quot; estão em falta. A executar %2 com os seguintes argumentos &quot;%3&quot;.</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>Não é suportado executar &amp;quot;%1&amp;quot; com os argumentos &amp;quot;%2&amp;quot;. Por favor, utilize &quot;set&quot;, &quot;remove&quot;, &quot;add_array_value&quot; ou &quot;remove_array_value&quot;.</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>Os argumentos: origem &quot;%1&quot; e destino &quot;%2&quot; teem de estar preenchidos.</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>Não é possível mover o ficheiro de &quot;%1&quot; para &quot;%2&quot; porque o caminho de destino já existe e não é removível.</translation>
+ </message>
+ <message>
+ <source>Cannot move file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível mover o ficheiro &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Moving file &quot;%1&quot; to &quot;%2&quot;.</source>
+ <translation>a mover o ficheiro &quot;%1&quot; para &quot;%2&quot;.</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::TestRepository</name>
+ <message>
+ <source>Missing package manager core engine.</source>
+ <translation>O motor principal do gestor de pacotes não está disponível.</translation>
+ </message>
+ <message>
+ <source>Empty repository URL.</source>
+ <translation>O URL do repositório está vazio.</translation>
+ </message>
+ <message>
+ <source>Download canceled.</source>
+ <translation>O descarregamento foi cancelado.</translation>
+ </message>
+ <message>
+ <source>Timeout while testing repository &quot;%1&quot;.</source>
+ <translation>Foi atingido o limite de tempo durante o teste do repositório &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot parse Updates.xml: %1</source>
+ <translation>Não é possível analisar o ficheiro Updates.xml: %1</translation>
+ </message>
+ <message>
+ <source>Cannot open Updates.xml for reading: %1</source>
+ <translation>Não é possível abrir o ficheiro Updates.xml para leitura: %1</translation>
+ </message>
+ <message>
+ <source>Authentication failed.</source>
+ <translation>Falha na autenticação.</translation>
+ </message>
+ <message>
+ <source>Unknown error while testing repository &quot;%1&quot;.</source>
+ <translation>Ocorreu um erro desconhecido ao testar o repositório &quot;%1&quot;.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::FileDownloader</name>
+ <message>
+ <source>Download finished.</source>
+ <translation>Descarregamento concluído.</translation>
+ </message>
+ <message>
+ <source>Cryptographic hashes do not match.</source>
+ <translation>Não coincidem os hashes criptográficos.</translation>
+ </message>
+ <message>
+ <source>Download canceled.</source>
+ <translation>Descarregamento cancelado.</translation>
+ </message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 de %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 descarregado.</translation>
+ </message>
+ <message>
+ <source>(%1/sec)</source>
+ <translation>(%1/segundo)</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n dia, </numerusform>
+ <numerusform>%n dias, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n hora, </numerusform>
+ <numerusform>%n horas, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minutos</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n segundo</numerusform>
+ <numerusform>%n segundos</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - %1%2%3%4 restantes.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - tempo restante desconhecido.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::LocalFileDownloader</name>
+ <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 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>Writing to file &quot;%1&quot; failed: %2</source>
+ <translation>Ocorreu uma erro a escrever no ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::ResourceFileDownloader</name>
+ <message>
+ <source>Cannot read resource file &quot;%1&quot;: %2</source>
+ <translation>Não é possível ler o ficheiro de recursos &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::HttpDownloader</name>
+ <message>
+ <source>Cannot download %1. Writing to file &quot;%2&quot; failed: %3</source>
+ <translation>Não é possível fazer o descarregamento de %1. A escrita no ficheiro &quot;%2&quot; falhou: %3</translation>
+ </message>
+ <message>
+ <source>Cannot download %1. Cannot create file &quot;%2&quot;: %3</source>
+ <translation>Não é possível fazer o descarregamento de %1. Não é possível criar o ficheiro &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>%1 at %2</source>
+ <translation>%1 em %2</translation>
+ </message>
+ <message>
+ <source>Authentication request canceled.</source>
+ <translation>Pedido de autenticação cancelado.</translation>
+ </message>
+ <message>
+ <source>Secure Connection Failed</source>
+ <translation>Ocorreu um erro na Conexão Segura</translation>
+ </message>
+ <message>
+ <source>There was an error during connection to: %1.</source>
+ <translation>Ocorreu um erro durante a conexão com: %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>Poderá haver um problema na configuração do servidor ou ser um ataque &quot;man-in-the-middle&quot;, ou seja, alguém a atribuir-se a identidade do servidor.</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>Se você se conectou a este servidor com sucesso no passado ou confia nele, o erro pode ser temporário. Tente novamente mais tarde.</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>Canceled</source>
+ <translation>Cancelado</translation>
+ </message>
+</context>
+<context>
+ <name>LocalPackageHub</name>
+ <message>
+ <source>%1 contains invalid content: %2</source>
+ <translation>%1 contém conteúdo inválido: %2</translation>
+ </message>
+ <message>
+ <source>The file %1 does not exist.</source>
+ <translation>O ficheiro %1 não existe.</translation>
+ </message>
+ <message>
+ <source>Cannot open %1.</source>
+ <translation>Não é possível abrir %1.</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 &apos;Packages&apos;.</source>
+ <translation>Não é esperado este elemento raiz %1. Deveria ser &apos;Packages&apos;.</translation>
+ </message>
+</context>
+<context>
+ <name>LockFile</name>
+ <message>
+ <source>Cannot create lock file &quot;%1&quot;: %2</source>
+ <translation>Não é possível criar o ficheiro &quot;lock&quot; &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot write PID to lock file &quot;%1&quot;: %2</source>
+ <translation>Não é possível gravar o PID no ficheiro &quot;lock&quot; &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot obtain the lock for file &quot;%1&quot;: %2</source>
+ <translation>Não é possível obter o &quot;lock&quot; para o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot release the lock for file &quot;%1&quot;: %2</source>
+ <translation>Não é possível libertar o &quot;lock&quot; para o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::Task</name>
+ <message>
+ <source>%1 started</source>
+ <translation>%1 foi iniciado</translation>
+ </message>
+ <message>
+ <source>%1 cannot be stopped</source>
+ <translation>%1 não pode ser interrompido</translation>
+ </message>
+ <message>
+ <source>Cannot stop task %1</source>
+ <translation>Não é possível parar a tarefa %1</translation>
+ </message>
+ <message>
+ <source>%1 cannot be paused</source>
+ <translation>Não é possivel pausar %1</translation>
+ </message>
+ <message>
+ <source>Cannot pause task %1</source>
+ <translation>Não é possível pausar a tarefa %1</translation>
+ </message>
+ <message>
+ <source>Cannot resume task %1</source>
+ <translation>Não é possível retomar a tarefa %1</translation>
+ </message>
+ <message>
+ <source>%1 done</source>
+ <translation>%1 foi concluído</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::UpdateFinder</name>
+ <message>
+ <source>Cannot access the package information of this application.</source>
+ <translation>Não é possível aceder às informações do pacote nesta aplicação.</translation>
+ </message>
+ <message>
+ <source>No package sources set for this application.</source>
+ <translation>Não foi definida nenhuma fonte para pacotes nesta aplicação.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n update(s) found.</source>
+ <translation>
+ <numerusform>%n atualização encontrada.</numerusform>
+ <numerusform>%n atualizações encontradas.</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Downloading Updates.xml from update sources.</source>
+ <translation>A descarregar o ficheiro Updates.xml para a atualização repositórios.</translation>
+ </message>
+ <message>
+ <source>Cannot download package source %1 from &quot;%2&quot;.</source>
+ <translation>Não é possível descarregar a fonte do pacote %1 de &quot;%2&quot;.</translation>
+ </message>
+ <message>
+ <source>Updates.xml file(s) downloaded from update sources.</source>
+ <translation>Os ficheiros Updates.xml foram descarregados das fontes para atualização.</translation>
+ </message>
+ <message>
+ <source>Computing applicable updates.</source>
+ <translation>A calcular possiveis atualizações.</translation>
+ </message>
+ <message>
+ <source>Application updates computed.</source>
+ <translation>Possiveis atualizações calculadas.</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::CopyOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;.</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot copy a non-existent file: %1</source>
+ <translation>Não é possível copiar um ficheiro inexistente: %1</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível copiar o ficheiro de &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Cannot delete file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file into &quot;%1&quot;: %2</source>
+ <translation>Não é possível recuperar a cópia de segurança em &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::MoveOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;.</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
+ <translation>Não é possível copiar o ficheiro de &quot;%1&quot; para &quot;%2&quot;: %3</translation>
+ </message>
+ <message>
+ <source>Cannot remove file &quot;%1&quot;.</source>
+ <translation>Não é possível remover o ficheiro &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Não é possível recuperar a cópia de segurança para &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::DeleteOperation</name>
+ <message>
+ <source>Cannot create backup of file &quot;%1&quot;: %2</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Não é possível recuperar a cópia de segurança para &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::MkdirOperation</name>
+ <message>
+ <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>Unknown error.</source>
+ <translation>Erro desconhecido.</translation>
+ </message>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o diretório &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::RmdirOperation</name>
+ <message>
+ <source>Cannot remove directory &quot;%1&quot;: %2</source>
+ <translation>Não é possível remover o diretório &quot;%1&quot;: %2</translation>
+ </message>
+ <message>
+ <source>The directory does not exist.</source>
+ <translation>O diretório não existe.</translation>
+ </message>
+ <message>
+ <source>Cannot recreate directory &quot;%1&quot;: %2</source>
+ <translation>Não é possível voltar a criar o diretório &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::AppendFileOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;: %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 gravação: %2</translation>
+ </message>
+ <message>
+ <source>Cannot find backup file for &quot;%1&quot;.</source>
+ <translation>Não é possível encontrar a cópia de segurança para &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;.</source>
+ <translation>Não é possível recuperar a cópia de segurança para &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Não é possível recuperar a cópia de segurança para &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::PrependFileOperation</name>
+ <message>
+ <source>Cannot backup file &quot;%1&quot;: %2</source>
+ <translation>Não é possível fazer a cópia de segurança do ficheiro &quot;%1&quot;: %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 open file &quot;%1&quot; for writing: %2</source>
+ <translation>Não é possível abrir o ficheiro &quot;%1&quot; para gravação: %2</translation>
+ </message>
+ <message>
+ <source>Cannot find backup file for &quot;%1&quot;.</source>
+ <translation>Não é possível encontrar a cópia de segurança para &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;.</source>
+ <translation>Não é possível recuperar a cópia de segurança para &quot;%1&quot;.</translation>
+ </message>
+ <message>
+ <source>Cannot restore backup file for &quot;%1&quot;: %2</source>
+ <translation>Não é possível recuperar a cópia de segurança para &quot;%1&quot;: %2</translation>
+ </message>
+</context>
+<context>
+ <name>KDUpdater::UpdatesInfoData</name>
+ <message>
+ <source>Updates.xml contains invalid content: %1</source>
+ <translation>O ficheiro Updates.xml contém conteúdo que não é válido: %1</translation>
+ </message>
+ <message>
+ <source>Cannot read &quot;%1&quot;</source>
+ <translation>Não é possível ler &quot;%1&quot;</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>
+ <message>
+ <source>ApplicationName element is missing.</source>
+ <translation>Falta o elemento &quot;ApplicationName&quot;.</translation>
+ </message>
+ <message>
+ <source>ApplicationVersion element is missing.</source>
+ <translation>Falta o elemento &quot;ApplicationVersion&quot;.</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without Name</source>
+ <translation>Falta a propriedade &quot;Name&quot; ao elemento &quot;PackageUpdate&quot;</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without Version</source>
+ <translation>Falta a propriedade &quot;Version&quot; ao elemento &quot;PackageUpdate&quot;</translation>
+ </message>
+ <message>
+ <source>PackageUpdate element without ReleaseDate</source>
+ <translation>Falta a propriedade &quot;ReleaseDate&quot; ao elemento &quot;PackageUpdate&quot;</translation>
+ </message>
+</context>
+<context>
+ <name>InstallerBase</name>
+ <message>
+ <source>Unable to start installer</source>
+ <translation>Não foi possível iniciar instalador</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ComponentSelectionPagePrivate</name>
+ <message>
+ <source>Filter</source>
+ <translation>Filtro</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informação</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation</name>
+ <message>
+ <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>
+ <message>
+ <source>User input is required but the output device is not associated with a terminal.</source>
+ <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>
+</context>
+<context>
+ <name>QInstaller::ExtractArchiveOperation::Worker</name>
+ <message>
+ <source>Could not create handler object for archive &quot;%1&quot;: &quot;%2&quot;.</source>
+ <translation>Não foi possível criar um &quot;handler&quot; para o ficheiro comprido &quot;%1&quot;: &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 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 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>
+</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_ru.ts b/src/sdk/translations/ifw_ru.ts
index 72c6d7e0b..830c2bc82 100644
--- a/src/sdk/translations/ifw_ru.ts
+++ b/src/sdk/translations/ifw_ru.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="ru_RU">
+<TS version="2.1" language="ru_RU" sourcelanguage="en_GB">
<context>
<name>AuthenticationRequiredException</name>
<message>
@@ -92,7 +92,7 @@
</message>
<message>
<source>Cannot create symlink at &quot;%1&quot;. Another one is already existing.</source>
- <translation>Не удалось создать символьную ссылку «%1», потому что ссылка уже существует.</translation>
+ <translation>Не удалось создать символьную ссылку «%1». Ссылка уже существует.</translation>
</message>
<message>
<source>Cannot read symlink target from file &quot;%1&quot;.</source>
@@ -107,7 +107,7 @@
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>Не удается запустить установщик</translation>
</message>
</context>
<context>
@@ -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>
@@ -590,11 +602,11 @@
</message>
<message>
<source>Internal code: %1</source>
- <translation type="unfinished"></translation>
+ <translation>внутренний код ошибки: %1</translation>
</message>
<message>
<source>Not enough memory</source>
- <translation type="unfinished"></translation>
+ <translation>недостаточно памяти</translation>
</message>
</context>
<context>
@@ -687,11 +699,11 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;: %3</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось скопировать файл «%1» в «%2»: %3</translation>
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось скопировать файл «%1» в «%2».</translation>
</message>
<message>
<source>No marker found, stopped after %1.</source>
@@ -747,7 +759,11 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -769,28 +785,36 @@
<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>
+ <source>Error: Operation %1 does not exist.</source>
+ <translation>Ошибка: операция %1 не существует.</translation>
</message>
<message>
- <source>Cannot open the requested license file &quot;%1&quot;: %2</source>
- <translation>Не удалось открыть запрошенный файл лицензии «%1»: %2</translation>
+ <source>There was an error loading the selected component. This component cannot be installed.</source>
+ <translation>Возникла ошибка при загрузке выбранного компонента. Установить его не получится.</translation>
</message>
<message>
- <source>Error: Operation %1 does not exist.</source>
- <translation>Ошибка: операция %1 не существует.</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>There was an error loading the selected component. This component cannot be installed.</source>
- <translation type="unfinished"></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 updated.</source>
- <translation type="unfinished"></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>
@@ -839,44 +863,40 @@
<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 type="unfinished"></translation>
+ <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 type="unfinished"></translation>
+ <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 type="unfinished"></translation>
+ <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 type="unfinished"></translation>
- </message>
- <message>
- <source>&amp;Browse QBSP files</source>
- <translation>&amp;Обзор файлов QBSP</translation>
+ <translation>Отмените выбор всех компонентов в древовидном представлении.</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>Выберите файл инструментальных средств для разработки Qt Board Support Package, чтобы установить дополнительное содержимое, которое недоступно непосредственно из сетевых хранилищ.</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -899,40 +919,44 @@
<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>
- <translation type="unfinished"></translation>
+ <translation>Прежде чем можно будет выбрать другие компоненты для обновления, сначала необходимо обновить обязательные компоненты.</translation>
</message>
<message>
<source>Open File</source>
<translation>Открытие файла</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>Отфильтруйте категории включенного хранилища по выбору.</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Search</source>
+ <translation>Поиск</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>Посмотреть &amp;QBSP файлы</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Select</source>
+ <translation>Выбрать</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation type="unfinished"></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>
@@ -946,8 +970,8 @@
<translation>Ошибка</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>Информация</translation>
</message>
</context>
<context>
@@ -965,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>
@@ -1073,11 +1093,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось создать путь «%1».</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось удалить каталог «%1».</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1107,6 +1127,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>Не удалось удалить каталог «%1»: %2</translation>
</message>
+ <message>
+ <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>
@@ -1142,14 +1170,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 fetch archives: %1
Error while loading %2</source>
<translation>Невозможно получить архивы :%1
@@ -1171,6 +1191,84 @@ Error while loading %2</source>
<source>Cannot find component for %1.</source>
<translation>Не удалось найти компонент для %1.</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1 из %2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>загружено %1.</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n день, </numerusform>
+ <numerusform>%n дня, </numerusform>
+ <numerusform>%n дней, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n час, </numerusform>
+ <numerusform>%n часа, </numerusform>
+ <numerusform>%n часов, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n минута</numerusform>
+ <numerusform>%n минуты</numerusform>
+ <numerusform>%n минут</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n секунда</numerusform>
+ <numerusform>%n секунды</numerusform>
+ <numerusform>%n секунд</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - осталось %1%2%3%4.</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - время окончания загрузки неизвестно.</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>Архив: </translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <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>
<name>QInstaller::Downloader</name>
@@ -1245,20 +1343,21 @@ Error while loading %2</source>
<source>Extracting &quot;%1&quot;</source>
<translation>Извлечение «%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>Неподдерживаемый архив &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 extracting archive &quot;%1&quot;: %2</source>
- <translation>Ошибка извлечения из архива «%1»: %2</translation>
+ <source>Error while reading contents of archive &quot;%1&quot;: %2</source>
+ <translation>Ошибка при чтении содержимого архива &quot;%1&quot;: %2</translation>
</message>
<message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>В процессе извлечения «%1» возникло неизвестное исключение.</translation>
+ <source>Removing files extracted from &quot;%1&quot;</source>
+ <translation>Удаление файлов, извлеченных из &quot;%1&quot;</translation>
</message>
</context>
<context>
@@ -1334,12 +1433,12 @@ 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>
<source>Finished</source>
- <translation type="unfinished"></translation>
+ <translation>Завершено</translation>
</message>
<message>
<source>Restart</source>
@@ -1350,11 +1449,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>
@@ -1395,15 +1494,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>
@@ -1431,13 +1534,13 @@ 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>
+ <message>
+ <source>There is an important update available. Please select &apos;%1&apos; first</source>
+ <translation>Доступно важное обновление. Пожалуйста, сперва выберите &apos;%1&apos;</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1459,12 +1562,12 @@ Error while loading %2</source>
</message>
<message>
<source>I accept the licenses.</source>
- <translation>Я согласен(а) с лицензией.</translation>
+ <translation>Я согласен(а) с лиценией.</translation>
</message>
<message>
<source>Alt+A</source>
<comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
+ <translation>Alt+A</translation>
</message>
</context>
<context>
@@ -1478,10 +1581,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>
@@ -1490,7 +1589,7 @@ Error while loading %2</source>
<name>QInstaller::LineReplaceOperation</name>
<message>
<source>Invalid argument in %1: Empty search argument is not supported.</source>
- <translation type="unfinished"></translation>
+ <translation>Недопустимый параметр в %1: Пустой параметр поиска не поддерживается.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1508,10 +1607,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>
@@ -1532,14 +1627,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>
@@ -1556,16 +1643,52 @@ Error while loading %2</source>
<translation>Ошибка извлечения из архива «%1»: %2</translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>В процессе извлечения из архива «%1» возникло неизвестное исключение.</translation>
- </message>
- <message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
<translation>Не удалось открыть файл «%1» на чтение: %2</translation>
</message>
<message>
<source>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1575,10 +1698,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>
@@ -1663,32 +1784,24 @@ 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 type="unfinished"></translation>
- </message>
- <message>
- <source>Component %1 already installed
-</source>
- <translation type="unfinished"></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 type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>Компонент %1 уже установлен</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>Не удалось установить %1. Компонент является виртуальным.</translation>
</message>
<message>
- <source>Running processes found.</source>
- <translation type="unfinished"></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>
- <translation type="unfinished"></translation>
+ <translation>Невозможно повысить уровень прав доступа при запуске из командной строки. Перезапустите приложение от имени администратора.</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1700,11 +1813,11 @@ Do you want to continue?</source>
</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>Том, который выбран для установки, по всей видимости имеет достаточно для этого места, но в результате на нем останется менее 1% свободного пространства.</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>Том, который выбран для установки, по всей видимости имеет достаточно для этого места, но в результате на нем останется менее 100 МБ свободного пространства.</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
@@ -1731,50 +1844,64 @@ Do you want to continue?</source>
<translation>Не удалось разрешить все зависимости.</translation>
</message>
<message>
- <source>Components about to be removed.</source>
- <translation>Удаляемые компоненты.</translation>
+ <source>User input is required but the output device is not associated with a terminal.</source>
+ <translation>Требуется ввод данных пользователем, но устройство вывода не связано с терминалом.</translation>
</message>
<message>
- <source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <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>
+ <translation>Не удалось установить компонент %1. Компонент не является проверяемым, и это означает, что необходимо выбрать один из подкомпонентов.</translation>
+ </message>
+ <message>
+ <source>Cannot install %1. Component is a descendant of a virtual component %2.</source>
+ <translation>Не удалось установить %1. Компонент является производным от виртуального компонента %2.</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
+ <source>Not enough disk space to store temporary files and the installation. %1 are available, while the minimum required is %2.</source>
+ <translation>&gt;Недостаточно места на диске для временных файлов и файлов установки. Доступно %1, а требуется минимум %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>Недостаточно места на диске для сохранения всех выбранных компонентов. Доступно %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>
+ <translation>Приблизительный размер установочника %1 превысит поддерживаемый предел размера исполняемого файла %2. Возможно, приложение не сможет быть запущено. </translation>
</message>
<message>
- <source>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <source>Invalid</source>
+ <translation>недопустимая версия</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>Components about to be removed:</source>
+ <translation>Компонент практически удален:</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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 and the installation. %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>Невозможно определить компоненты для удаления.</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>
+ <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>Invalid</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1828,16 +1955,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>
@@ -1848,16 +1971,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>
@@ -1865,7 +1984,7 @@ Update aborted!</source>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>Превышено число повторных попыток</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
@@ -1885,7 +2004,7 @@ Update aborted!</source>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось удалить временный файл данных «%1»: %2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1893,7 +2012,7 @@ Update aborted!</source>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>Запись двоичных данных автономного экземпляра.</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1901,15 +2020,15 @@ Update aborted!</source>
</message>
<message>
<source>Cannot create directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось создать каталог «%1».</translation>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось записать двоичные данные автономного экземпляра в «%1»: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось удалить временный файл «%1»: %2</translation>
</message>
<message>
<source>Creating Maintenance Tool</source>
@@ -1917,41 +2036,39 @@ Update aborted!</source>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось создать целевой каталог для установщика.</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>Подготовка к созданию автономного экземпляра...</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>Подготовка конфигурации установщика...</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>Создание установщика...</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось создать автономный установщик. %1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удалось удалить временный каталог «%1».</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>Создание автономного экземпляра успешно завершено.</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1975,10 +2092,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>
@@ -2004,24 +2117,69 @@ Installing component %1</source>
</message>
<message>
<source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>Удаление успешно завершено.</translation>
</message>
<message>
<source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <translation>Удаление прервано.</translation>
</message>
<message>
<source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <translation>Невозможно подготовиться к удалению</translation>
</message>
<message>
<source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <translation>Невозможно начать удаление</translation>
</message>
<message>
<source>Error during removal process:
%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2051,12 +2209,12 @@ Installing component %1</source>
<translation>Выйти из приложения обслуживания?</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 type="unfinished"></translation>
+ <translation>Укажите параметры прокси-сервера и настройте хранилища для подключаемых компонентов.</translation>
</message>
<message>
<source>Error</source>
@@ -2074,7 +2232,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>Отменить установку?</translation>
</message>
</context>
<context>
@@ -2116,22 +2274,34 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>Установка</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>Обновление</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
<message>
<source>Dialog</source>
- <translation></translation>
+ <translation>Диалоговое окно</translation>
</message>
<message>
<source>The proxy %1 requires a username and password.</source>
@@ -2169,7 +2339,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>
@@ -2181,7 +2351,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>
@@ -2193,12 +2363,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2223,11 +2405,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>Текущий параметр поиска, вызывающий «%1» с пустым параметром поиска, не поддерживается.</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>Текущий параметр режима, вызывающий «%1» с параметрами «%2», не поддерживается. Используйте строку или регулярное выражение.</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2256,7 +2438,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>
@@ -2291,7 +2473,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>Автоматическая перезагрузка: подходит только для программы обновления или для режима менеджера пакетов.</translation>
</message>
</context>
<context>
@@ -2325,7 +2507,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>Текущий способ вызова «%1» с аргументами «%2» не поддерживается. Используйте set, remove, add_array_value или remove_array_value.</translation>
</message>
</context>
<context>
@@ -2370,7 +2552,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>Просмотрите файловую систему, чтобы выбрать каталог для установки.</translation>
</message>
<message>
<source>Select Installation Folder</source>
@@ -2383,7 +2565,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>
@@ -2433,31 +2615,31 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удается запустить двоичный файл установщика как программу обновления.</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удается запустить двоичный файл установщика как менеджер пакетов.</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>Не удается запустить двоичный файл установщика как программу удаления.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Пустой список хранилищ для опции &apos;addRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Пустой список хранилищ для опции &apos;addTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Пустой список хранилищ для опции &apos;setTempRepository&apos;.</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>Пустой список хранилищ для опции &apos;installCompressedRepository&apos;.</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2465,19 +2647,27 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>Отсутствуют параметры для опции %1</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>Недопустимое значение кнопки %1 </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>Неправильные параметры для %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 type="unfinished"></translation>
+ <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>
@@ -2505,7 +2695,10 @@ as a user with the appropriate rights and then clicking OK.</source>
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>Не удалось пройти авторизацию, которая необходима для продолжения установки.
+
+Запустите программу от пользователя с подходящими правами.
+Или разрешите повышение прав, когда об этом будет попрошено.</translation>
</message>
</context>
<context>
@@ -2522,8 +2715,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>
@@ -2658,7 +2851,31 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></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>
@@ -2716,7 +2933,192 @@ or accept the elevation of access rights if being asked.</source>
<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>Требуется ввод данных пользователем, но устройство вывода не связано с терминалом.</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>Не удалось создать объект обработчика для архива &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 extracting archive &quot;%1&quot;: %2</source>
+ <translation>Ошибка извлечения из архива «%1»: %2</translation>
+ </message>
+</context>
+<context>
+ <name>QInstaller::ExtractWorker</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>
+</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 93b23a1b8..7246914a1 100644
--- a/src/sdk/translations/ifw_zh_CN.ts
+++ b/src/sdk/translations/ifw_zh_CN.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="zh_CN">
+<TS version="2.1" language="zh_CN" sourcelanguage="en_GB">
<context>
<name>AuthenticationRequiredException</name>
<message>
@@ -107,7 +107,7 @@
<name>InstallerBase</name>
<message>
<source>Unable to start installer</source>
- <translation type="unfinished"></translation>
+ <translation>无法启动安装程序</translation>
</message>
</context>
<context>
@@ -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>
@@ -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>
@@ -515,6 +527,14 @@
<context>
<name>Lib7z</name>
<message>
+ <source>Internal code: %1</source>
+ <translation>内部代码:%1</translation>
+ </message>
+ <message>
+ <source>Not enough memory</source>
+ <translation>内存不足</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>错误:%1</translation>
</message>
@@ -578,14 +598,6 @@
<source>Unknown exception caught (%1)</source>
<translation>捕获到未知异常(%1)</translation>
</message>
- <message>
- <source>Internal code: %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not enough memory</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>LocalPackageHub</name>
@@ -729,7 +741,7 @@
</message>
<message>
<source>Cannot copy file &quot;%1&quot; to &quot;%2&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>无法将文件“%1”复制到“%2”。</translation>
</message>
<message>
<source>The specified module could not be found.</source>
@@ -737,7 +749,11 @@
</message>
<message>
<source>Invalid content in &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -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,11 +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>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>无法打开请求的 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>
@@ -829,44 +853,44 @@
<context>
<name>QInstaller::ComponentSelectionPage</name>
<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 type="unfinished"></translation>
+ <translation>在树视图中选择默认组件。</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 type="unfinished"></translation>
+ <translation>在树视图中将所有组件重置为其原始选择状态。</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 type="unfinished"></translation>
+ <translation>在树视图中选择所有组件。</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 type="unfinished"></translation>
+ <translation>在树视图中删除所有组件。</translation>
</message>
<message>
- <source>&amp;Browse QBSP files</source>
- <translation>浏览 QBSP 文件(&amp;B)</translation>
+ <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>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>
+ <source>Filter the enabled repository categories</source>
+ <translation>过滤已启用的存储库类别</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
@@ -893,36 +917,36 @@
<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 type="unfinished"></translation>
+ <translation>必须先更新必备组件,然后才能选择其他组件进行更新。</translation>
</message>
<message>
- <source>Alt+A</source>
- <comment>Select default components</comment>
- <translation type="unfinished">Alt+A</translation>
+ <source>Search</source>
+ <translation>搜索</translation>
</message>
<message>
- <source>Alt+R</source>
- <comment>Reset to already installed components</comment>
- <translation type="unfinished">Alt+R</translation>
+ <source>Browse &amp;QBSP files</source>
+ <translation>浏览&amp;QBSP文件</translation>
</message>
<message>
- <source>Alt+S</source>
- <comment>Select all components</comment>
- <translation type="unfinished">Alt+S</translation>
+ <source>Select</source>
+ <translation>选择</translation>
</message>
<message>
- <source>Alt+D</source>
- <comment>Deselect all components</comment>
- <translation type="unfinished">Alt+D</translation>
+ <source>Error</source>
+ <translation>错误</translation>
</message>
<message>
- <source>Filter the enabled repository categories</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -940,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>
@@ -1044,11 +1064,11 @@
</message>
<message>
<source>Cannot create path &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>无法创建路径“%1”。</translation>
</message>
<message>
<source>Cannot remove directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>无法删除目录“%1”。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading.</source>
@@ -1082,6 +1102,14 @@
<source>Cannot remove directory &quot;%1&quot;: %2</source>
<translation>无法移除目录“%1”:%2</translation>
</message>
+ <message>
+ <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>
@@ -1146,6 +1166,75 @@ Error while loading %2</source>
<source>Cannot find component for %1.</source>
<translation>无法找到 %1 的组件。</translation>
</message>
+ <message>
+ <source>%1 of %2</source>
+ <translation>%1/%2</translation>
+ </message>
+ <message>
+ <source>%1 downloaded.</source>
+ <translation>%1 已下载。</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s), </source>
+ <translation>
+ <numerusform>%n 天, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s), </source>
+ <translation>
+ <numerusform>%n 小时, </numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation>
+ <numerusform>%n 分钟,</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation>
+ <numerusform>%n 秒,</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source> - %1%2%3%4 remaining.</source>
+ <translation> - 剩余 %1%2%3%4。</translation>
+ </message>
+ <message>
+ <source> - unknown time remaining.</source>
+ <translation> - 剩余时间未知。</translation>
+ </message>
+ <message>
+ <source>Archive: </source>
+ <translation>存档:</translation>
+ </message>
+ <message>
+ <source>Total: </source>
+ <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>
<name>QInstaller::Downloader</name>
@@ -1156,16 +1245,19 @@ Error while loading %2</source>
<message>
<source>Cannot open file &quot;%1&quot; for writing: %2</source>
<extracomment>%2 is a sentence describing the error</extracomment>
+ <translatorcomment>%2 is a sentence describing the error</translatorcomment>
<translation>无法打开文件“%1”进行写入:%2</translation>
</message>
<message>
<source>File &quot;%1&quot; not open for writing: %2</source>
<extracomment>%2 is a sentence describing the error.</extracomment>
+ <translatorcomment>%2 is a sentence describing the error.</translatorcomment>
<translation>未打开文件“%1”进行写入:%2</translation>
</message>
<message>
<source>Writing to file &quot;%1&quot; failed: %2</source>
<extracomment>%2 is a sentence describing the error.</extracomment>
+ <translatorcomment>%2 is a sentence describing the error.</translatorcomment>
<translation>写入文件“%1”失败:%2</translation>
</message>
<message>
@@ -1174,11 +1266,12 @@ 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>
<extracomment>%1 is a sentence describing the error</extracomment>
+ <translatorcomment>%1 is a sentence describing the error</translatorcomment>
<translation>下载“%1”时出现未知的网络错误。</translation>
</message>
<message>
@@ -1192,6 +1285,7 @@ Error while loading %2</source>
<message>
<source>Invalid source URL &quot;%1&quot;: %2</source>
<extracomment>%2 is a sentence describing the error</extracomment>
+ <translatorcomment>%2 is a sentence describing the error</translatorcomment>
<translation>无效的源 URL“%1”:%2</translation>
</message>
</context>
@@ -1215,21 +1309,6 @@ Error while loading %2</source>
</message>
</context>
<context>
- <name>QInstaller::ExtractArchiveOperation::Runnable</name>
- <message>
- <source>Cannot open archive &quot;%1&quot; for reading: %2</source>
- <translation>无法打开存档“%1”进行读取:%2</translation>
- </message>
- <message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>提取存档“%1”时出错:%2</translation>
- </message>
- <message>
- <source>Unknown exception caught while extracting &quot;%1&quot;.</source>
- <translation>提取“%1”时捕获到未知异常。</translation>
- </message>
-</context>
-<context>
<name>QInstaller::FakeStopProcessForUpdateOperation</name>
<message>
<source>Cannot get package manager core.</source>
@@ -1294,15 +1373,15 @@ 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>
<source>Finished</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1314,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>
@@ -1355,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>
@@ -1391,13 +1474,13 @@ 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>有重要的更新可供使用,请先选择“%1”</translation>
+ </message>
</context>
<context>
<name>QInstaller::LicenseAgreementPage</name>
@@ -1406,6 +1489,11 @@ Error while loading %2</source>
<translation>许可协议</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>请阅读以下许可协议。 您必须接受此协议中的条款才能继续安装。</translation>
</message>
@@ -1421,11 +1509,6 @@ Error while loading %2</source>
<source>I accept the licenses.</source>
<translation>我接受这些许可。</translation>
</message>
- <message>
- <source>Alt+A</source>
- <comment>Agree license</comment>
- <translation type="unfinished">Alt+A</translation>
- </message>
</context>
<context>
<name>QInstaller::LicenseOperation</name>
@@ -1441,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 type="unfinished"></translation>
+ <translation>%1 中的无效参数:不支持空搜索参数。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -1468,14 +1547,14 @@ 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>
<message>
+ <source>Metadata download canceled.</source>
+ <translation>元数据下载已取消。</translation>
+ </message>
+ <message>
<source>Unknown exception during extracting.</source>
<translation>提取过程中出现未知异常。</translation>
</message>
@@ -1504,28 +1583,50 @@ Error while loading %2</source>
<translation>检测到“%1”的校验和不匹配。</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>提取存档“%1”时出错:%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>无法打开文件“%1”进行读取:%2</translation>
</message>
<message>
- <source>Error while extracting archive &quot;%1&quot;: %2</source>
- <translation>提取存档“%1”时出错:%2</translation>
+ <source>Unsupported archive &quot;%1&quot;: no handler registered for file suffix &quot;%2&quot;.</source>
+ <translation>不支持的存档“%1”:没有处理程序注册在文件后缀“%2”名下。</translation>
</message>
<message>
- <source>Unknown exception caught while extracting archive &quot;%1&quot;.</source>
- <translation>提取存档“%1”时捕获到未知异常。</translation>
+ <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>Cannot open file &quot;%1&quot; for reading: %2</source>
- <translation>无法打开文件“%1”进行读取:%2</translation>
+ <source>Clearing the cache directory and restarting the application may solve this.</source>
+ <translation>正在清空缓存目录并且重启应用程序也许可以解决这个问题。</translation>
</message>
<message>
- <source>Metadata download canceled.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1535,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>
@@ -1549,6 +1648,10 @@ Downloading packages...</source>
<translation>所有下载均已完成。</translation>
</message>
<message>
+ <source>Canceling the Installer</source>
+ <translation>正在取消安装程序</translation>
+ </message>
+ <message>
<source>Authentication Error</source>
<translation>身份验证错误</translation>
</message>
@@ -1643,36 +1746,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 component %1. Component is installed only as automatic dependency to %2.
-</source>
- <translation type="unfinished"></translation>
+ <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 type="unfinished"></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 %1. Component is virtual.
-</source>
- <translation type="unfinished"></translation>
+ <source>Component %1 already installed</source>
+ <translation>组件 %1 已安装</translation>
</message>
<message>
- <source>Cannot install %1. Component not found.
-</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is virtual.</source>
+ <translation>无法安装 %1。组件是虚拟的。</translation>
</message>
<message>
- <source>Running processes found.</source>
- <translation type="unfinished"></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>
- <translation type="unfinished"></translation>
+ <translation>请以管理员身份重新启动应用程序。</translation>
</message>
<message>
<source>Error while elevating access rights.</source>
@@ -1683,58 +1778,68 @@ Do you want to continue?</source>
<translation>错误</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>没有足够的磁盘空间来存储临时文件和安装。%1 可用,但至少需要 %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>没有足够的磁盘空间来存储所有选定的组件! %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 type="unfinished"></translation>
+ <translation>您选择安装的容量似乎有足够的安装空间,但之后的可用空间将不到该容量的 1%。</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>您选择安装的容量似乎有足够的安装空间,但之后的可用空间将不到 100 MB。</translation>
</message>
<message>
<source>Installation will use %1 of disk space.</source>
<translation>安装程序将使用 %1 的磁盘空间。</translation>
</message>
<message>
+ <source>Invalid</source>
+ <translation>无效</translation>
+ </message>
+ <message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>需要用户输入,但输出设备并未与任何终端裝置建立关联。</translation>
</message>
<message>
- <source>Cannot register component! Component with identifier %1 already exists.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot install %1. Component is a descendant of a virtual component %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 type="unfinished"></translation>
+ <translation>预估的安装程序大小 %1 可能超过被支持的可执行程序大小限制 %2。应用程序可能无法运行。</translation>
</message>
<message>
- <source>Canceling the Installer</source>
- <translation type="unfinished"></translation>
+ <source>Components about to be removed:</source>
+ <translation>即将要移除的组件:</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. There was a problem loading this component, so it is marked unstable and cannot be selected.</source>
+ <translation>无法安装组件 %1。加载这个组件时发生错误,所以它被标记为不稳定并且不能被选择。</translation>
</message>
<message>
- <source>Cannot install %1. Component is a descendant of a virtual component %2.
-</source>
- <translation type="unfinished"></translation>
+ <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>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>
+ <source>Cannot resolve components to uninstall.</source>
+ <translation>无法解析要移除的组件。</translation>
</message>
<message>
- <source>Not enough disk space to store all selected components! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <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>Not enough disk space to store temporary files! %1 are available, while the minimum required is %2.</source>
- <translation type="unfinished"></translation>
+ <source>Cannot select %1. Alias is marked virtual, meaning it cannot be selected manually.</source>
+ <translation>无法选择%1。别名被标记为虚拟,意味着它不能被手动选中。</translation>
</message>
<message>
- <source>Invalid</source>
- <translation type="unfinished"></translation>
+ <source>Created installer will use %1 of disk space.</source>
+ <translation>创建的安装程序将使用%1的磁盘空间。</translation>
</message>
</context>
<context>
@@ -1777,11 +1882,11 @@ Do you want to continue?</source>
</message>
<message>
<source>Retry count exceeded</source>
- <translation type="unfinished"></translation>
+ <translation>超过重试次数</translation>
</message>
<message>
<source>Writing maintenance tool.</source>
- <translation>编写维护工具</translation>
+ <translation>编写维护工具。</translation>
</message>
<message>
<source>Failed to seek in file %1: %2</source>
@@ -1805,7 +1910,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot remove temporary data file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>无法删除临时数据文件 &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot write maintenance tool binary data to %1: %2</source>
@@ -1813,7 +1918,7 @@ Do you want to continue?</source>
</message>
<message>
<source>Writing offline base binary.</source>
- <translation type="unfinished"></translation>
+ <translation>正在编写离线基本二进制文件。</translation>
</message>
<message>
<source>Cannot remove file &quot;%1&quot;: %2</source>
@@ -1825,11 +1930,11 @@ Do you want to continue?</source>
</message>
<message>
<source>Cannot write offline binary to &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>无法将离线二进制文件写入 &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Cannot remove temporary file &quot;%1&quot;: %2</source>
- <translation type="unfinished"></translation>
+ <translation>无法删除临时文件 &quot;%1&quot;: %2</translation>
</message>
<message>
<source>Variable &apos;TargetDir&apos; not set.</source>
@@ -1852,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>
@@ -1872,54 +1973,56 @@ 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>
+ <translation>成功卸载。</translation>
+ </message>
+ <message>
+ <source>Removal aborted.</source>
+ <translation>卸载已中止。</translation>
</message>
<message>
<source>Cannot create target directory for installer.</source>
- <translation type="unfinished"></translation>
+ <translation>无法为安装程序创建目标目录。</translation>
</message>
<message>
<source>Preparing offline generation...</source>
- <translation type="unfinished"></translation>
+ <translation>正在准备离线生成......</translation>
</message>
<message>
<source>Preparing installer configuration...</source>
- <translation type="unfinished"></translation>
+ <translation>正在准备安装程序配置......</translation>
</message>
<message>
<source>Creating the installer...</source>
- <translation type="unfinished"></translation>
+ <translation>正在创建安装程序......</translation>
</message>
<message>
<source>Failed to create offline installer. %1</source>
- <translation type="unfinished"></translation>
+ <translation>无法创建离线安装程序。%1</translation>
</message>
<message>
<source>Cannot remove temporary directory &quot;%1&quot;.</source>
- <translation type="unfinished"></translation>
+ <translation>无法删除临时目录“%1”。</translation>
</message>
<message>
<source>Offline generation completed successfully.</source>
- <translation type="unfinished"></translation>
+ <translation>离线生成已顺利完成。</translation>
</message>
<message>
<source>Offline generation aborted!</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -1933,7 +2036,21 @@ Installing component %1</source>
</message>
<message>
<source>Done</source>
- <translation type="unfinished"></translation>
+ <translation>已完成</translation>
+ </message>
+ <message>
+ <source>Cannot prepare removal</source>
+ <translation>无法准备卸载</translation>
+ </message>
+ <message>
+ <source>Cannot start removal</source>
+ <translation>无法开始卸载</translation>
+ </message>
+ <message>
+ <source>Error during removal process:
+%1</source>
+ <translation>卸载过程中出现错误:
+%1</translation>
</message>
<message>
<source>Unknown error</source>
@@ -1952,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>
@@ -1964,25 +2077,48 @@ Installing component %1</source>
<translation>检测到组件“%1”和“%2”之间的依赖项循环。</translation>
</message>
<message>
- <source>Removal completed successfully.</source>
- <translation type="unfinished"></translation>
+ <source>Preparing to unpack components...</source>
+ <translation>正在准备解压组件......</translation>
</message>
<message>
- <source>Removal aborted.</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations completed.</source>
+ <translation>%2 个操作中的 %1 个已经完成。</translation>
</message>
<message>
- <source>Cannot prepare removal</source>
- <translation type="unfinished"></translation>
+ <source>Unpacking components...</source>
+ <translation>正在解压组件......</translation>
</message>
<message>
- <source>Cannot start removal</source>
- <translation type="unfinished"></translation>
+ <source>%1 of %2 operations rolled back.</source>
+ <translation>%2 个操作中的 %1 个已经回滚。</translation>
</message>
<message>
- <source>Error during removal process:
-%1</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2000,6 +2136,10 @@ Installing component %1</source>
<translation>是否要取消安装过程?</translation>
</message>
<message>
+ <source>Do you want to cancel the removal process?</source>
+ <translation>是否要取消卸载过程?</translation>
+ </message>
+ <message>
<source>Do you want to quit the installer application?</source>
<translation>是否要退出安装程序应用程序?</translation>
</message>
@@ -2016,12 +2156,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 type="unfinished"></translation>
+ <translation>指定代理设置,并为附加组件配置存储库。</translation>
</message>
<message>
<source>Error</source>
@@ -2033,20 +2173,16 @@ Please copy the installer to a local drive</source>
<translation>无法从网络位置进行安装。
请将安装程序复制到本地驱动器</translation>
</message>
- <message>
- <source>Do you want to cancel the removal process?</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<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>
@@ -2077,15 +2213,27 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Installing</source>
- <translation type="unfinished"></translation>
+ <translation>正在安装</translation>
</message>
<message>
<source>Updating</source>
- <translation type="unfinished"></translation>
+ <translation>正在更新</translation>
</message>
<message>
<source>Uninstalling</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2130,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>
@@ -2154,12 +2302,24 @@ 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 type="unfinished"></translation>
+ <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>
@@ -2184,11 +2344,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>不支持当前的搜索参数使用空搜索参数调用“%1”。</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>当前使用参数“%2”的模式参数调用“%1”不被支持。请使用字符串或正则表达式。</translation>
</message>
<message>
<source>Cannot open file &quot;%1&quot; for reading: %2</source>
@@ -2217,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>
@@ -2247,12 +2407,12 @@ Please copy the installer to a local drive</source>
<translation>操作 %1 中所需的安装程序对象为空。</translation>
</message>
<message>
- <source>Self Restart: Invalid arguments</source>
- <translation>自动重启:无效的参数</translation>
+ <source>Self Restart: Only valid within updater or package manager mode.</source>
+ <translation>自动重启:仅在更新程序或包管理器模式下有效。</translation>
</message>
<message>
- <source>Self Restart: Only valid within updater or package manager mode.</source>
- <translation type="unfinished"></translation>
+ <source>Self Restart: Invalid arguments</source>
+ <translation>自动重启:无效的参数</translation>
</message>
</context>
<context>
@@ -2286,7 +2446,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>使用参数“%2”调用“%1”的当前方法参数不受支持。 请使用 set、remove、add_array_value 或 remove_array_value。</translation>
</message>
</context>
<context>
@@ -2330,22 +2490,22 @@ Please copy the installer to a local drive</source>
<translation>请指定将安装 %1 的目录。</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;R)...</translation>
</message>
<message>
<source>Browse file system to choose the installation directory.</source>
- <translation type="unfinished"></translation>
+ <translation>浏览文件系统以选择安装目录。</translation>
</message>
<message>
<source>Select Installation Folder</source>
<translation>选择安装文件夹</translation>
</message>
- <message>
- <source>Alt+R</source>
- <comment>Browse file system to choose a file</comment>
- <translation type="unfinished">Alt+R</translation>
- </message>
</context>
<context>
<name>QInstaller::TestRepository</name>
@@ -2394,31 +2554,31 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Cannot start installer binary as updater.</source>
- <translation type="unfinished"></translation>
+ <translation>无法将安装程序二进制文件作为更新程序启动。</translation>
</message>
<message>
<source>Cannot start installer binary as package manager.</source>
- <translation type="unfinished"></translation>
+ <translation>无法将安装程序二进制文件作为包管理器启动。</translation>
</message>
<message>
<source>Cannot start installer binary as uninstaller.</source>
- <translation type="unfinished"></translation>
+ <translation>无法将安装程序二进制文件作为卸载程序启动。</translation>
</message>
<message>
<source>Empty repository list for option &apos;addRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>“addRepository”选项的空存储库列表。</translation>
</message>
<message>
<source>Empty repository list for option &apos;addTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>“addTempRepository”选项的空存储库列表。</translation>
</message>
<message>
<source>Empty repository list for option &apos;setTempRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>‘setTempRepository&apos;选项的空存储库列表。</translation>
</message>
<message>
<source>Empty repository list for option &apos;installCompressedRepository&apos;.</source>
- <translation type="unfinished"></translation>
+ <translation>‘installCompressedRepository&apos;选项的空存储库列表。</translation>
</message>
<message>
<source>The file %1 does not exist.</source>
@@ -2426,19 +2586,27 @@ Please copy the installer to a local drive</source>
</message>
<message>
<source>Arguments missing for option %1</source>
- <translation type="unfinished"></translation>
+ <translation>选项 %1 缺少参数</translation>
</message>
<message>
<source>Invalid button value %1 </source>
- <translation type="unfinished"></translation>
+ <translation>无效的按钮值 %1 </translation>
</message>
<message>
<source>Incorrect arguments for %1</source>
- <translation type="unfinished"></translation>
+ <translation>%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 type="unfinished"></translation>
+ <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>
@@ -2466,7 +2634,10 @@ as a user with the appropriate rights and then clicking OK.</source>
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>无法获得继续安装所需的授权。
+
+请以具有适当权限的用户身份启动安装程序。
+或者在被询问时接受访问权限的提升。</translation>
</message>
</context>
<context>
@@ -2483,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 type="unfinished"></translation>
+ <source>Categories</source>
+ <translation>类别</translation>
</message>
</context>
<context>
@@ -2562,6 +2733,10 @@ or accept the elevation of access rights if being asked.</source>
<translation>添加密码以在服务器端进行身份验证。</translation>
</message>
<message>
+ <source>The server&apos;s URL that contains a valid repository.</source>
+ <translation>服务器 URL 包含有效的资料档案库。</translation>
+ </message>
+ <message>
<source>An error occurred while testing this repository.</source>
<translation>测试此资料档案库时出错。</translation>
</message>
@@ -2611,15 +2786,35 @@ or accept the elevation of access rights if being asked.</source>
</message>
<message>
<source>Select All</source>
- <translation type="unfinished"></translation>
+ <translation>全选</translation>
</message>
<message>
<source>Deselect All</source>
- <translation type="unfinished"></translation>
+ <translation>取消全选</translation>
</message>
<message>
- <source>The server&apos;s URL that contains a valid repository.</source>
- <translation type="unfinished"></translation>
+ <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>
@@ -2673,29 +2868,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>筛选</translation>
</message>
<message>
<source>Error</source>
<translation>错误</translation>
</message>
<message>
- <source>Component Information</source>
- <translation type="unfinished"></translation>
+ <source>Information</source>
+ <translation>组件信息</translation>
</message>
</context>
<context>
<name>QInstaller::ExtractArchiveOperation</name>
<message>
<source>Extracting &quot;%1&quot;</source>
- <translation type="unfinished"></translation>
+ <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>
<message>
<source>User input is required but the output device is not associated with a terminal.</source>
- <translation type="unfinished"></translation>
+ <translation>需要用户输入,但输出设备并未与任何终端裝置建立关联。</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>无法为存档“%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 extracting archive &quot;%1&quot;: %2</source>
+ <translation>提取存档“%1”时出错:%2</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>QInstaller::ExtractWorker</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>
+</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>
diff --git a/src/sdk/translations/translations.pro b/src/sdk/translations/translations.pro
index a951a5b53..397691fcc 100644
--- a/src/sdk/translations/translations.pro
+++ b/src/sdk/translations/translations.pro
@@ -9,7 +9,7 @@ IB_TRANSLATIONS -= $$PWD/ifw_en.ts
wd = $$toNativeSeparators($$IFW_SOURCE_TREE)
sources = src
-lupdate_opts = -locations relative -no-ui-lines -no-sort
+lupdate_opts = -locations relative -no-ui-lines -no-sort -no-obsolete
IB_ALL_TRANSLATIONS = $$IB_TRANSLATIONS $$PWD/ifw_untranslated.ts
for(file, IB_ALL_TRANSLATIONS) {