diff options
55 files changed, 1453 insertions, 36 deletions
diff --git a/doc/reference/items/convenience/androidapk.qdoc b/doc/reference/items/convenience/androidapk.qdoc index 17496bbc3..c3cce0ea1 100644 --- a/doc/reference/items/convenience/androidapk.qdoc +++ b/doc/reference/items/convenience/androidapk.qdoc @@ -27,7 +27,7 @@ /*! \contentspage list-of-convenience-items.html \page androidapk-item.html - \nextpage application-item.html + \nextpage applediskimage-item.html \ingroup list-of-convenience-items \ingroup list-of-items diff --git a/doc/reference/items/convenience/appleapplicationdiskimage.qdoc b/doc/reference/items/convenience/appleapplicationdiskimage.qdoc new file mode 100644 index 000000000..7612d60bf --- /dev/null +++ b/doc/reference/items/convenience/appleapplicationdiskimage.qdoc @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ +/*! + \contentspage list-of-convenience-items.html + \page appleapplicationdiskimage-item.html + \previouspage applediskimage-item.html + \nextpage application-item.html + \ingroup list-of-convenience-items + \ingroup list-of-items + + \title AppleApplicationDiskImage Item + \brief Represents a product that is an Apple application drag 'n' drop disk image installer. + + An \c AppleApplicationDiskImage item is a convenience item that has a dependency on the + \l{Module dmg}{DMG module} and whose type is \c{["dmg.dmg"]}, and also has rules and properties + specific to building drag 'n' drop disk image installers with an application bundle and symbolic + link to the /Applications directory. + + Any artifacts of product dependencies which are tagged \c{"installable"} will be copied into the + disk image, provided their file paths are relative to the path specified by the \c{sourceBase} + property (i.e. are located in that directory). Any artifacts tagged \c{"installable"} and which + are not relative to \c{sourceBase} will be ignored. + + Here is what the project file could look like for a simple DMG installer: + \code + import qbs + + AppleApplicationDiskImage { + Depends { name: "myapp" } + name: "My App" + dmg.volumeName: name + dmg.iconSize: 128 + dmg.windowWidth: 640 + dmg.windowHeight: 280 + dmg.iconPositions: [ + {"path": "Applications", "x": 128, "y": 128}, + {"path": "My App.app", "x": 256, "y": 128} + ] + files: ["background.tiff", "volume-icon.icns"] + Group { + files: ["*.lproj/**"] // licenses + fileTags: ["dmg.license.input"] + } + } + \endcode + + For plain disk images whose contents are not a single application bundle, consider the base + \l{AppleDiskImage Item}{AppleDiskImage} item instead. + + \section1 AppleApplicationDiskImage Properties + The following properties are available in addition to the ones inherited from \c AppleDiskImage. + + \table + \header + \li Property + \li Type + \li Since + \li Default + \li Description + \row + \li sourceBase + \li \c{string} + \li 1.9 + \li /Applications + \li The base directory from which artifacts installed into the disk image will be copied. + This directory is always considered to be relative to \c{qbs.installRoot}. + For example, if the application Example.app exists at + \c{qbs.installRoot}/Applications/Example.app, and \c{sourceBase} is + \c{/Applications}, the application will be located at /Example.app + relative to the disk image root, and therefore its full path when the disk image is + mounted would be something like /Volumes/Example-1.0/Example.app. + \row + \li symlinks + \li \c{stringList} + \li 1.9 + \li \c{["/Applications:Applications"]} + \li List of symlinks to create in the disk image. This is specified as a list of strings, + each string containing two file paths separated by a colon. The first path is the + symlink target, and the second path is the name of the symlink relative to the root of + the disk image. + \endtable +*/ diff --git a/doc/reference/items/convenience/applediskimage.qdoc b/doc/reference/items/convenience/applediskimage.qdoc new file mode 100644 index 000000000..ffd335212 --- /dev/null +++ b/doc/reference/items/convenience/applediskimage.qdoc @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ +/*! + \contentspage list-of-convenience-items.html + \page applediskimage-item.html + \previouspage androidapk-item.html + \nextpage appleapplicationdiskimage-item.html + \ingroup list-of-convenience-items + \ingroup list-of-items + + \title AppleDiskImage Item + \brief Represents a product that is an Apple disk image. + + An \c AppleDiskImage item is a convenience item that has a dependency on the + \l{Module dmg}{DMG module} and whose type is \c{["dmg.dmg"]}. + + For single-application drag 'n' drop disk image installers, you'll probably want to use the + \l{AppleApplicationDiskImage Item}{AppleApplicationDiskImage} item instead. +*/ diff --git a/doc/reference/items/convenience/application.qdoc b/doc/reference/items/convenience/application.qdoc index 1a13724b1..d254e84ee 100644 --- a/doc/reference/items/convenience/application.qdoc +++ b/doc/reference/items/convenience/application.qdoc @@ -27,7 +27,7 @@ /*! \contentspage list-of-convenience-items.html \page application-item.html - \previouspage androidapk-item.html + \previouspage appleapplicationdiskimage-item.html \nextpage applicationextension-item.html \ingroup list-of-convenience-items \ingroup list-of-items diff --git a/doc/reference/modules/dmg-module.qdoc b/doc/reference/modules/dmg-module.qdoc new file mode 100644 index 000000000..6a11e6c4b --- /dev/null +++ b/doc/reference/modules/dmg-module.qdoc @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \contentspage index.html + \page dmg-module.html + \ingroup list-of-modules + + \title Module dmg + \since 1.9 + \brief Provides support for building Apple Disk Images + + The \c dmg module contains properties and rules for building Apple Disk Images, which are + typically used to distribute applications and installers on macOS. + + This module is only available on Apple platforms. + + \section1 General Properties + + \table + \header + \li Property + \li Type + \li Since + \li Default + \li Description + \row + \li volumeName + \li \c{string} + \li 1.9 + \li \c{product.targetName} + \li The name of the disk image which displayed in Finder when the DMG is mounted. + \row + \li badgeVolumeIcon + \li \c{bool} + \li 1.9 + \li \c{false} + \li Whether to render the user-supplied icon (see the \c{"icns"} file tag documentation) + on top of the default volume icon instead of using it directly. This generally gives + the disk image icon a better and more consistent appearance. + \row + \li format + \li \c{string} + \li 1.9 + \li \c{"UDBZ"} + \li The format to create the disk image in. + Allowed values include but are not limited to \c{"UDZO"}, \c{"UDBZ"} and \c{"ULFO"}. + \row + \li compressionLevel + \li \c{int} + \li 1.9 + \li 9 in release mode, otherwise undefined + \li Sets the zlib, bzip2, or lzfse compression level for UDZO, UDBZ, or ULFO disk images. + \row + \li sourceBase + \li \c{string} + \li 1.9 + \li \c{undefined} + \li Specifies the base directory of the files that are going to be embedded in the DMG + (see the \c{"dmg.input"} file tag documentation). The source base directory is omitted + from the target directory path of the DMG directory. + The default value of this property is the directory of the current file + to be embedded, relative to the product's source directory. + \endtable + + \section1 Appearance Properties + + Properties in this section are used to control the contents of the .DS_Store file and its + embedded Alias and Bookmark records, that will be generated by \QBS in order to control the + appearance of the disk image when mounted in Finder. + + \table + \header + \li Property + \li Type + \li Since + \li Default + \li Description + \row + \li backgroundColor + \li \c{string} + \li 1.9 + \li \c{undefined} + \li Specifies the background color of the disk image as seen when mounted in Finder. + Refer to the \l{https://dmgbuild.readthedocs.io/en/latest/settings.html#background} + {dmgbuild documentation} + for the full list of supported color names and formats. + To use an image for the background instead, + refer to the \c{"tiff"} file tag documentation. + \row + \li iconSize + \li \c{int} + \li 1.9 + \li \c{128} + \li Specifies the width and height of the file icons as seen when the disk image is mounted + in Finder. + \row + \li windowX + \li \c{int} + \li 1.9 + \li \c{100} + \li Specifies the X position of the Finder window that displays the disk image contents + when it is mounted. + \row + \li windowY + \li \c{int} + \li 1.9 + \li \c{100} + \li Specifies the Y position of the Finder window that displays the disk image contents + when it is mounted. + \row + \li windowWidth + \li \c{int} + \li 1.9 + \li \c{640} + \li Specifies the width of the Finder window that displays the disk image contents + when it is mounted. + \row + \li windowHeight + \li \c{int} + \li 1.9 + \li \c{480} + \li Specifies the height of the Finder window that displays the disk image contents + when it is mounted. Note that the window height includes the height of the standard + macOS title bar (22 points). + \row + \li iconPositions + \li \c{list} + \li 1.9 + \li \c{undefined} + List of objects containing \c{path}, \c{x}, and \c{y} properties, which correspond to + disk image-relative file paths and visual coordinates of file icons in the disk image + as seen when it is mounted in Finder. For example: + \code + dmg.iconPositions: [ + {"path": "Applications", "x": 128, "y": 128}, + {"path": "Foo Bar.app", "x": 256, "y": 128} + ] + \endcode + This property is useful for specifying the positions of files where you do not have + direct control over the corresponding \QBS artifact, or there is no corresponding \QBS + artifact (for example, "Foo Bar.app" is a directory, which has no equivalent artifact in + the build graph). For files to which you are directly applying the \c{dmg.input} file + tag, you should use the \c{dmg.iconX} and \c{dmg.iconY} properties instead. + \row + \li iconX + \li \c{int} + \li 1.9 + \li \c{windowWidth / 2} + \li X position of the file icon in the Finder window that displayed the disk image contents + when it is mounted. This property is only useful with artifacts tagged \c{dmg.input} and + cannot be used at the product level to affect all files. + If you do not have access to the artifact corresponding to the file whose position you + want to set, use the \c{dmg.iconPositions} property instead. + \row + \li iconY + \li \c{int} + \li 1.9 + \li \c{windowHeight / 2} + \li Y position of the file icon in the Finder window that displayed the disk image contents + when it is mounted. This property is only useful with artifacts tagged \c{dmg.input} and + cannot be used at the product level to affect all files. + If you do not have access to the artifact corresponding to the file whose position you + want to set, use the \c{dmg.iconPositions} property instead. + \endtable + + \section1 License Properties + + Properties in this section are used to control the content and appearance of the license prompt + displayed when a user attempts to mount the resulting disk image via Finder. + + \table + \header + \li Property + \li Type + \li Since + \li Default + \li Description + \row + \li defaultLicenseLocale + \li \c{string} + \li 1.9 + \li \c{"en_US"} + \li Locale of the default license to display when there is no license whose locale matches + the system locale. + \row + \li licenseLocale + \li \c{string} + \li 1.9 + \li determined automatically + \li Locale of the license file. Defaults to a value guess from the file path, specifically + the base name of any .lproj directory found in the file's path. If the locale could not + be determined from the file path and this property is not set, an error will be emitted. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \row + \li licenseLanguageName + \li \c{string} + \li 1.9 + \li \c{"English"} + \li Name of the language associated with the license file, localized for that language. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \row + \li licenseAgreeButtonText + \li \c{string} + \li 1.9 + \li \c{"Agree"} + \li Text shown on the "Agree" button associated with the license file, + localized for that language. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \row + \li licenseDisagreeButtonText + \li \c{string} + \li 1.9 + \li \c{"Disagree"} + \li Text shown on the "Disagree" button associated with the license file, + localized for that language. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \row + \li licensePrintButtonText + \li \c{string} + \li 1.9 + \li \c{"Print"} + \li Text shown on the "Print" button associated with the license file, + localized for that language. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \row + \li licenseSaveButtonText + \li \c{string} + \li 1.9 + \li \c{"Save"} + \li Text shown on the "Save" button associated with the license file, + localized for that language. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \row + \li licenseInstructionText + \li \c{string} + \li 1.9 + \li \c{"If you agree with the terms of this license, press \"Agree\" to install the software. If you do not agree, press \"Disagree\"."} + \li Instruction text associated with the license file that will be shown on the license + dialog, localized for that language. + This property is only useful with artifacts tagged \c{dmg.license.input} and + cannot be used at the product level to affect all files. + \endtable + + \section1 Advanced Properties + + \table + \header + \li Property + \li Type + \li Since + \li Default + \li Description + \row + \li dmgSuffix + \li \c{string} + \li 1.9 + \li \c{".dmg"} + \li File extension for disk images. + This should not normally need to be changed. + \row + \li hdiutilPath + \li \c{string} + \li 1.9 + \li \c{"/usr/bin/hdiutil"} + \li Path to the hdiutil binary used to perform disk image related operations. + This should not normally need to be changed. + \row + \li textutilPath + \li \c{string} + \li 1.9 + \li \c{"/usr/bin/textutil"} + \li Path to the textutil binary used to convert license agreement files to rich text format. + This should not normally need to be changed. + \endtable + + \section1 Relevant File Tags + + \table + \header + \li Tag + \li Auto-tagged File Names + \li Since + \li Description + \row + \li \c{"dmg.input"} + \li n/a + \li 1.9 + \li If the product contains files with this tag, they will be copied into the disk image. + See the \c{sourceBase} property to learn how to control the destination directory and + hierarchy of copied files within the disk image. + \row + \li \c{"dmg.license.input"} + \li \c{*.txt}, \c{*.rtf}, \c{*.html}, \c{*.doc}, \c{*.docx}, \c{*.odt}, \c{*.xml}, + \c{*.webarchive} + \li 1.9 + \li If the product contains files with this tag, they will be converted into rich text and + used for the license prompt when mounting the DMG. + \row + \li \c{"icns"} + \li \c{*.icns} + \li 1.3 + \li If the product contains a file with this tag, it will be added as the Apple Disk Image + volume icon, which will show up in the Finder as an overlay on the file icon. + \row + \li \c{"tiff"} + \li \c{*.tif}, \c{*.tiff} + \li 1.9 + \li If the product contains a file with this tag, it will be used as the background image + of the directory as shown in Finder when the DMG file is mounted. + \endtable +*/ diff --git a/examples/cocoa-application/CocoaApplication.qbs b/examples/cocoa-application/CocoaApplication.qbs index 2c26904a8..d0d2affc6 100644 --- a/examples/cocoa-application/CocoaApplication.qbs +++ b/examples/cocoa-application/CocoaApplication.qbs @@ -36,39 +36,18 @@ ** ****************************************************************************/ -import qbs 1.0 +import qbs +import qbs.Utilities -CppApplication { - Depends { condition: product.condition; name: "ib" } - condition: qbs.targetOS.contains("macos") - name: "Cocoa Application" +Project { + references: [ + "app.qbs" + ] - cpp.useObjcPrecompiledHeader: true - - cpp.frameworks: ["Cocoa"] - - Group { - prefix: "CocoaApplication/" - files: [ - "AppDelegate.h", - "AppDelegate.m", - "CocoaApplication-Info.plist", - "main.m" - ] - } - - Group { - name: "Supporting Files" - prefix: "CocoaApplication/en.lproj/" - files: [ - "Credits.rtf", - "InfoPlist.strings", - "MainMenu.xib" - ] - } - - Group { - files: ["CocoaApplication/CocoaApplication-Prefix.pch"] - fileTags: ["objc_pch_src"] + SubProject { + filePath: "dmg.qbs" + Properties { + condition: Utilities.versionCompare(qbs.version, "1.9") >= 0 + } } } diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..7cd4f8e12 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16x16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16x16@2x.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32x32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32x32@2x.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128x128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128x128@2x.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256x256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256x256@2x.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512x512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512x512@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +}
\ No newline at end of file diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.png Binary files differnew file mode 100644 index 000000000..6c556a835 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.png Binary files differnew file mode 100644 index 000000000..4442d3eb2 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_128x128@2x.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.png Binary files differnew file mode 100644 index 000000000..2adcdb5f4 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.png Binary files differnew file mode 100644 index 000000000..2a7030fd7 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_16x16@2x.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.png Binary files differnew file mode 100644 index 000000000..4442d3eb2 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.png Binary files differnew file mode 100644 index 000000000..069b5c050 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_256x256@2x.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.png Binary files differnew file mode 100644 index 000000000..2a7030fd7 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.png Binary files differnew file mode 100644 index 000000000..c5e458164 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_32x32@2x.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.png Binary files differnew file mode 100644 index 000000000..069b5c050 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512.png diff --git a/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.png Binary files differnew file mode 100644 index 000000000..0b810615e --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset/icon_512x512@2x.png diff --git a/examples/cocoa-application/CocoaApplication/background.png b/examples/cocoa-application/CocoaApplication/background.png Binary files differnew file mode 100644 index 000000000..938dc0c04 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/background.png diff --git a/examples/cocoa-application/CocoaApplication/background@2x.png b/examples/cocoa-application/CocoaApplication/background@2x.png Binary files differnew file mode 100644 index 000000000..099e9d830 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/background@2x.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png Binary files differnew file mode 100644 index 000000000..6c556a835 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png Binary files differnew file mode 100644 index 000000000..4442d3eb2 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png Binary files differnew file mode 100644 index 000000000..2adcdb5f4 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png Binary files differnew file mode 100644 index 000000000..2a7030fd7 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16@2x.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png Binary files differnew file mode 100644 index 000000000..4442d3eb2 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png Binary files differnew file mode 100644 index 000000000..069b5c050 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png Binary files differnew file mode 100644 index 000000000..2a7030fd7 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png Binary files differnew file mode 100644 index 000000000..c5e458164 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png Binary files differnew file mode 100644 index 000000000..069b5c050 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png diff --git a/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png Binary files differnew file mode 100644 index 000000000..0b810615e --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png diff --git a/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE b/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE new file mode 100644 index 000000000..44650fe73 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE @@ -0,0 +1,27 @@ +Copyright (C) 2017 The Qt Company Ltd. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"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 COPYRIGHT +OWNER OR CONTRIBUTORS 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. diff --git a/examples/cocoa-application/CocoaApplication/en_US.lproj b/examples/cocoa-application/CocoaApplication/en_US.lproj new file mode 120000 index 000000000..545e7ac76 --- /dev/null +++ b/examples/cocoa-application/CocoaApplication/en_US.lproj @@ -0,0 +1 @@ +en.lproj
\ No newline at end of file diff --git a/examples/cocoa-application/app.qbs b/examples/cocoa-application/app.qbs new file mode 100644 index 000000000..366d49263 --- /dev/null +++ b/examples/cocoa-application/app.qbs @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of the examples of Qbs. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "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 COPYRIGHT +** OWNER OR CONTRIBUTORS 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." +** +****************************************************************************/ + +import qbs + +CppApplication { + Depends { condition: product.condition; name: "ib" } + condition: qbs.targetOS.contains("macos") + name: "Cocoa Application" + + cpp.useObjcPrecompiledHeader: true + + cpp.frameworks: ["Cocoa"] + + Group { + prefix: "CocoaApplication/" + files: [ + "AppDelegate.h", + "AppDelegate.m", + "CocoaApplication-Info.plist", + "CocoaApplication.xcassets", + "main.m" + ] + } + + Group { + name: "Supporting Files" + prefix: "CocoaApplication/en.lproj/" + files: [ + "Credits.rtf", + "InfoPlist.strings", + "MainMenu.xib" + ] + } + + Group { + files: ["CocoaApplication/CocoaApplication-Prefix.pch"] + fileTags: ["objc_pch_src"] + } + + Group { + fileTagsFilter: ["bundle.content"] + qbs.install: true + qbs.installDir: "Applications" + qbs.installSourceBase: product.destinationDirectory + } + + ib.appIconName: "AppIcon" +} diff --git a/examples/cocoa-application/dmg.qbs b/examples/cocoa-application/dmg.qbs new file mode 100644 index 000000000..e8e0a923a --- /dev/null +++ b/examples/cocoa-application/dmg.qbs @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of the examples of Qbs. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "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 COPYRIGHT +** OWNER OR CONTRIBUTORS 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." +** +****************************************************************************/ + +import qbs + +AppleApplicationDiskImage { + condition: qbs.targetOS.contains("macos") + name: "Cocoa Application DMG" + targetName: "cocoa-application-" + version + version: "1.0" + + Depends { name: "Cocoa Application" } + Depends { name: "ib" } + + files: [ + "CocoaApplication/dmg.iconset", + "CocoaApplication/en_US.lproj/LICENSE", + ] + + // set to false to use a solid-color background (see dmg.backgroundColor below) + property bool useImageBackground: true + Group { + condition: useImageBackground + files: ["CocoaApplication/background*"] + } + + dmg.backgroundColor: "#41cd52" + dmg.badgeVolumeIcon: true + dmg.iconPositions: [ + {"x": 200, "y": 200, "path": "Cocoa Application.app"}, + {"x": 400, "y": 200, "path": "Applications"} + ] + dmg.windowX: 420 + dmg.windowY: 250 + dmg.windowWidth: 600 + dmg.windowHeight: 422 // this *includes* the macOS title bar height of 22 + dmg.iconSize: 64 +} diff --git a/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs new file mode 100644 index 000000000..d1d4988c6 --- /dev/null +++ b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** 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://www.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. +** +** In addition, 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. +** +****************************************************************************/ + +import qbs.File +import qbs.FileInfo +import qbs.ModUtils + +AppleDiskImage { + property string sourceBase: "/Applications" + readonly property string absoluteSourceBase: FileInfo.joinPaths(qbs.installRoot, sourceBase) + property stringList symlinks: ["/Applications:Applications"] + + readonly property string stageDirectory: FileInfo.joinPaths(destinationDirectory, "Volumes", dmg.volumeName) + + Rule { + multiplex: true + inputs: ["qbs"] + outputFileTags: ["dmg.input", "dmg.input.symlink"] + outputArtifacts: Array.prototype.map.call(product.symlinks, function (symlink) { + var symlinkTarget = symlink.split(':')[0]; + var symlinkName = symlink.split(':')[1] || symlinkTarget; + if (FileInfo.isAbsolutePath(symlinkName)) + throw(symlink + " is an invalid symlink; the destination must be a relative path"); + return { + filePath: FileInfo.joinPaths(product.stageDirectory, symlinkName), + fileTags: ["dmg.input", "dmg.input.symlink"], + dmg: { symlinkTarget: symlinkTarget, sourceBase: product.stageDirectory }, + }; + }) + prepare: Array.prototype.map.call(outputs["dmg.input"], function (symlink) { + var cmd = new Command("ln", ["-sfn", symlink.dmg.symlinkTarget, symlink.filePath]); + cmd.workingDirectory = product.stageDirectory; + cmd.description = "symlinking " + symlink.fileName + " => " + symlink.dmg.symlinkTarget; + return cmd; + }); + } + + Rule { + multiplex: true + inputs: ["dmg.input.symlink"] + inputsFromDependencies: ["installable"] + outputFileTags: ["dmg.input"] + outputArtifacts: { + var absSourceBase = product.absoluteSourceBase; + var symlinkPaths = (inputs["dmg.input.symlink"] || []).map(function (s) { return s.filePath; }); + return Array.prototype.map.call(inputs["installable"], function (a) { + var fp = ModUtils.artifactInstalledFilePath(a); + if (fp.startsWith(absSourceBase)) { + var outputFilePath = fp.replace(absSourceBase, product.stageDirectory); + + // Check for symlink conflicts + for (var i in symlinkPaths) { + if (outputFilePath.startsWith(symlinkPaths[i])) + throw new Error("Cannot install '" + a.filePath + + "' to '" + outputFilePath + "' because it " + + "would conflict with the symlink at '" + + symlinkPaths[i] + "'"); + } + + return { + filePath: outputFilePath, + fileTags: ["dmg.input"], + dmg: { sourceBase: product.stageDirectory } + } + } + }).filter(function (a) { return !!a; }); + } + prepare: { + var absSourceBase = product.absoluteSourceBase; + var cmds = [], dmgs = outputs["dmg.input"]; + for (var i in dmgs) { + var a = dmgs[i]; + var cmd = new JavaScriptCommand(); + cmd.src = a.filePath.replace(product.stageDirectory, absSourceBase); + cmd.dst = a.filePath; + cmd.silent = true; + cmd.sourceCode = function () { File.copy(src, dst); }; + cmds.push(cmd); + } + return cmds; + } + } +} diff --git a/share/qbs/imports/qbs/base/AppleDiskImage.qbs b/share/qbs/imports/qbs/base/AppleDiskImage.qbs new file mode 100644 index 000000000..1467d822b --- /dev/null +++ b/share/qbs/imports/qbs/base/AppleDiskImage.qbs @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** 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://www.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. +** +** In addition, 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. +** +****************************************************************************/ + +Product { + Depends { name: "dmg" } + type: ["dmg.dmg"] +} diff --git a/share/qbs/modules/dmg/DMGModule.qbs b/share/qbs/modules/dmg/DMGModule.qbs new file mode 100644 index 000000000..b45f9d548 --- /dev/null +++ b/share/qbs/modules/dmg/DMGModule.qbs @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** 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://www.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. +** +** In addition, 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. +** +****************************************************************************/ + +import qbs +import qbs.DarwinTools +import qbs.File +import qbs.FileInfo +import qbs.ModUtils +import qbs.Process +import qbs.TextFile +import "dmg.js" as Dmg + +Module { + Depends { name: "xcode"; required: false } + + condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin") + + property string volumeName: product.targetName + PropertyOptions { + name: "volumeName" + description: "the name of the disk image (displayed in Finder when mounted)" + } + + property bool badgeVolumeIcon: false + PropertyOptions { + name: "badgeVolumeIcon" + description: "whether to render the user-supplied icon on top of the " + + "default volume icon instead of using it directly" + } + + property string format: "UDBZ" + PropertyOptions { + name: "format" + description: "the format to create the disk image in" + } + + property int compressionLevel: qbs.buildVariant === "release" ? 9 : undefined + PropertyOptions { + name: "compressionLevel" + description: "sets the zlib or bzip2 compression level for UDZO and UDBZ disk images" + } + + property string textutilPath: "/usr/bin/textutil" + property string hdiutilPath: "/usr/bin/hdiutil" + property string dmgSuffix: ".dmg" + + property string sourceBase + + readonly property string pythonPath: File.canonicalFilePath(FileInfo.joinPaths(path, + "..", "..", + "python")) + readonly property string libexecPath: File.canonicalFilePath(FileInfo.joinPaths(path, + "..", "..", "..", "..", + "libexec", "qbs")) + + property string backgroundColor + property int iconSize: 128 + property int windowX: 100 + property int windowY: 100 + property int windowWidth: 640 + property int windowHeight: 480 + property var iconPositions + + property int iconX: windowWidth / 2 + property int iconY: windowHeight / 2 + + property string defaultLicenseLocale + property string licenseLocale + property string licenseLanguageName + property string licenseAgreeButtonText + property string licenseDisagreeButtonText + property string licensePrintButtonText + property string licenseSaveButtonText + property string licenseInstructionText + + FileTagger { + patterns: [ + "*.txt", "*.rtf", "*.html", "*.doc", "*.docx", "*.odt", "*.xml", "*.webarchive", + "LICENSE" + ] + fileTags: ["dmg.license.input"] + } + + FileTagger { + patterns: ["*.icns"] + fileTags: ["icns"] + } + + FileTagger { + patterns: ["*.tif", "*.tiff"] + fileTags: ["tiff"] + } + + Rule { + inputs: ["dmg.license.input"] + + outputFileTags: ["dmg.license"] + outputArtifacts: ([{ + filePath: FileInfo.joinPaths(product.destinationDirectory, "licenses", + FileInfo.relativePath(product.sourceDirectory, + input.filePath) + ".rtf"), + fileTags: ["dmg.license"], + dmg: { + licenseLocale: input.dmg.licenseLocale, + licenseLanguageName: input.dmg.licenseLanguageName, + licenseAgreeButtonText: input.dmg.licenseAgreeButtonText, + licenseDisagreeButtonText: input.dmg.licenseDisagreeButtonText, + licensePrintButtonText: input.dmg.licensePrintButtonText, + licenseSaveButtonText: input.dmg.licenseSaveButtonText, + licenseInstructionText: input.dmg.licenseInstructionText + } + }]) + + prepare: Dmg.prepareLicense.apply(Dmg, arguments) + } + + Rule { + multiplex: true + inputs: ["qbs", "dmg.input", "dmg.license", "icns", "tiff"] + + Artifact { + fileTags: ["dmg.dmg"] + filePath: FileInfo.joinPaths(product.destinationDirectory, + product.targetName + product.dmg.dmgSuffix) + } + + prepare: Dmg.prepareDmg.apply(Dmg, arguments) + } +} diff --git a/share/qbs/modules/dmg/dmg.js b/share/qbs/modules/dmg/dmg.js new file mode 100644 index 000000000..82b701434 --- /dev/null +++ b/share/qbs/modules/dmg/dmg.js @@ -0,0 +1,212 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** 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://www.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. +** +** In addition, 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. +** +****************************************************************************/ + +var DarwinTools = require("qbs.DarwinTools"); +var FileInfo = require("qbs.FileInfo"); +var TextFile = require("qbs.TextFile"); +var Utilities = require("qbs.Utilities"); + +function localizationFromArtifact(input) { + var locale = input.dmg.licenseLocale || DarwinTools.localizationKey(input.filePath); + if (!locale) + throw("Could not determine localization for license file: " + input.filePath); + return locale; +} + +function dmgbuildSettings(product, inputs) { + var backgroundImages = inputs["tiff"]; + var backgroundImage; + if (backgroundImages) { + if (backgroundImages.length > 1) + throw new Error("only one background image may be specified"); + backgroundImage = backgroundImages[0].filePath; + } + + var volumeIcons = inputs["icns"]; + var volumeIcon; + if (volumeIcons) { + if (volumeIcons.length > 1) + throw new Error("only one volume icon may be specified"); + volumeIcon = volumeIcons[0].filePath; + } + + var licenseFileObjects = Array.prototype.map.call(inputs["dmg.license"], function (a) { + return { + "dmg": { + "licenseLocale": localizationFromArtifact(a), + "licenseLanguageName": a.dmg.licenseLanguageName, + "licenseAgreeButtonText": a.dmg.licenseAgreeButtonText, + "licenseDisagreeButtonText": a.dmg.licenseDisagreeButtonText, + "licensePrintButtonText": a.dmg.licensePrintButtonText, + "licenseSaveButtonText": a.dmg.licenseSaveButtonText, + "licenseInstructionText": a.dmg.licenseInstructionText, + }, + "filePath": a.filePath + }; + }); + + function reduceLicensesForKey(licenseFileObjects, key) { + return licenseFileObjects.reduce(function (accumulator, currentValue) { + var locale = currentValue.dmg.licenseLocale; + if (accumulator[locale]) + throw new Error("Multiple license files for localization '" + locale + "'"); + switch (key) { + case "licenses": + accumulator[locale] = currentValue.filePath; + break; + case "buttons": + var texts = [ + currentValue.dmg.licenseLanguageName, + currentValue.dmg.licenseAgreeButtonText, + currentValue.dmg.licenseDisagreeButtonText, + currentValue.dmg.licensePrintButtonText, + currentValue.dmg.licenseSaveButtonText, + currentValue.dmg.licenseInstructionText + ]; + accumulator[locale] = texts.every(function (a) { return !!a; }) ? texts : undefined; + break; + } + return accumulator; + }, {}); + } + + var contentsArray = Array.prototype.map.call(inputs["dmg.input"], function (a) { + if (a.dmg.sourceBase && !a.filePath.startsWith(a.dmg.sourceBase)) { + throw new Error("Cannot install '" + a.filePath + "', " + + "because it doesn't start with the value of " + + "dmg.sourceBase '" + a.dmg.sourceBase + "'."); + } + + var isSymlink = a.fileTags.contains("dmg.input.symlink"); + return { + "x": a.dmg.iconX, + "y": a.dmg.iconY, + "type": isSymlink ? "link" : "file", + "path": isSymlink ? a.dmg.symlinkTarget : a.filePath, + "name": FileInfo.relativePath(a.dmg.sourceBase || FileInfo.path(a.filePath), a.filePath) + }; + }); + + Array.prototype.forEach.call(product.dmg.iconPositions, function (obj) { + var existingIndex = -1; + Array.prototype.forEach.call(contentsArray, function (contentsItem, i) { + if (contentsItem["name"] === obj["path"]) + existingIndex = i; + }); + + if (existingIndex >= 0) { + contentsArray[existingIndex]["x"] = obj["x"]; + contentsArray[existingIndex]["y"] = obj["y"]; + } else { + contentsArray.push({ + "type": "position", + "name": obj["path"], // name => path is not a typo + "path": obj["path"], + "x": obj["x"], + "y": obj["y"] + }); + } + }); + + return { + "title": product.dmg.volumeName, + "icon": !product.dmg.badgeVolumeIcon ? volumeIcon : undefined, + "badge-icon": product.dmg.badgeVolumeIcon ? volumeIcon : undefined, + "background": backgroundImage, + "background-color": product.dmg.backgroundColor, + "icon-size": product.dmg.iconSize, + "window": { + "position": { + "x": product.dmg.windowX, + "y": product.dmg.windowY + }, + "size": { + "width": product.dmg.windowWidth, + "height": product.dmg.windowHeight + } + }, + "format": product.dmg.format, + "compression-level": product.dmg.compressionLevel, + "license": { + "default-language": product.dmg.defaultLicenseLocale, + "licenses": reduceLicensesForKey(licenseFileObjects, "licenses"), + "buttons": reduceLicensesForKey(licenseFileObjects, "buttons") + }, + "contents": contentsArray + }; +} + +function prepareLicense(project, product, inputs, outputs, input, output) { + var cmd = new Command(product.dmg.textutilPath, [ + "-convert", "rtf", + "-strip", + "-font", "Arial", + "-output", output.filePath, + "--", input.filePath + ]); + cmd.description = "converting " + input.fileName; + return [cmd]; +} + +function prepareDmg(project, product, inputs, outputs, input, output) { + var i; + var cmd; + var cmds = []; + + var settingsJsonFilePath = FileInfo.joinPaths(product.destinationDirectory, + "settings.json"); + cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.settingsJSON = dmgbuildSettings(product, inputs); + cmd.settingsJsonFilePath = settingsJsonFilePath; + cmd.sourceCode = function () { + var tf; + try { + tf = new TextFile(settingsJsonFilePath, TextFile.WriteOnly); + tf.writeLine(JSON.stringify(settingsJSON, undefined, 4)); + } finally { + if (tf) + tf.close(); + } + } + cmds.push(cmd); + + // Create the actual DMG via dmgbuild + cmd = new Command(FileInfo.joinPaths(product.dmg.libexecPath, "dmgbuild"), + [product.dmg.volumeName, + output.filePath, + "--no-hidpi", // qbs handles this by itself + "--settings", settingsJsonFilePath]); + cmd.environment = ["PYTHONPATH=" + product.dmg.pythonPath]; + cmd.description = "creating " + output.fileName; + cmds.push(cmd); + + return cmds; +} diff --git a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py index 58a76a6e1..41b9acf35 100644 --- a/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py +++ b/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py @@ -144,7 +144,7 @@ kBookmarkFileCreationDate = 0x1040 # = 0x1055 # ? # = 0x1056 # ? # = 0x1101 # ? -# = 0x1102 # ? +# = 0x1102 # ? kBookmarkTOCPath = 0x2000 # A list of (TOC id, ?) pairs kBookmarkVolumePath = 0x2002 kBookmarkVolumeURL = 0x2005 @@ -299,6 +299,9 @@ class Bookmark (object): def from_bytes(cls, data): """Create a :class:`Bookmark` given byte data.""" + if isinstance(data, bytearray): + data = bytes(data) + if len(data) < 16: raise ValueError('Not a bookmark file (too short)') @@ -493,7 +496,7 @@ class Bookmark (object): # binary search to find data entries.sort() - tocs.append((tid, b''.join([struct.pack('<III',k,o,0) + tocs.append((tid, b''.join([struct.pack(b'<III',k,o,0) for k,o in entries]))) first_toc_offset = offset diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs b/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs new file mode 100644 index 000000000..3bccebfd0 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs @@ -0,0 +1,88 @@ +import qbs + +Project { + AppleApplicationDiskImage { + Depends { name: "myapp" } + Depends { name: "ib" } + dmg.volumeName: "My Great App" + dmg.iconSize: 128 + dmg.windowWidth: 640 + dmg.windowHeight: 280 + files: [ + "white.iconset", + ] + } + + CppApplication { + name: "myapp" + targetName: "My Great App" + files: ["main.c"] + + Group { + fileTagsFilter: ["bundle.content"] + qbs.install: true + qbs.installDir: "/Applications" + qbs.installSourceBase: product.buildDirectory + } + } + + AppleDiskImage { + name: "hellodmg" + targetName: "hellodmg-1.0" + + (qbs.architecture ? "-" + qbs.architecture : "") + + dmg.volumeName: "Hello DMG" + + files: [ + "hello.icns", + "hello.tif" + ] + + Group { + files: ["en_US.lproj/eula.txt"] + fileTags: ["dmg.input", "dmg.license.input"] + dmg.iconX: 320 + dmg.iconY: 240 + dmg.licenseLocale: "en_US" + } + + Group { + files: ["*.lproj/**"] + excludeFiles: ["en_US.lproj/eula.txt"] + } + } + + AppleDiskImage { + name: "green" + dmg.backgroundColor: "green" + } + + AppleDiskImage { + name: "german" + dmg.defaultLicenseLocale: "de_DE" + + Group { + files: ["*.lproj/**"] + } + } + + AppleDiskImage { + name: "custom-buttons" + + Group { + files: ["ru_RU.lproj/eula.txt"] + dmg.licenseLocale: "sv_SE" // override auto-detected ru_RU with sv_SE + dmg.licenseLanguageName: "Swedish, not Russian" + dmg.licenseAgreeButtonText: "Of course" + dmg.licenseDisagreeButtonText: "Never!" + dmg.licensePrintButtonText: "Make Paper" + dmg.licenseSaveButtonText: "Make Bits" + dmg.licenseInstructionText: "Do please agree to the license!" + } + + Group { + files: ["*.lproj/**"] + excludeFiles: ["ru_RU.lproj/eula.txt"] + } + } +} diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt new file mode 100644 index 000000000..7ca2bf84b --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt @@ -0,0 +1,6 @@ +FIKTIVE UNTERNEHMEN +SOFTWARE BEISPIEL VEREINBARUNG + +Sie stimmen zu, dass Sie nicht mit dieser App auf Atomwaffen zu machen. + +Sie bestätigen, dass Qbs das Beste ist. diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt new file mode 100644 index 000000000..e2b7adbed --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt @@ -0,0 +1,6 @@ +FICTIONAL CORPORATION +SOFTWARE EXAMPLE AGREEMENT + +You agree that you will not use this app to make nuclear weapons. + +You agree that Qbs is the best. diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt new file mode 100644 index 000000000..e2b7adbed --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt @@ -0,0 +1,6 @@ +FICTIONAL CORPORATION +SOFTWARE EXAMPLE AGREEMENT + +You agree that you will not use this app to make nuclear weapons. + +You agree that Qbs is the best. diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt new file mode 100644 index 000000000..48a9af57c --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt @@ -0,0 +1,6 @@ +SOCIÉTÉ FICTIONNEL +EXEMPLE D'ACCORD DU LOGICIEL + +Vous vous engagez à ne pas utiliser cette application pour fabriquer des armes nucléaires. + +Vous acceptez que Qbs est le meilleur. diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns Binary files differnew file mode 100644 index 000000000..b8ff0c53b --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif Binary files differnew file mode 100644 index 000000000..b58b4548d --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt new file mode 100644 index 000000000..e44c34bb3 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt @@ -0,0 +1,6 @@ +架空CORPORATION +ソフトウェア例契約 + +あなたは核兵器を作るために、このアプリを使用しないことに同意します。 + +あなたは、QBSがベストであることに同意するものとします。 diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf b/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf new file mode 100644 index 000000000..5b7c49d56 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf @@ -0,0 +1,49 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1265 +{\fonttbl\f0\fnil\fcharset129 AppleSDGothicNeo-Regular;\f1\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww10800\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural + +\f0\b\fs24 \cf0 \'c7\'e3\'b1\'b8 +\f1 CORPORATION\ + +\f0 \'bc\'d2\'c7\'c1\'c6\'ae\'bf\'fe\'be\'ee +\f1 +\f0 \'bf\'b9 +\f1 +\f0 \'b0\'e8\'be\'e0 +\f1\b0 \ +\ + +\f0 \'b4\'e7\'bd\'c5\'c0\'ba +\f1 +\f0 \'b4\'e7\'bd\'c5\'c0\'cc +\f1 +\f0 \'c7\'d9\'b9\'ab\'b1\'e2\'b8\'a6 +\f1 +\f0 \'b8\'b8\'b5\'e9\'b1\'e2 +\f1 +\f0 \'c0\'a7\'c7\'d8\'c0\'cc +\f1 +\f0 \'c0\'c0\'bf\'eb +\f1 +\f0 \'c7\'c1\'b7\'ce\'b1\'d7\'b7\'a5\'c0\'bb +\f1 +\f0 \'bb\'e7\'bf\'eb\'c7\'cf\'c1\'f6 +\f1 +\f0 \'be\'ca\'c0\'bb +\f1 +\f0 \'b0\'cd\'bf\'a1 +\f1 +\f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9 +\f1 .\ +\ + +\f0 \'b4\'e7\'bd\'c5\'c0\'ba +\f1 QBS +\f0 \'b0\'a1 +\f1 +\f0 \'c3\'d6\'b0\'ed\'b6\'f3\'b0\'ed +\f1 +\f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9 +\f1 .}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/main.c b/tests/auto/blackbox/testdata-apple/apple-dmg/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt b/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt new file mode 100644 index 000000000..e2b7adbed --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt @@ -0,0 +1,6 @@ +FICTIONAL CORPORATION +SOFTWARE EXAMPLE AGREEMENT + +You agree that you will not use this app to make nuclear weapons. + +You agree that Qbs is the best. diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png Binary files differnew file mode 100644 index 000000000..60365798f --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png Binary files differnew file mode 100644 index 000000000..20369000d --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt Binary files differnew file mode 100644 index 000000000..21345e536 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx Binary files differnew file mode 100644 index 000000000..9e48895ac --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp index f5bad1cbd..9d3364914 100644 --- a/tests/auto/blackbox/tst_blackboxapple.cpp +++ b/tests/auto/blackbox/tst_blackboxapple.cpp @@ -595,6 +595,12 @@ void TestBlackboxApple::deploymentTarget_data() } } +void TestBlackboxApple::dmg() +{ + QDir::setCurrent(testDataDir + "/apple-dmg"); + QCOMPARE(runQbs(), 0); +} + void TestBlackboxApple::embedInfoPlist() { QDir::setCurrent(testDataDir + QLatin1String("/embedInfoPlist")); diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h index ea56d915f..b9bb64104 100644 --- a/tests/auto/blackbox/tst_blackboxapple.h +++ b/tests/auto/blackbox/tst_blackboxapple.h @@ -57,6 +57,7 @@ private slots: void bundleStructure_data(); void deploymentTarget(); void deploymentTarget_data(); + void dmg(); void embedInfoPlist(); void frameworkStructure(); void iconset(); |