Merge pull request #645 from tdewey-rpi/dev/shared/device-filtering

Device-first OS list filtering
This commit is contained in:
Tom Dewey 2023-10-16 13:56:39 +01:00 committed by GitHub
commit e8d7de934f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 6317 additions and 6559 deletions

View file

@ -197,8 +197,8 @@ On macOS, disable it by editing the property list for the application:
defaults write org.raspberrypi.Imager.plist telemetry -bool NO defaults write org.raspberrypi.Imager.plist telemetry -bool NO
``` ```
### Advanced options ### OS Customization
When using the app, press <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>X</kbd> to reveal the **Advanced options** dialog. When using the app, press <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>X</kbd> to reveal the **OS Customization** dialog.
In here, you can specify several things you would otherwise set in the boot configuration files. For example, you can enable SSH, set the Wi-Fi login, and specify your locale settings for the system image. In here, you can specify several things you would otherwise set in the boot configuration files. For example, you can enable SSH, set the Wi-Fi login, and specify your locale settings for the system image.

View file

@ -194,7 +194,8 @@
"extract_sha256": "ceb7d7489847ed811e7746fa779837f78fc06d43663148a696280e6a1cfe00e3", "extract_sha256": "ceb7d7489847ed811e7746fa779837f78fc06d43663148a696280e6a1cfe00e3",
"image_download_size": 1306588543, "image_download_size": 1306588543,
"release_date": "2022-01-28", "release_date": "2022-01-28",
"init_format": "systemd" "init_format": "systemd",
"devices": ["pi1a"]
} }
], ],
"required": [ "required": [
@ -205,7 +206,8 @@
"extract_size", "extract_size",
"extract_sha256", "extract_sha256",
"image_download_size", "image_download_size",
"release_date" "release_date",
"devices"
], ],
"properties": { "properties": {
"name": { "name": {
@ -298,6 +300,31 @@
"systemd" "systemd"
] ]
}, },
"devices": {
"$id": "#/properties/os_list/items/anyOf/0/properties/devices",
"type": "array",
"title": "The devices schema",
"description": "Provides a JSON-format list of strings representing Raspberry Pi devices that are supported with this image",
"default": "",
"examples": [
"[\"pi1a\", \"pi1b\"]",
"[\"pi4\", \"pi5\"]",
"[\"cm3\", \"cm4\"]"
]
},
"matching_type": {
"$id": "#/properties/os_list/items/anyOf/0/properties/matching_type",
"type": "array",
"title": "The matching_type schema",
"description": "Allows specification of the matching algorithm to use for device tags. If you set this to 'exclusive', any image that does not explicitly tag your target device will not be displayed. Set to 'prefix' to allow for family matching (eg, match all Pi1 devices), but no untagged images. Set to 'inclusive', and get your exact device name and all untagged images. Finally, if you set to 'inclusive_prefix', you can match all images tagged with your family prefix (eg, Pi1), and any untagged image.",
"default": "exclusive",
"examples": [
"exclusive",
"exclusive_prefix",
"inclusive",
"inclusive_prefix"
]
},
"website": { "website": {
"$id": "#/properties/os_list/items/anyOf/1/properties/website", "$id": "#/properties/os_list/items/anyOf/1/properties/website",
"type": "string", "type": "string",

View file

@ -17,7 +17,7 @@ Window {
maximumWidth: width maximumWidth: width
minimumHeight: 125 minimumHeight: 125
height: Math.min(750, cl.implicitHeight) height: Math.min(750, cl.implicitHeight)
title: qsTr("Advanced options") title: qsTr("OS Customization")
property bool initialized: false property bool initialized: false
property bool hasSavedSettings: false property bool hasSavedSettings: false
@ -49,7 +49,7 @@ Window {
RowLayout { RowLayout {
Label { Label {
text: qsTr("Image customization options") text: qsTr("OS customization options")
} }
ComboBox { ComboBox {
id: comboSaveSettings id: comboSaveSettings
@ -539,7 +539,7 @@ Window {
/* Lacking an easy cross-platform to fetch keyboard layout /* Lacking an easy cross-platform to fetch keyboard layout
from host system, just default to "gb" for people in from host system, just default to "gb" for people in
UK time zone for now, and "us" for everyone else */ UK time zone for now, and "us" for everyone else */
if (tz == "Europe/London") { if (tz === "Europe/London") {
fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("gb") fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("gb")
} else { } else {
fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("us") fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("us")

View file

@ -70,7 +70,7 @@ Popup {
Layout.topMargin: 10 Layout.topMargin: 10
font.family: roboto.name font.family: roboto.name
font.bold: true font.bold: true
text: qsTr("Warning: advanced settings set") text: qsTr("Use OS customization?")
} }
Text { Text {
@ -83,8 +83,9 @@ Popup {
Layout.fillHeight: true Layout.fillHeight: true
Layout.leftMargin: 25 Layout.leftMargin: 25
Layout.topMargin: 25 Layout.topMargin: 25
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Accessible.name: text.replace(/<\/?[^>]+(>|$)/g, "") Accessible.name: text.replace(/<\/?[^>]+(>|$)/g, "")
text: qsTr("Would you like to apply the image customization settings saved earlier?") text: qsTr("Would you like to apply OS customization settings?")
} }
RowLayout { RowLayout {
@ -94,10 +95,10 @@ Popup {
id: buttons id: buttons
ImButton { ImButton {
text: qsTr("NO") text: qsTr("EDIT SETTINGS")
onClicked: { onClicked: {
msgpopup.close() msgpopup.close()
msgpopup.no() msgpopup.editSettings()
} }
Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff"
Material.background: "#c51a4a" Material.background: "#c51a4a"
@ -111,6 +112,7 @@ Popup {
} }
Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff"
Material.background: "#c51a4a" Material.background: "#c51a4a"
enabled: imageWriter.hasSavedCustomizationSettings() ? true : false
} }
ImButton { ImButton {
@ -121,13 +123,14 @@ Popup {
} }
Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff"
Material.background: "#c51a4a" Material.background: "#c51a4a"
enabled: imageWriter.hasSavedCustomizationSettings() ? true : false
} }
ImButton { ImButton {
text: qsTr("EDIT SETTINGS") text: qsTr("NO")
onClicked: { onClicked: {
msgpopup.close() msgpopup.close()
msgpopup.editSettings() msgpopup.no()
} }
Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff"
Material.background: "#c51a4a" Material.background: "#c51a4a"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,16 @@
</context> </context>
<context> <context>
<name>DownloadThread</name> <name>DownloadThread</name>
<message>
<location filename="../downloadthread.cpp" line="118"/>
<source>unmounting drive</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../downloadthread.cpp" line="138"/>
<source>opening drive</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../downloadthread.cpp" line="166"/> <location filename="../downloadthread.cpp" line="166"/>
<source>Error running diskpart: %1</source> <source>Error running diskpart: %1</source>
@ -73,13 +83,18 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="826"/> <location filename="../downloadthread.cpp" line="319"/>
<source>Error reading from storage.&lt;br&gt;SD card may be broken.</source> <source>Write error while trying to zero out last part of card.&lt;br&gt;Card could be advertising wrong capacity (possible counterfeit).</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="898"/> <location filename="../downloadthread.cpp" line="408"/>
<source>Customizing image</source> <source>starting download</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../downloadthread.cpp" line="466"/>
<source>Error downloading: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -98,8 +113,8 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="466"/> <location filename="../downloadthread.cpp" line="697"/>
<source>Error downloading: %1</source> <source>Download corrupt. Hash does not match</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -114,41 +129,26 @@
<source>Error writing to storage (while fsync)</source> <source>Error writing to storage (while fsync)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../downloadthread.cpp" line="697"/>
<source>Download corrupt. Hash does not match</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../downloadthread.cpp" line="118"/>
<source>unmounting drive</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../downloadthread.cpp" line="138"/>
<source>opening drive</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../downloadthread.cpp" line="319"/>
<source>Write error while trying to zero out last part of card.&lt;br&gt;Card could be advertising wrong capacity (possible counterfeit).</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../downloadthread.cpp" line="408"/>
<source>starting download</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../downloadthread.cpp" line="751"/> <location filename="../downloadthread.cpp" line="751"/>
<source>Error writing first block (partition table)</source> <source>Error writing first block (partition table)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../downloadthread.cpp" line="826"/>
<source>Error reading from storage.&lt;br&gt;SD card may be broken.</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../downloadthread.cpp" line="845"/> <location filename="../downloadthread.cpp" line="845"/>
<source>Verifying write failed. Contents of SD card is different from what was written to it.</source> <source>Verifying write failed. Contents of SD card is different from what was written to it.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../downloadthread.cpp" line="898"/>
<source>Customizing image</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>DriveFormatThread</name> <name>DriveFormatThread</name>
@ -213,27 +213,27 @@
<context> <context>
<name>ImageWriter</name> <name>ImageWriter</name>
<message> <message>
<location filename="../imagewriter.cpp" line="248"/> <location filename="../imagewriter.cpp" line="252"/>
<source>Storage capacity is not large enough.&lt;br&gt;Needs to be at least %1 GB.</source> <source>Storage capacity is not large enough.&lt;br&gt;Needs to be at least %1 GB.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="254"/> <location filename="../imagewriter.cpp" line="258"/>
<source>Input file is not a valid disk image.&lt;br&gt;File size %1 bytes is not a multiple of 512 bytes.</source> <source>Input file is not a valid disk image.&lt;br&gt;File size %1 bytes is not a multiple of 512 bytes.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="442"/> <location filename="../imagewriter.cpp" line="446"/>
<source>Downloading and writing image</source> <source>Downloading and writing image</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="575"/> <location filename="../imagewriter.cpp" line="579"/>
<source>Select image</source> <source>Select image</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="896"/> <location filename="../imagewriter.cpp" line="971"/>
<source>Would you like to prefill the wifi password from the system keychain?</source> <source>Would you like to prefill the wifi password from the system keychain?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -316,6 +316,62 @@
<source>Set hostname:</source> <source>Set hostname:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../OptionsPopup.qml" line="120"/>
<source>Set username and password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="142"/>
<source>Username:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="158"/>
<location filename="../OptionsPopup.qml" line="219"/>
<source>Password:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="186"/>
<source>Configure wireless LAN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="205"/>
<source>SSID:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="238"/>
<source>Show password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="244"/>
<source>Hidden SSID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="250"/>
<source>Wireless LAN country:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="261"/>
<source>Set locale settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="271"/>
<source>Time zone:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="281"/>
<source>Keyboard layout:</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../OptionsPopup.qml" line="298"/> <location filename="../OptionsPopup.qml" line="298"/>
<source>Enable SSH</source> <source>Enable SSH</source>
@ -341,62 +397,6 @@
<source>RUN SSH-KEYGEN</source> <source>RUN SSH-KEYGEN</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../OptionsPopup.qml" line="186"/>
<source>Configure wireless LAN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="205"/>
<source>SSID:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="158"/>
<location filename="../OptionsPopup.qml" line="219"/>
<source>Password:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="120"/>
<source>Set username and password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="142"/>
<source>Username:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="244"/>
<source>Hidden SSID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="238"/>
<source>Show password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="250"/>
<source>Wireless LAN country:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="261"/>
<source>Set locale settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="271"/>
<source>Time zone:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../OptionsPopup.qml" line="281"/>
<source>Keyboard layout:</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../OptionsPopup.qml" line="375"/> <location filename="../OptionsPopup.qml" line="375"/>
<source>Play sound when finished</source> <source>Play sound when finished</source>
@ -430,32 +430,32 @@
<name>UseSavedSettingsPopup</name> <name>UseSavedSettingsPopup</name>
<message> <message>
<location filename="../UseSavedSettingsPopup.qml" line="73"/> <location filename="../UseSavedSettingsPopup.qml" line="73"/>
<source>Warning: advanced settings set</source> <source>Use image customisation?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../UseSavedSettingsPopup.qml" line="87"/> <location filename="../UseSavedSettingsPopup.qml" line="88"/>
<source>Would you like to apply the image customization settings saved earlier?</source> <source>Would you like to apply image customization settings?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../UseSavedSettingsPopup.qml" line="97"/> <location filename="../UseSavedSettingsPopup.qml" line="98"/>
<source>NO</source> <source>EDIT SETTINGS</source>
<translation></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../UseSavedSettingsPopup.qml" line="107"/> <location filename="../UseSavedSettingsPopup.qml" line="108"/>
<source>NO, CLEAR SETTINGS</source> <source>NO, CLEAR SETTINGS</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../UseSavedSettingsPopup.qml" line="117"/> <location filename="../UseSavedSettingsPopup.qml" line="119"/>
<source>YES</source> <source>YES</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../UseSavedSettingsPopup.qml" line="127"/> <location filename="../UseSavedSettingsPopup.qml" line="130"/>
<source>EDIT SETTINGS</source> <source>NO</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@ -467,256 +467,262 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="97"/> <location filename="../main.qml" line="114"/>
<location filename="../main.qml" line="413"/> <location filename="../main.qml" line="467"/>
<source>Raspberry Pi Device</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="126"/>
<source>CHOOSE DEVICE</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="138"/>
<source>Select this button to choose your target Raspberry Pi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="152"/>
<location filename="../main.qml" line="576"/>
<source>Operating System</source> <source>Operating System</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="109"/> <location filename="../main.qml" line="163"/>
<source>CHOOSE OS</source> <source>CHOOSE OS</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="121"/> <location filename="../main.qml" line="175"/>
<source>Select this button to change the operating system</source> <source>Select this button to change the operating system</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="133"/> <location filename="../main.qml" line="189"/>
<location filename="../main.qml" line="780"/> <location filename="../main.qml" line="957"/>
<source>Storage</source> <source>Storage</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="145"/> <location filename="../main.qml" line="200"/>
<location filename="../main.qml" line="1108"/> <location filename="../main.qml" line="1286"/>
<source>CHOOSE STORAGE</source> <source>CHOOSE STORAGE</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="171"/> <location filename="../main.qml" line="214"/>
<source>WRITE</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="175"/>
<source>Select this button to start writing the image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="216"/>
<source>CANCEL WRITE</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="219"/>
<location filename="../main.qml" line="1035"/>
<source>Cancelling...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="227"/>
<source>CANCEL VERIFY</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="230"/>
<location filename="../main.qml" line="1058"/>
<location filename="../main.qml" line="1127"/>
<source>Finalizing...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="245"/>
<source>Select this button to access advanced settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="259"/>
<source>Using custom repository: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="268"/>
<source>Keyboard navigation: &lt;tab&gt; navigate to next button &lt;space&gt; press button/select item &lt;arrow up/down&gt; go up/down in lists</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="289"/>
<source>Language: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="312"/>
<source>Keyboard: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="437"/>
<source>Pi model:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="448"/>
<source>[ All ]</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="572"/>
<location filename="../main.qml" line="1092"/>
<source>Erase</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="573"/>
<source>Format card as FAT32</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="582"/>
<source>Use custom</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="583"/>
<source>Select a custom .img from your computer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="528"/>
<source>Back</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="155"/>
<source>Select this button to change the destination storage device</source> <source>Select this button to change the destination storage device</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="529"/> <location filename="../main.qml" line="261"/>
<source>CANCEL WRITE</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="264"/>
<location filename="../main.qml" line="1213"/>
<source>Cancelling...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="276"/>
<source>CANCEL VERIFY</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="279"/>
<location filename="../main.qml" line="1236"/>
<location filename="../main.qml" line="1305"/>
<source>Finalizing...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="288"/>
<source>Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="294"/>
<source>Select this button to start writing the image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="316"/>
<source>Using custom repository: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="325"/>
<source>Keyboard navigation: &lt;tab&gt; navigate to next button &lt;space&gt; press button/select item &lt;arrow up/down&gt; go up/down in lists</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="346"/>
<source>Language: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="369"/>
<source>Keyboard: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="490"/>
<source>[ All ]</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="638"/>
<source>Back</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="639"/>
<source>Go back to main menu</source> <source>Go back to main menu</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="695"/> <location filename="../main.qml" line="872"/>
<source>Released: %1</source> <source>Released: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="705"/> <location filename="../main.qml" line="882"/>
<source>Cached on your computer</source> <source>Cached on your computer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="707"/> <location filename="../main.qml" line="884"/>
<source>Local file</source> <source>Local file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="708"/> <location filename="../main.qml" line="885"/>
<source>Online - %1 GB download</source> <source>Online - %1 GB download</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="833"/> <location filename="../main.qml" line="1010"/>
<location filename="../main.qml" line="885"/> <location filename="../main.qml" line="1062"/>
<location filename="../main.qml" line="891"/> <location filename="../main.qml" line="1068"/>
<source>Mounted as %1</source> <source>Mounted as %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="887"/> <location filename="../main.qml" line="1064"/>
<source>[WRITE PROTECTED]</source> <source>[WRITE PROTECTED]</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="929"/> <location filename="../main.qml" line="1106"/>
<source>Are you sure you want to quit?</source> <source>Are you sure you want to quit?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="930"/> <location filename="../main.qml" line="1107"/>
<source>Raspberry Pi Imager is still busy.&lt;br&gt;Are you sure you want to quit?</source> <source>Raspberry Pi Imager is still busy.&lt;br&gt;Are you sure you want to quit?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="941"/> <location filename="../main.qml" line="1118"/>
<source>Warning</source> <source>Warning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="949"/> <location filename="../main.qml" line="1126"/>
<source>Preparing to write...</source> <source>Preparing to write...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="973"/> <location filename="../main.qml" line="1140"/>
<source>Update available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="974"/>
<source>There is a newer version of Imager available.&lt;br&gt;Would you like to visit the website to download it?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1038"/>
<source>Writing... %1%</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="962"/>
<source>All existing data on &apos;%1&apos; will be erased.&lt;br&gt;Are you sure you want to continue?</source> <source>All existing data on &apos;%1&apos; will be erased.&lt;br&gt;Are you sure you want to continue?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1017"/> <location filename="../main.qml" line="1151"/>
<source>Update available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1152"/>
<source>There is a newer version of Imager available.&lt;br&gt;Would you like to visit the website to download it?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1195"/>
<source>Error downloading OS list from Internet</source> <source>Error downloading OS list from Internet</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1061"/> <location filename="../main.qml" line="1216"/>
<source>Writing... %1%</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1239"/>
<source>Verifying... %1%</source> <source>Verifying... %1%</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1068"/> <location filename="../main.qml" line="1246"/>
<source>Preparing to write... (%1)</source> <source>Preparing to write... (%1)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1084"/> <location filename="../main.qml" line="1262"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1091"/> <location filename="../main.qml" line="1269"/>
<source>Write Successful</source> <source>Write Successful</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1093"/> <location filename="../main.qml" line="1270"/>
<location filename="../main.qml" line="1523"/>
<source>Erase</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1271"/>
<source>&lt;b&gt;%1&lt;/b&gt; has been erased&lt;br&gt;&lt;br&gt;You can now remove the SD card from the reader</source> <source>&lt;b&gt;%1&lt;/b&gt; has been erased&lt;br&gt;&lt;br&gt;You can now remove the SD card from the reader</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1100"/> <location filename="../main.qml" line="1278"/>
<source>&lt;b&gt;%1&lt;/b&gt; has been written to &lt;b&gt;%2&lt;/b&gt;&lt;br&gt;&lt;br&gt;You can now remove the SD card from the reader</source> <source>&lt;b&gt;%1&lt;/b&gt; has been written to &lt;b&gt;%2&lt;/b&gt;&lt;br&gt;&lt;br&gt;You can now remove the SD card from the reader</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1202"/> <location filename="../main.qml" line="1423"/>
<source>Error parsing os_list.json</source> <source>Error parsing os_list.json</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1391"/> <location filename="../main.qml" line="1524"/>
<source>Format card as FAT32</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1533"/>
<source>Use custom</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1534"/>
<source>Select a custom .img from your computer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="1681"/>
<source>Connect an USB stick containing images first.&lt;br&gt;The images must be located in the root folder of the USB stick.</source> <source>Connect an USB stick containing images first.&lt;br&gt;The images must be located in the root folder of the USB stick.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="1407"/> <location filename="../main.qml" line="1697"/>
<source>SD card is write protected.&lt;br&gt;Push the lock switch on the left side of the card upwards, and try again.</source> <source>SD card is write protected.&lt;br&gt;Push the lock switch on the left side of the card upwards, and try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -25,6 +25,20 @@ ApplicationWindow {
FontLoader {id: robotoLight; source: "fonts/Roboto-Light.ttf"} FontLoader {id: robotoLight; source: "fonts/Roboto-Light.ttf"}
FontLoader {id: robotoBold; source: "fonts/Roboto-Bold.ttf"} FontLoader {id: robotoBold; source: "fonts/Roboto-Bold.ttf"}
/** hw device list storage
*
* To allow us to filter the OS list, we maintain an application-wide record of the selected device
* tags.
*/
property string hwTags
/** 0: Exclusive, must match explicit device names only, no untagged
1: Exclusive by prefix, must match the device name as a prefix, no untagged
2: Inclusive, match explicit device names and untagged
3: Inclusive by prefix, match explicit device names and untagged
*/
property int hwTagMatchingType
onClosing: { onClosing: {
if (progressBar.visible) { if (progressBar.visible) {
close.accepted = false close.accepted = false
@ -55,40 +69,81 @@ ApplicationWindow {
spacing: 0 spacing: 0
Rectangle { Rectangle {
implicitHeight: window.height/2 implicitHeight: window.height/3
Image { Image {
id: image id: image
Layout.fillWidth: true //Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
source: "icons/logo_stacked_imager.png" source: "icons/logo_sxs_imager.png"
width: window.width width: window.width
height: window.height/2 height: window.height/3
} }
} }
Rectangle { Rectangle {
color: "#c31c4a" color: "#c31c4a"
implicitWidth: window.width implicitWidth: window.width
implicitHeight: window.height/2 implicitHeight: (window.height/3) * 2
GridLayout { GridLayout {
id: gridLayout id: gridLayout
rowSpacing: 25 rowSpacing: 15
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 25 anchors.topMargin: 25
anchors.rightMargin: 50 anchors.rightMargin: 50
anchors.leftMargin: 50 anchors.leftMargin: 50
rows: 6 rows: 5
columns: 3 columns: 3
columnSpacing: 25 columnSpacing: 15
ColumnLayout { ColumnLayout {
id: columnLayout id: columnLayout0
spacing: 0 spacing: 0
Layout.row: 0
Layout.column: 0
Layout.fillWidth: true
Text {
id: text0
color: "#ffffff"
text: qsTr("Raspberry Pi Device")
Layout.fillWidth: true
Layout.preferredHeight: 17
Layout.preferredWidth: 100
font.pixelSize: 12
font.family: robotoBold.name
font.bold: true
horizontalAlignment: Text.AlignHCenter
}
ImButton {
id: hwbutton
text: qsTr("CHOOSE DEVICE")
spacing: 0
padding: 0
bottomPadding: 0
topPadding: 0
Layout.minimumHeight: 40
Layout.fillWidth: true
onClicked: {
hwpopup.open()
hwlistview.currentItem.forceActiveFocus()
}
Accessible.ignored: ospopup.visible || dstpopup.visible || hwpopup.visible
Accessible.description: qsTr("Select this button to choose your target Raspberry Pi")
}
}
ColumnLayout {
id: columnLayout1
spacing: 0
Layout.row: 0
Layout.column: 1
Layout.fillWidth: true Layout.fillWidth: true
Text { Text {
@ -97,7 +152,6 @@ ApplicationWindow {
text: qsTr("Operating System") text: qsTr("Operating System")
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 17 Layout.preferredHeight: 17
Layout.preferredWidth: 100
font.pixelSize: 12 font.pixelSize: 12
font.family: robotoBold.name font.family: robotoBold.name
font.bold: true font.bold: true
@ -117,7 +171,7 @@ ApplicationWindow {
ospopup.open() ospopup.open()
osswipeview.currentItem.forceActiveFocus() osswipeview.currentItem.forceActiveFocus()
} }
Accessible.ignored: ospopup.visible || dstpopup.visible Accessible.ignored: ospopup.visible || dstpopup.visible || hwpopup.visible
Accessible.description: qsTr("Select this button to change the operating system") Accessible.description: qsTr("Select this button to change the operating system")
} }
} }
@ -125,6 +179,8 @@ ApplicationWindow {
ColumnLayout { ColumnLayout {
id: columnLayout2 id: columnLayout2
spacing: 0 spacing: 0
Layout.row: 0
Layout.column: 2
Layout.fillWidth: true Layout.fillWidth: true
Text { Text {
@ -133,7 +189,6 @@ ApplicationWindow {
text: qsTr("Storage") text: qsTr("Storage")
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 17 Layout.preferredHeight: 17
Layout.preferredWidth: 100
font.pixelSize: 12 font.pixelSize: 12
font.family: robotoBold.name font.family: robotoBold.name
font.bold: true font.bold: true
@ -143,55 +198,29 @@ ApplicationWindow {
ImButton { ImButton {
id: dstbutton id: dstbutton
text: qsTr("CHOOSE STORAGE") text: qsTr("CHOOSE STORAGE")
spacing: 0
padding: 0
bottomPadding: 0
topPadding: 0
Layout.minimumHeight: 40 Layout.minimumHeight: 40
Layout.preferredWidth: 100 Layout.preferredWidth: 200
Layout.fillWidth: true Layout.fillWidth: true
onClicked: { onClicked: {
imageWriter.startDriveListPolling() imageWriter.startDriveListPolling()
dstpopup.open() dstpopup.open()
dstlist.forceActiveFocus() dstlist.forceActiveFocus()
} }
Accessible.ignored: ospopup.visible || dstpopup.visible Accessible.ignored: ospopup.visible || dstpopup.visible || hwpopup.visible
Accessible.description: qsTr("Select this button to change the destination storage device") Accessible.description: qsTr("Select this button to change the destination storage device")
} }
} }
ColumnLayout { ColumnLayout {
id: columnLayoutProgress
spacing: 0 spacing: 0
Layout.fillWidth: true Layout.row: 1
Layout.column: 0
Text { Layout.columnSpan: 2
text: " "
Layout.preferredHeight: 17
Layout.preferredWidth: 100
}
ImButton {
id: writebutton
text: qsTr("WRITE")
Layout.minimumHeight: 40
Layout.fillWidth: true
Accessible.ignored: ospopup.visible || dstpopup.visible
Accessible.description: qsTr("Select this button to start writing the image")
enabled: false
onClicked: {
if (!imageWriter.readyToWrite()) {
return
}
if (!optionspopup.initialized && imageWriter.imageSupportsCustomization() && imageWriter.hasSavedCustomizationSettings()) {
usesavedsettingspopup.openPopup()
} else {
confirmwritepopup.askForConfirmation()
}
}
}
}
ColumnLayout {
id: columnLayout3
Layout.columnSpan: 3
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Text { Text {
id: progressText id: progressText
@ -202,16 +231,32 @@ ApplicationWindow {
visible: false visible: false
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true Layout.fillWidth: true
Layout.bottomMargin: 25
padding: 5
} }
ProgressBar { ProgressBar {
Layout.bottomMargin: 25
padding: 5
id: progressBar id: progressBar
Layout.fillWidth: true Layout.fillWidth: true
visible: false visible: false
Material.background: "#d15d7d" Material.background: "#d15d7d"
} }
}
ColumnLayout {
id: columnLayout3
Layout.row: 1
Layout.column: 2
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
spacing: 0
ImButton { ImButton {
Layout.bottomMargin: 25
Layout.minimumHeight: 40
Layout.preferredWidth: 200
padding: 5
id: cancelwritebutton id: cancelwritebutton
text: qsTr("CANCEL WRITE") text: qsTr("CANCEL WRITE")
onClicked: { onClicked: {
@ -223,6 +268,10 @@ ApplicationWindow {
visible: false visible: false
} }
ImButton { ImButton {
Layout.bottomMargin: 25
Layout.minimumHeight: 40
Layout.preferredWidth: 200
padding: 5
id: cancelverifybutton id: cancelverifybutton
text: qsTr("CANCEL VERIFY") text: qsTr("CANCEL VERIFY")
onClicked: { onClicked: {
@ -235,17 +284,25 @@ ApplicationWindow {
} }
ImButton { ImButton {
id: writebutton
text: qsTr("Next")
Layout.bottomMargin: 25 Layout.bottomMargin: 25
padding: 5 Layout.minimumHeight: 40
id: customizebutton Layout.preferredWidth: 200
Layout.alignment: Qt.AlignRight
Accessible.ignored: ospopup.visible || dstpopup.visible || hwpopup.visible
Accessible.description: qsTr("Select this button to start writing the image")
enabled: false
onClicked: { onClicked: {
optionspopup.openPopup() if (!imageWriter.readyToWrite()) {
} return
visible: imageWriter.imageSupportsCustomization() }
Accessible.description: qsTr("Select this button to access advanced settings")
contentItem: Image { if (!optionspopup.visible && imageWriter.imageSupportsCustomization()) {
source: "icons/ic_cog_red.svg" usesavedsettingspopup.openPopup()
fillMode: Image.PreserveAspectFit } else {
confirmwritepopup.askForConfirmation()
}
} }
} }
} }
@ -359,6 +416,110 @@ ApplicationWindow {
} }
} }
Popup {
id: hwpopup
x: 50
y: 25
width: parent.width-100
height: parent.height-50
padding: 0
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
property string hwselected: ""
// background of title
Rectangle {
color: "#f5f5f5"
anchors.right: parent.right
anchors.top: parent.top
height: 35
width: parent.width
}
// line under title
Rectangle {
color: "#afafaf"
width: parent.width
y: 35
implicitHeight: 1
}
Text {
text: "X"
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 25
anchors.topMargin: 10
font.family: roboto.name
font.bold: true
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
hwpopup.close()
}
}
}
ColumnLayout {
spacing: 10
Text {
text: qsTr("Raspberry Pi Device")
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: true
Layout.topMargin: 10
font.family: roboto.name
font.bold: true
}
Item {
clip: true
Layout.preferredWidth: hwlist.width
Layout.preferredHeight: hwlist.height
ListView {
id: hwlistview
interactive: false
ListView {
id: hwlist
model: ListModel {
id: deviceModel
ListElement {
name: qsTr("[ All ]")
tags: "[]"
icon: ""
description: ""
matching_type: "exclusive"
}
}
currentIndex: -1
delegate: hwdelegate
width: window.width-100
height: window.height-100
boundsBehavior: Flickable.StopAtBounds
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
ScrollBar.vertical: ScrollBar {
width: 10
policy: hwlist.contentHeight > hwlist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded
}
Keys.onSpacePressed: {
if (currentIndex != -1)
selectHWitem(model.get(currentIndex))
}
Accessible.onPressAction: {
if (currentIndex != -1)
selectHWitem(model.get(currentIndex))
}
Keys.onEnterPressed: Keys.onSpacePressed(event)
Keys.onReturnPressed: Keys.onSpacePressed(event)
}
}
}
}
}
/* /*
Popup for OS selection Popup for OS selection
*/ */
@ -402,6 +563,7 @@ ApplicationWindow {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
ospopup.close() ospopup.close()
osswipeview.decrementCurrentIndex()
} }
} }
} }
@ -419,59 +581,6 @@ ApplicationWindow {
font.bold: true font.bold: true
} }
Rectangle {
id: modelRowRect
color: "#ffffe3"
Layout.fillWidth: true
implicitHeight: modelRow.implicitHeight
visible: osswipeview.currentIndex == 0
Layout.bottomMargin: -10
Row {
id: modelRow
spacing: 15
leftPadding: 15
Text {
id: modelText
text: qsTr("Pi model:")
font.family: roboto.name
verticalAlignment: Qt.AlignVCenter
height: parent.height
}
ComboBox {
id: deviceModelCombo
model: ListModel {
id: deviceModel
ListElement {
name: qsTr("[ All ]")
tags: "[]"
}
}
width: 300
textRole: "name"
font.family: roboto.name
font.pixelSize: 12
currentIndex: 0
onCurrentIndexChanged: {
/* Reload list */
httpRequest(imageWriter.constantOsListUrl(), function (x) {
var o = JSON.parse(x.responseText)
var oslist = oslistFromJson(o)
if (oslist === false)
return
osmodel.remove(0, osmodel.count-2)
for (var i in oslist) {
osmodel.insert(osmodel.count-2, oslist[i])
}
})
}
}
}
}
Item { Item {
clip: true clip: true
Layout.preferredWidth: oslist.width Layout.preferredWidth: oslist.width
@ -487,7 +596,7 @@ ApplicationWindow {
currentIndex: -1 currentIndex: -1
delegate: osdelegate delegate: osdelegate
width: window.width-100 width: window.width-100
height: modelRowRect.visible ? window.height-100-modelRowRect.height : window.height-100 height: window.height-100
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
highlight: Rectangle { color: "lightsteelblue"; radius: 5 } highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
@ -559,30 +668,6 @@ ApplicationWindow {
ListModel { ListModel {
id: osmodel id: osmodel
ListElement {
url: "internal://format"
icon: "icons/erase.png"
extract_size: 0
image_download_size: 0
extract_sha256: ""
contains_multiple_files: false
release_date: ""
subitems_url: ""
subitems_json: ""
name: qsTr("Erase")
description: qsTr("Format card as FAT32")
tooltip: ""
website: ""
init_format: ""
}
ListElement {
url: ""
icon: "icons/use_custom.png"
name: qsTr("Use custom")
description: qsTr("Select a custom .img from your computer")
}
Component.onCompleted: { Component.onCompleted: {
if (imageWriter.isOnline()) { if (imageWriter.isOnline()) {
fetchOSlist(); fetchOSlist();
@ -590,6 +675,97 @@ ApplicationWindow {
} }
} }
Component {
id: hwdelegate
Item {
width: window.width-100
height: contentLayout.implicitHeight + 24
Accessible.name: name+".\n"+description
MouseArea {
id: hwMouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
bgrect.mouseOver = true
}
onExited: {
bgrect.mouseOver = false
}
onClicked: {
selectHWitem(model)
}
}
Rectangle {
id: bgrect
anchors.fill: parent
color: "#f5f5f5"
visible: mouseOver && parent.ListView.view.currentIndex !== index
property bool mouseOver: false
}
Rectangle {
id: borderrect
implicitHeight: 1
implicitWidth: parent.width
color: "#dcdcdc"
y: parent.height
}
RowLayout {
id: contentLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
margins: 12
}
spacing: 12
Image {
source: icon == "icons/ic_build_48px.svg" ? "icons/cat_misc_utility_images.png": icon
Layout.preferredHeight: 64
Layout.preferredWidth: 64
sourceSize.width: 64
sourceSize.height: 64
fillMode: Image.PreserveAspectFit
verticalAlignment: Image.AlignVCenter
Layout.alignment: Qt.AlignVCenter
}
ColumnLayout {
Layout.fillWidth: true
Text {
text: name
elide: Text.ElideRight
font.family: roboto.name
font.bold: true
}
Text {
Layout.fillWidth: true
font.family: roboto.name
text: description
wrapMode: Text.WordWrap
color: "#1a1a1a"
}
ToolTip {
visible: hwMouseArea.containsMouse && typeof(tooltip) == "string" && tooltip != ""
delay: 1000
text: typeof(tooltip) == "string" ? tooltip : ""
clip: false
}
}
}
}
}
Component { Component {
id: osdelegate id: osdelegate
@ -941,8 +1117,8 @@ ApplicationWindow {
title: qsTr("Warning") title: qsTr("Warning")
onYes: { onYes: {
langbarRect.visible = false langbarRect.visible = false
writebutton.visible = false
writebutton.enabled = false writebutton.enabled = false
customizebutton.visible = false
cancelwritebutton.enabled = true cancelwritebutton.enabled = true
cancelwritebutton.visible = true cancelwritebutton.visible = true
cancelverifybutton.enabled = true cancelverifybutton.enabled = true
@ -953,6 +1129,7 @@ ApplicationWindow {
progressBar.Material.accent = "#ffffff" progressBar.Material.accent = "#ffffff"
osbutton.enabled = false osbutton.enabled = false
dstbutton.enabled = false dstbutton.enabled = false
hwbutton.enabled = false
imageWriter.setVerifyEnabled(true) imageWriter.setVerifyEnabled(true)
imageWriter.startWrite() imageWriter.startWrite()
} }
@ -1071,9 +1248,9 @@ ApplicationWindow {
function resetWriteButton() { function resetWriteButton() {
progressText.visible = false progressText.visible = false
progressBar.visible = false progressBar.visible = false
customizebutton.visible = imageWriter.imageSupportsCustomization()
osbutton.enabled = true osbutton.enabled = true
dstbutton.enabled = true dstbutton.enabled = true
hwbutton.enabled = true
writebutton.visible = true writebutton.visible = true
writebutton.enabled = imageWriter.readyToWrite() writebutton.enabled = imageWriter.readyToWrite()
cancelwritebutton.visible = false cancelwritebutton.visible = false
@ -1113,10 +1290,10 @@ ApplicationWindow {
imageWriter.setSrc(file) imageWriter.setSrc(file)
osbutton.text = imageWriter.srcFileName() osbutton.text = imageWriter.srcFileName()
ospopup.close() ospopup.close()
osswipeview.decrementCurrentIndex()
if (imageWriter.readyToWrite()) { if (imageWriter.readyToWrite()) {
writebutton.enabled = true writebutton.enabled = true
} }
customizebutton.visible = imageWriter.imageSupportsCustomization()
} }
function onCancelled() { function onCancelled() {
@ -1150,7 +1327,7 @@ ApplicationWindow {
} }
} }
function filterItems(list, tags) function filterItems(list, tags, matchingType)
{ {
if (!tags || !tags.length) if (!tags || !tags.length)
return return
@ -1162,24 +1339,67 @@ ApplicationWindow {
if ("devices" in entry && entry["devices"].length) { if ("devices" in entry && entry["devices"].length) {
var foundTag = false var foundTag = false
for (var j in tags) switch(matchingType) {
{ case 0: /* exact matching */
if (entry["devices"].includes(tags[j])) case 2: /* exact matching */
{ for (var j in tags)
foundTag = true {
if (entry["devices"].includes(tags[j]))
{
foundTag = true
break
}
}
/* If there's no match, remove this item from the list. */
if (!foundTag)
{
list.splice(i, 1)
continue
}
break
case 1: /* Exlusive by prefix matching */
case 3: /* Inclusive by prefix matching */
for (var deviceTypePrefix in tags) {
for (var deviceSpec in entry["devices"]) {
if (deviceSpec.startsWith(deviceTypePrefix)) {
foundTag = true
break
}
}
/* Terminate outer loop early if we've already
* decided it's a match
*/
if (foundTag) {
break
}
}
/* If there's no match, remove this item from the list. */
if (!foundTag)
{
list.splice(i, 1)
continue
}
break break
}
} }
} else {
if (!foundTag) /* No device list attached? If we're in an exclusive mode that's bad news indeed. */
{ switch (matchingType) {
list.splice(i, 1) case 0:
continue case 1:
if (!("subitems" in entry)) {
/* If you're not carrying subitems, you're not going in. */
list.splice(i, 1)
}
break
case 2:
case 3:
/* Inclusive filtering. We're keeping this one. */
break;
} }
} }
if ("subitems" in entry) { if ("subitems" in entry) {
filterItems(entry["subitems"], tags) filterItems(entry["subitems"], tags, hwTagMatchingType)
} }
} }
} }
@ -1206,7 +1426,9 @@ ApplicationWindow {
oslist = o["os_list"] oslist = o["os_list"]
} }
filterItems(oslist, JSON.parse(deviceModel.get(deviceModelCombo.currentIndex).tags)) if (hwTags != "") {
filterItems(oslist, JSON.parse(hwTags), hwTagMatchingType)
}
checkForRandom(oslist) checkForRandom(oslist)
/* Flatten subitems to subitems_json */ /* Flatten subitems to subitems_json */
@ -1242,8 +1464,9 @@ ApplicationWindow {
var oslist = oslistFromJson(o) var oslist = oslistFromJson(o)
if (oslist === false) if (oslist === false)
return return
osmodel.clear()
for (var i in oslist) { for (var i in oslist) {
osmodel.insert(osmodel.count-2, oslist[i]) osmodel.append(oslist[i])
} }
if ("imager" in o) { if ("imager" in o) {
@ -1251,6 +1474,7 @@ ApplicationWindow {
if ("devices" in imager) if ("devices" in imager)
{ {
deviceModel.clear()
var devices = imager["devices"] var devices = imager["devices"]
for (var j in devices) for (var j in devices)
{ {
@ -1258,7 +1482,7 @@ ApplicationWindow {
deviceModel.append(devices[j]) deviceModel.append(devices[j])
if ("default" in devices[j] && devices[j]["default"]) if ("default" in devices[j] && devices[j]["default"])
{ {
deviceModelCombo.currentIndex = deviceModel.count-1 hwlist.currentIndex = deviceModel.count-1
} }
} }
} }
@ -1283,6 +1507,31 @@ ApplicationWindow {
} }
} }
} }
/* Add in our 'special' items. */
osmodel.append({
url: "internal://format",
icon: "icons/erase.png",
extract_size: 0,
image_download_size: 0,
extract_sha256: "",
contains_multiple_files: false,
release_date: "",
subitems_url: "",
subitems_json: "",
name: qsTr("Erase"),
description: qsTr("Format card as FAT32"),
tooltip: "",
website: "",
init_format: ""
})
osmodel.append({
url: "",
icon: "icons/use_custom.png",
name: qsTr("Use custom"),
description: qsTr("Select a custom .img from your computer")
})
}) })
} }
@ -1326,6 +1575,46 @@ ApplicationWindow {
return m return m
} }
function selectHWitem(hwmodel) {
hwTags = hwmodel.tags
if (hwmodel.matching_type) {
switch (hwmodel.matching_type) {
case "exclusive":
hwTagMatchingType = 0
break;
case "exclusive_prefix":
hwTagMatchingType = 1
break;
case "inclusive":
hwTagMatchingType = 2
break;
case "inclusive_prefix":
hwTagMatchingType = 3
break;
}
} else {
/* Default is exclusive exact matching */
hwTagMatchingType = 0
}
/* Reload list */
httpRequest(imageWriter.constantOsListUrl(), function (x) {
var o = JSON.parse(x.responseText)
var oslist = oslistFromJson(o)
if (oslist === false)
return
osmodel.remove(0, osmodel.count-2)
for (var i in oslist) {
osmodel.insert(osmodel.count-2, oslist[i])
}
})
hwbutton.text = hwmodel.name
hwpopup.close()
}
function selectOSitem(d, selectFirstSubitem) function selectOSitem(d, selectFirstSubitem)
{ {
if (typeof(d.subitems_json) == "string" && d.subitems_json !== "") { if (typeof(d.subitems_json) == "string" && d.subitems_json !== "") {
@ -1395,10 +1684,10 @@ ApplicationWindow {
imageWriter.setSrc(d.url, d.image_download_size, d.extract_size, typeof(d.extract_sha256) != "undefined" ? d.extract_sha256 : "", typeof(d.contains_multiple_files) != "undefined" ? d.contains_multiple_files : false, ospopup.categorySelected, d.name, typeof(d.init_format) != "undefined" ? d.init_format : "") imageWriter.setSrc(d.url, d.image_download_size, d.extract_size, typeof(d.extract_sha256) != "undefined" ? d.extract_sha256 : "", typeof(d.contains_multiple_files) != "undefined" ? d.contains_multiple_files : false, ospopup.categorySelected, d.name, typeof(d.init_format) != "undefined" ? d.init_format : "")
osbutton.text = d.name osbutton.text = d.name
ospopup.close() ospopup.close()
osswipeview.decrementCurrentIndex()
if (imageWriter.readyToWrite()) { if (imageWriter.readyToWrite()) {
writebutton.enabled = true writebutton.enabled = true
} }
customizebutton.visible = imageWriter.imageSupportsCustomization()
} }
} }

View file

@ -32,6 +32,7 @@
<file>icons/cat_language_specific_operating_systems.png</file> <file>icons/cat_language_specific_operating_systems.png</file>
<file>icons/cat_3d_printing.png</file> <file>icons/cat_3d_printing.png</file>
<file>icons/logo_stacked_imager.png</file> <file>icons/logo_stacked_imager.png</file>
<file>icons/logo_sxs_imager.png</file>
<file>qmlcomponents/ImButton.qml</file> <file>qmlcomponents/ImButton.qml</file>
<file>qmlcomponents/ImCheckBox.qml</file> <file>qmlcomponents/ImCheckBox.qml</file>
<file>qmlcomponents/ImRadioButton.qml</file> <file>qmlcomponents/ImRadioButton.qml</file>