Add basic accessibility support

- Support for screen readers on Linux/Windows. (Mac does not work
  as intended yet)
- Add keyboard navigation
- Add write confirmation dialog. Closes #84
- Update debian changelog
This commit is contained in:
Floris Bos 2020-06-30 00:42:39 +02:00
parent 855ad53b21
commit 2a0925b10a
6 changed files with 643 additions and 324 deletions

142
MsgPopup.qml Normal file
View file

@ -0,0 +1,142 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright (C) 2020 Raspberry Pi (Trading) Limited
*/
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls.Material 2.2
Popup {
id: msgpopup
x: 75
y: parent.height/2-100
width: parent.width-150
height: msgpopupbody.implicitHeight+150
padding: 0
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
property alias title: msgpopupheader.text
property alias text: msgpopupbody.text
property bool continueButton: true
property bool yesButton: false
property bool noButton: false
signal yes()
signal no()
// 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 {
id: msgx
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: {
msgpopup.close()
}
}
}
ColumnLayout {
spacing: 20
anchors.fill: parent
Text {
id: msgpopupheader
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: true
Layout.topMargin: 10
font.family: roboto.name
font.bold: true
}
Text {
id: msgpopupbody
font.pointSize: 12
wrapMode: Text.Wrap
textFormat: Text.StyledText
font.family: roboto.name
Layout.maximumWidth: msgpopup.width-50
Layout.fillHeight: true
Layout.leftMargin: 25
Layout.topMargin: 25
Accessible.name: text.replace(/<\/?[^>]+(>|$)/g, "")
}
RowLayout {
Layout.alignment: Qt.AlignCenter | Qt.AlignBottom
Layout.bottomMargin: 10
spacing: 20
Button {
text: qsTr("NO")
onClicked: {
msgpopup.close()
msgpopup.no()
}
Material.foreground: "#ffffff"
Material.background: "#c51a4a"
font.family: roboto.name
visible: msgpopup.noButton
Accessible.onPressAction: clicked()
}
Button {
text: qsTr("YES")
onClicked: {
msgpopup.close()
msgpopup.yes()
}
Material.foreground: "#ffffff"
Material.background: "#c51a4a"
font.family: roboto.name
visible: msgpopup.yesButton
Accessible.onPressAction: clicked()
}
Button {
text: qsTr("CONTINUE")
onClicked: {
msgpopup.close()
}
Material.foreground: "#ffffff"
Material.background: "#c51a4a"
font.family: roboto.name
visible: msgpopup.continueButton
Accessible.onPressAction: clicked()
}
Text { text: " " }
}
}
function openPopup() {
open()
// trigger screen reader to speak out message
msgpopupbody.forceActiveFocus()
}
}

12
debian/changelog vendored
View file

@ -1,3 +1,15 @@
rpi-imager (1.4) unstable; urgency=medium
* Add basic accessibility support
* Add keyboard navigation support
* Linux: do not let progress exceed 100% if
device reports incorrect write counters
* Show new SD card size if SD card is replaced
* Linux: do not use direct IO on verifying but purge cache with
posix_fadvise()
-- Floris Bos <bos@je-eigen-domein.nl> Tue, 30 Jun 2020 00:29:37 +0200
rpi-imager (1.3) unstable; urgency=medium rpi-imager (1.3) unstable; urgency=medium
* Remove zero sized drives from list * Remove zero sized drives from list

View file

@ -48,7 +48,7 @@
<translation>Fout bij uitvoeren authopen: &apos;%1&apos;</translation> <translation>Fout bij uitvoeren authopen: &apos;%1&apos;</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="192"/> <location filename="../downloadthread.cpp" line="193"/>
<source>Cannot open storage device &apos;%1&apos;.</source> <source>Cannot open storage device &apos;%1&apos;.</source>
<translation>Fout bij openen opslagapparaat &apos;%1&apos;.</translation> <translation>Fout bij openen opslagapparaat &apos;%1&apos;.</translation>
</message> </message>
@ -65,33 +65,33 @@ Card could be advertising wrong capacity (possible counterfeit)</source>
Kaart geeft mogelijk onjuiste capaciteit aan (mogelijk counterfeit)</translation> Kaart geeft mogelijk onjuiste capaciteit aan (mogelijk counterfeit)</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="523"/> <location filename="../downloadthread.cpp" line="537"/>
<source>Error writing to storage (while flushing)</source> <source>Error writing to storage (while flushing)</source>
<translation>Fout bij schrijven naar opslag (tijdens flushen)</translation> <translation>Fout bij schrijven naar opslag (tijdens flushen)</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="529"/> <location filename="../downloadthread.cpp" line="543"/>
<source>Error writing to storage (while fsync)</source> <source>Error writing to storage (while fsync)</source>
<translation>Fout bij schrijven naar opslag (tijdens fsync)</translation> <translation>Fout bij schrijven naar opslag (tijdens fsync)</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="546"/> <location filename="../downloadthread.cpp" line="560"/>
<source>Download corrupt. Hash does not match</source> <source>Download corrupt. Hash does not match</source>
<translation>Download corrupt. Hash komt niet overeen</translation> <translation>Download corrupt. Hash komt niet overeen</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="576"/> <location filename="../downloadthread.cpp" line="590"/>
<source>Error writing first block (partition table)</source> <source>Error writing first block (partition table)</source>
<translation>Fout bij schrijven naar eerste deel van kaart (partitie tabel)</translation> <translation>Fout bij schrijven naar eerste deel van kaart (partitie tabel)</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="622"/> <location filename="../downloadthread.cpp" line="642"/>
<source>Error reading from storage. <source>Error reading from storage.
SD card may be broken.</source> SD card may be broken.</source>
<translation>Fout bij lezen van SD kaart. Kaart is mogelijk defect.</translation> <translation>Fout bij lezen van SD kaart. Kaart is mogelijk defect.</translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="641"/> <location filename="../downloadthread.cpp" line="661"/>
<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>Verificatie mislukt. De gegevens die op de SD kaart staan wijken af van wat er naar geschreven is.</translation> <translation>Verificatie mislukt. De gegevens die op de SD kaart staan wijken af van wat er naar geschreven is.</translation>
</message> </message>
@ -101,7 +101,7 @@ SD card may be broken.</source>
<message> <message>
<location filename="../driveformatthread.cpp" line="63"/> <location filename="../driveformatthread.cpp" line="63"/>
<location filename="../driveformatthread.cpp" line="124"/> <location filename="../driveformatthread.cpp" line="124"/>
<location filename="../driveformatthread.cpp" line="181"/> <location filename="../driveformatthread.cpp" line="185"/>
<source>Error partitioning: %1</source> <source>Error partitioning: %1</source>
<translation>Fout bij partitioneren: %1</translation> <translation>Fout bij partitioneren: %1</translation>
</message> </message>
@ -126,27 +126,27 @@ SD card may be broken.</source>
<translation>Ongeldig device: %1</translation> <translation>Ongeldig device: %1</translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="144"/> <location filename="../driveformatthread.cpp" line="146"/>
<source>Error formatting (through udisks2)</source> <source>Error formatting (through udisks2)</source>
<translation>Fout bij formatteren (via udisks2)</translation> <translation>Fout bij formatteren (via udisks2)</translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="170"/> <location filename="../driveformatthread.cpp" line="174"/>
<source>Error starting sfdisk</source> <source>Error starting sfdisk</source>
<translation>Fout bij starten sfdisk</translation> <translation>Fout bij starten sfdisk</translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="192"/> <location filename="../driveformatthread.cpp" line="196"/>
<source>Error starting mkfs.fat</source> <source>Error starting mkfs.fat</source>
<translation>Fout bij starten mkfs.fat</translation> <translation>Fout bij starten mkfs.fat</translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="202"/> <location filename="../driveformatthread.cpp" line="206"/>
<source>Error running mkfs.fat: %1</source> <source>Error running mkfs.fat: %1</source>
<translation>Fout bij uitvoeren mkfs.fat: %1</translation> <translation>Fout bij uitvoeren mkfs.fat: %1</translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="209"/> <location filename="../driveformatthread.cpp" line="213"/>
<source>Formatting not implemented for this platform</source> <source>Formatting not implemented for this platform</source>
<translation>Formatteren is niet geimplementeerd op dit besturingssysteem</translation> <translation>Formatteren is niet geimplementeerd op dit besturingssysteem</translation>
</message> </message>
@ -154,198 +154,270 @@ SD card may be broken.</source>
<context> <context>
<name>ImageWriter</name> <name>ImageWriter</name>
<message> <message>
<location filename="../imagewriter.cpp" line="152"/> <location filename="../imagewriter.cpp" line="170"/>
<source>Storage capacity is not large enough. <source>Storage capacity is not large enough.
Needs to be at least %1 GB</source> Needs to be at least %1 GB</source>
<translation>Opslagcapaciteit niet groot genoeg. <translation>Opslagcapaciteit niet groot genoeg.
Deze dient minimaal %1 GB te zijn</translation> Deze dient minimaal %1 GB te zijn</translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="158"/> <location filename="../imagewriter.cpp" line="176"/>
<source>Input file is not a valid disk image. <source>Input file is not a valid disk image.
File size %1 bytes is not a multiple of 512 bytes.</source> File size %1 bytes is not a multiple of 512 bytes.</source>
<translation>Invoerbestand is geen disk image. <translation>Invoerbestand is geen disk image.
Bestandsgrootte %1 bytes is geen veelvoud van 512 bytes.</translation> Bestandsgrootte %1 bytes is geen veelvoud van 512 bytes.</translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="178"/> <location filename="../imagewriter.cpp" line="200"/>
<source>Downloading and writing image</source> <source>Downloading and writing image</source>
<translation>Downloaden en schrijven van image</translation> <translation>Downloaden en schrijven van image</translation>
</message> </message>
<message> <message>
<location filename="../imagewriter.cpp" line="380"/> <location filename="../imagewriter.cpp" line="403"/>
<source>Select image</source> <source>Select image</source>
<translation>Selecteer image</translation> <translation>Selecteer image</translation>
</message> </message>
</context> </context>
<context>
<name>LocalFileExtractThread</name>
<message>
<location filename="../localfileextractthread.cpp" line="38"/>
<source>Error opening image file</source>
<translation>Fout bij openen image bestand</translation>
</message>
</context>
<context>
<name>MsgPopup</name>
<message>
<location filename="../MsgPopup.qml" line="96"/>
<source>NO</source>
<translation>Nee</translation>
</message>
<message>
<location filename="../MsgPopup.qml" line="108"/>
<source>YES</source>
<translation>Ja</translation>
</message>
<message>
<location filename="../MsgPopup.qml" line="120"/>
<source>CONTINUE</source>
<translation>VERDER GAAN</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../linux/linuxdrivelist.cpp" line="111"/>
<source>Internal SD card reader</source>
<translation>Interne SD kaart lezer</translation>
</message>
</context>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../main.qml" line="23"/> <location filename="../main.qml" line="24"/>
<source>Raspberry Pi Imager v%1</source> <source>Raspberry Pi Imager v%1</source>
<translation>Raspberry Pi Imager v%1</translation> <translation>Raspberry Pi Imager v%1</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="32"/> <location filename="../main.qml" line="719"/>
<source>Are you sure you want to quit?</source> <source>Are you sure you want to quit?</source>
<translation>Weet u zeker dat u wilt afsluiten?</translation> <translation>Weet u zeker dat u wilt afsluiten?</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="33"/> <location filename="../main.qml" line="720"/>
<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>Raspberry Pi Imager is nog niet klaar.&lt;br&gt;Weet u zeker dat u wilt afsluiten?</translation> <translation>Raspberry Pi Imager is nog niet klaar.&lt;br&gt;Weet u zeker dat u wilt afsluiten?</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="78"/> <location filename="../main.qml" line="91"/>
<location filename="../main.qml" line="286"/> <location filename="../main.qml" line="300"/>
<source>Operating System</source> <source>Operating System</source>
<translation>Besturingssysteem</translation> <translation>Besturingssysteem</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="90"/> <location filename="../main.qml" line="103"/>
<source>CHOOSE OS</source> <source>CHOOSE OS</source>
<translation>SELECTEER OS</translation> <translation>SELECTEER OS</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="112"/> <location filename="../main.qml" line="133"/>
<location filename="../main.qml" line="594"/> <location filename="../main.qml" line="575"/>
<source>SD Card</source> <source>SD Card</source>
<translation>SD kaart</translation> <translation>SD kaart</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="124"/> <location filename="../main.qml" line="145"/>
<location filename="../main.qml" line="914"/> <location filename="../main.qml" line="859"/>
<source>CHOOSE SD CARD</source> <source>CHOOSE SD CARD</source>
<translation>SELECTEER SD KAART</translation> <translation>SELECTEER SD KAART</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="151"/> <location filename="../main.qml" line="175"/>
<source>WRITE</source> <source>WRITE</source>
<translation>SCHRIJF</translation> <translation>SCHRIJF</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="166"/> <location filename="../main.qml" line="737"/>
<location filename="../main.qml" line="859"/> <location filename="../main.qml" line="804"/>
<source>Writing... %1%</source> <source>Writing... %1%</source>
<translation>Schrijven... %1%</translation> <translation>Schrijven... %1%</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="204"/> <location filename="../main.qml" line="219"/>
<source>CANCEL WRITE</source> <source>CANCEL WRITE</source>
<translation>Annuleer schrijven</translation> <translation>Annuleer schrijven</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="207"/> <location filename="../main.qml" line="121"/>
<location filename="../main.qml" line="856"/> <source>Select this button to change the operating system</source>
<translation>Kies deze knop om een besturingssysteem te kiezen</translation>
</message>
<message>
<location filename="../main.qml" line="159"/>
<source>Select this button to change the destination SD card</source>
<translation>Kies deze knop om de SD kaart te kiezen</translation>
</message>
<message>
<location filename="../main.qml" line="180"/>
<source>Select this button to start writing the image</source>
<translation>Kies deze knop om te beginnen met het schrijven van de image</translation>
</message>
<message>
<location filename="../main.qml" line="222"/>
<location filename="../main.qml" line="801"/>
<source>Cancelling...</source> <source>Cancelling...</source>
<translation>Annuleren...</translation> <translation>Annuleren...</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="218"/> <location filename="../main.qml" line="233"/>
<source>CANCEL VERIFY</source> <source>CANCEL VERIFY</source>
<translation>ANNULEER VERIFICATIE</translation> <translation>ANNULEER VERIFICATIE</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="221"/> <location filename="../main.qml" line="236"/>
<location filename="../main.qml" line="879"/> <location filename="../main.qml" line="824"/>
<location filename="../main.qml" line="932"/> <location filename="../main.qml" line="877"/>
<source>Finalizing...</source> <source>Finalizing...</source>
<translation>Afronden...</translation> <translation>Afronden...</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="348"/> <location filename="../main.qml" line="373"/>
<location filename="../main.qml" line="908"/> <location filename="../main.qml" line="853"/>
<source>Erase</source> <source>Erase</source>
<translation>Wissen</translation> <translation>Wissen</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="349"/> <location filename="../main.qml" line="374"/>
<source>Format card as FAT32</source> <source>Format card as FAT32</source>
<translation>Formatteer kaart als FAT32</translation> <translation>Formatteer kaart als FAT32</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="356"/> <location filename="../main.qml" line="381"/>
<source>Use custom</source> <source>Use custom</source>
<translation>Gebruik eigen bestand</translation> <translation>Gebruik eigen bestand</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="357"/> <location filename="../main.qml" line="382"/>
<source>Select a custom .img from your computer</source> <source>Select a custom .img from your computer</source>
<translation>Selecteer een eigen .img bestand</translation> <translation>Selecteer een eigen .img bestand</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="364"/> <location filename="../main.qml" line="468"/>
<location filename="../main.qml" line="517"/> <source>Local file</source>
<translation>Lokaal bestand</translation>
</message>
<message>
<location filename="../main.qml" line="731"/>
<source>Warning</source>
<translation>Waarschuwing</translation>
</message>
<message>
<location filename="../main.qml" line="750"/>
<source>All existing data on &apos;%1&apos; will be erased.&lt;br&gt;Are you sure you want to continue?</source>
<translation>Alle bestaande gegevens op &apos;%1&apos; zullen verwijderd worden.&lt;br&gt;Weet u zeker dat u door wilt gaan?</translation>
</message>
<message>
<location filename="../main.qml" line="854"/>
<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>&lt;b&gt;%1&lt;/b&gt; is gewist&lt;br&gt;&lt;br&gt;U kunt nu de SD kaart uit de lezer halen</translation>
</message>
<message>
<location filename="../main.qml" line="884"/>
<location filename="../main.qml" line="926"/>
<source>Error parsing os_list.json</source> <source>Error parsing os_list.json</source>
<translation>Fout bij parsen os_list.json</translation> <translation>Fout bij parsen os_list.json</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="388"/> <location filename="../main.qml" line="964"/>
<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>Sluit eerst een USB stick met images aan.&lt;br&gt;De images moeten in de hoofdmap van de USB stick staan.</translation>
</message>
<message>
<location filename="../main.qml" line="405"/>
<source>Back</source> <source>Back</source>
<translation>Terug</translation> <translation>Terug</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="389"/> <location filename="../main.qml" line="406"/>
<source>Go back to main menu</source> <source>Go back to main menu</source>
<translation>Terug naar hoofdmenu</translation> <translation>Terug naar hoofdmenu</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="444"/> <location filename="../main.qml" line="463"/>
<source>Released: %1</source> <source>Released: %1</source>
<translation>Release datum: %1</translation> <translation>Release datum: %1</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="447"/> <location filename="../main.qml" line="466"/>
<source>Cached on your computer</source> <source>Cached on your computer</source>
<translation>Opgeslagen op computer</translation> <translation>Opgeslagen op computer</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="449"/> <location filename="../main.qml" line="470"/>
<source>Online - %1 GB download</source> <source>Online - %1 GB download</source>
<translation>Online %1 GB download</translation> <translation>Online %1 GB download</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="670"/> <location filename="../main.qml" line="628"/>
<location filename="../main.qml" line="676"/>
<source>Mounted as %1</source> <source>Mounted as %1</source>
<translation>Mounted op %1</translation> <translation>Mounted op %1</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="785"/>
<source>QUIT APP</source> <source>QUIT APP</source>
<translation>AFSLUITEN</translation> <translation type="vanished">AFSLUITEN</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="795"/>
<source>CONTINUE</source> <source>CONTINUE</source>
<translation>VERDER GAAN</translation> <translation type="vanished">VERDER GAAN</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="838"/> <location filename="../main.qml" line="783"/>
<source>Error downloading OS list from Internet</source> <source>Error downloading OS list from Internet</source>
<translation>Fout bij downloaden van lijst met besturingssystemen</translation> <translation>Fout bij downloaden van lijst met besturingssystemen</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="882"/> <location filename="../main.qml" line="827"/>
<source>Verifying... %1%</source> <source>Verifying... %1%</source>
<translation>Verifiëren... %1%</translation> <translation>Verifiëren... %1%</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="900"/> <location filename="../main.qml" line="845"/>
<source>Error</source> <source>Error</source>
<translation>Fout</translation> <translation>Fout</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="907"/> <location filename="../main.qml" line="852"/>
<source>Write Successful</source> <source>Write Successful</source>
<translation>Klaar met schrijven</translation> <translation>Klaar met schrijven</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="909"/>
<source>&lt;b&gt;%2&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;%2&lt;/b&gt; has been erased&lt;br&gt;&lt;br&gt;You can now remove the SD card from the reader</source>
<translation>&lt;b&gt;%2&lt;/b&gt; is gewist&lt;br&gt;&lt;br&gt;U kunt nu de SD kaart uit de lezer halen</translation> <translation type="vanished">&lt;b&gt;%2&lt;/b&gt; is gewist&lt;br&gt;&lt;br&gt;U kunt nu de SD kaart uit de lezer halen</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="911"/> <location filename="../main.qml" line="856"/>
<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>&lt;b&gt;%1&lt;/b&gt; is geschreven naar &lt;b&gt;%2&lt;/b&gt;&lt;br&gt;&lt;br&gt;U kunt nu de SD kaart uit de lezer halen</translation> <translation>&lt;b&gt;%1&lt;/b&gt; is geschreven naar &lt;b&gt;%2&lt;/b&gt;&lt;br&gt;&lt;br&gt;U kunt nu de SD kaart uit de lezer halen</translation>
</message> </message>

View file

@ -48,7 +48,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="192"/> <location filename="../downloadthread.cpp" line="193"/>
<source>Cannot open storage device &apos;%1&apos;.</source> <source>Cannot open storage device &apos;%1&apos;.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -64,33 +64,33 @@ 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="523"/> <location filename="../downloadthread.cpp" line="537"/>
<source>Error writing to storage (while flushing)</source> <source>Error writing to storage (while flushing)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="529"/> <location filename="../downloadthread.cpp" line="543"/>
<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> <message>
<location filename="../downloadthread.cpp" line="546"/> <location filename="../downloadthread.cpp" line="560"/>
<source>Download corrupt. Hash does not match</source> <source>Download corrupt. Hash does not match</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="576"/> <location filename="../downloadthread.cpp" line="590"/>
<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> <message>
<location filename="../downloadthread.cpp" line="622"/> <location filename="../downloadthread.cpp" line="642"/>
<source>Error reading from storage. <source>Error reading from storage.
SD card may be broken.</source> SD card may be broken.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../downloadthread.cpp" line="641"/> <location filename="../downloadthread.cpp" line="661"/>
<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>
@ -100,7 +100,7 @@ SD card may be broken.</source>
<message> <message>
<location filename="../driveformatthread.cpp" line="63"/> <location filename="../driveformatthread.cpp" line="63"/>
<location filename="../driveformatthread.cpp" line="124"/> <location filename="../driveformatthread.cpp" line="124"/>
<location filename="../driveformatthread.cpp" line="181"/> <location filename="../driveformatthread.cpp" line="185"/>
<source>Error partitioning: %1</source> <source>Error partitioning: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -125,27 +125,27 @@ SD card may be broken.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="144"/> <location filename="../driveformatthread.cpp" line="146"/>
<source>Error formatting (through udisks2)</source> <source>Error formatting (through udisks2)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="170"/> <location filename="../driveformatthread.cpp" line="174"/>
<source>Error starting sfdisk</source> <source>Error starting sfdisk</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="192"/> <location filename="../driveformatthread.cpp" line="196"/>
<source>Error starting mkfs.fat</source> <source>Error starting mkfs.fat</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="202"/> <location filename="../driveformatthread.cpp" line="206"/>
<source>Error running mkfs.fat: %1</source> <source>Error running mkfs.fat: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../driveformatthread.cpp" line="209"/> <location filename="../driveformatthread.cpp" line="213"/>
<source>Formatting not implemented for this platform</source> <source>Formatting not implemented for this platform</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -153,196 +153,264 @@ SD card may be broken.</source>
<context> <context>
<name>ImageWriter</name> <name>ImageWriter</name>
<message> <message>
<location filename="../imagewriter.cpp" line="152"/> <location filename="../imagewriter.cpp" line="170"/>
<source>Storage capacity is not large enough. <source>Storage capacity is not large enough.
Needs to be at least %1 GB</source> 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="158"/> <location filename="../imagewriter.cpp" line="176"/>
<source>Input file is not a valid disk image. <source>Input file is not a valid disk image.
File size %1 bytes is not a multiple of 512 bytes.</source> 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="178"/> <location filename="../imagewriter.cpp" line="200"/>
<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="380"/> <location filename="../imagewriter.cpp" line="403"/>
<source>Select image</source> <source>Select image</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>LocalFileExtractThread</name>
<message>
<location filename="../localfileextractthread.cpp" line="38"/>
<source>Error opening image file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MsgPopup</name>
<message>
<location filename="../MsgPopup.qml" line="96"/>
<source>NO</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../MsgPopup.qml" line="108"/>
<source>YES</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../MsgPopup.qml" line="120"/>
<source>CONTINUE</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../linux/linuxdrivelist.cpp" line="111"/>
<source>Internal SD card reader</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../main.qml" line="23"/> <location filename="../main.qml" line="24"/>
<source>Raspberry Pi Imager v%1</source> <source>Raspberry Pi Imager v%1</source>
<translation> v%1</translation> <translation> v%1</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="32"/> <location filename="../main.qml" line="719"/>
<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="33"/> <location filename="../main.qml" line="720"/>
<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="78"/> <location filename="../main.qml" line="91"/>
<location filename="../main.qml" line="286"/> <location filename="../main.qml" line="300"/>
<source>Operating System</source> <source>Operating System</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="90"/> <location filename="../main.qml" line="103"/>
<source>CHOOSE OS</source> <source>CHOOSE OS</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="112"/> <location filename="../main.qml" line="133"/>
<location filename="../main.qml" line="594"/> <location filename="../main.qml" line="575"/>
<source>SD Card</source> <source>SD Card</source>
<translation>SD卡</translation> <translation>SD卡</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="124"/> <location filename="../main.qml" line="145"/>
<location filename="../main.qml" line="914"/> <location filename="../main.qml" line="859"/>
<source>CHOOSE SD CARD</source> <source>CHOOSE SD CARD</source>
<translation>SD卡</translation> <translation>SD卡</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="151"/> <location filename="../main.qml" line="175"/>
<source>WRITE</source> <source>WRITE</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="166"/> <location filename="../main.qml" line="737"/>
<location filename="../main.qml" line="859"/> <location filename="../main.qml" line="804"/>
<source>Writing... %1%</source> <source>Writing... %1%</source>
<translation>...%1%</translation> <translation>...%1%</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="204"/> <location filename="../main.qml" line="219"/>
<source>CANCEL WRITE</source> <source>CANCEL WRITE</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="207"/> <location filename="../main.qml" line="121"/>
<location filename="../main.qml" line="856"/> <source>Select this button to change the operating system</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="159"/>
<source>Select this button to change the destination SD card</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="180"/>
<source>Select this button to start writing the image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="222"/>
<location filename="../main.qml" line="801"/>
<source>Cancelling...</source> <source>Cancelling...</source>
<translation>...</translation> <translation>...</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="218"/> <location filename="../main.qml" line="233"/>
<source>CANCEL VERIFY</source> <source>CANCEL VERIFY</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="221"/> <location filename="../main.qml" line="236"/>
<location filename="../main.qml" line="879"/> <location filename="../main.qml" line="824"/>
<location filename="../main.qml" line="932"/> <location filename="../main.qml" line="877"/>
<source>Finalizing...</source> <source>Finalizing...</source>
<translation>...</translation> <translation>...</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="348"/> <location filename="../main.qml" line="373"/>
<location filename="../main.qml" line="908"/> <location filename="../main.qml" line="853"/>
<source>Erase</source> <source>Erase</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="349"/> <location filename="../main.qml" line="374"/>
<source>Format card as FAT32</source> <source>Format card as FAT32</source>
<translation>SD卡为FAT32格式</translation> <translation>SD卡为FAT32格式</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="356"/> <location filename="../main.qml" line="381"/>
<source>Use custom</source> <source>Use custom</source>
<translation>使</translation> <translation>使</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="357"/> <location filename="../main.qml" line="382"/>
<source>Select a custom .img from your computer</source> <source>Select a custom .img from your computer</source>
<translation>使</translation> <translation>使</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="364"/> <location filename="../main.qml" line="468"/>
<location filename="../main.qml" line="517"/> <source>Local file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="731"/>
<source>Warning</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.qml" line="750"/>
<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>
</message>
<message>
<location filename="../main.qml" line="854"/>
<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>
</message>
<message>
<location filename="../main.qml" line="884"/>
<location filename="../main.qml" line="926"/>
<source>Error parsing os_list.json</source> <source>Error parsing os_list.json</source>
<translation> os_list.json </translation> <translation> os_list.json </translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="388"/> <location filename="../main.qml" line="964"/>
<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>
</message>
<message>
<location filename="../main.qml" line="405"/>
<source>Back</source> <source>Back</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="389"/> <location filename="../main.qml" line="406"/>
<source>Go back to main menu</source> <source>Go back to main menu</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="444"/> <location filename="../main.qml" line="463"/>
<source>Released: %1</source> <source>Released: %1</source>
<translation>...%1</translation> <translation>...%1</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="447"/> <location filename="../main.qml" line="466"/>
<source>Cached on your computer</source> <source>Cached on your computer</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="449"/> <location filename="../main.qml" line="470"/>
<source>Online - %1 GB download</source> <source>Online - %1 GB download</source>
<translation>%1 GB</translation> <translation>%1 GB</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="670"/> <location filename="../main.qml" line="628"/>
<location filename="../main.qml" line="676"/>
<source>Mounted as %1</source> <source>Mounted as %1</source>
<translation>%1 </translation> <translation>%1 </translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="785"/>
<source>QUIT APP</source> <source>QUIT APP</source>
<translation>退</translation> <translation type="vanished">退</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="795"/>
<source>CONTINUE</source> <source>CONTINUE</source>
<translation></translation> <translation type="vanished"></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="838"/> <location filename="../main.qml" line="783"/>
<source>Error downloading OS list from Internet</source> <source>Error downloading OS list from Internet</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="882"/> <location filename="../main.qml" line="827"/>
<source>Verifying... %1%</source> <source>Verifying... %1%</source>
<translation>...%1%</translation> <translation>...%1%</translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="900"/> <location filename="../main.qml" line="845"/>
<source>Error</source> <source>Error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="907"/> <location filename="../main.qml" line="852"/>
<source>Write Successful</source> <source>Write Successful</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.qml" line="909"/> <location filename="../main.qml" line="856"/>
<source>&lt;b&gt;%2&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>
</message>
<message>
<location filename="../main.qml" line="911"/>
<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>&lt;b&gt;%1&lt;/b&gt; &lt;b&gt;%2&lt;/b&gt;&lt;br&gt;&lt;br&gt;SD</translation> <translation>&lt;b&gt;%1&lt;/b&gt; &lt;b&gt;%2&lt;/b&gt;&lt;br&gt;&lt;br&gt;SD</translation>
</message> </message>

416
main.qml
View file

@ -30,10 +30,7 @@ ApplicationWindow {
onClosing: { onClosing: {
if (progressBar.visible) { if (progressBar.visible) {
close.accepted = false close.accepted = false
msgpopupheader.text = qsTr("Are you sure you want to quit?") quitpopup.openPopup()
msgpopupbody.text = qsTr("Raspberry Pi Imager is still busy.<br>Are you sure you want to quit?")
quitbutton.visible = true
msgpopup.open()
} }
} }
@ -111,9 +108,18 @@ ApplicationWindow {
topPadding: 0 topPadding: 0
Layout.minimumHeight: 40 Layout.minimumHeight: 40
Layout.fillWidth: true Layout.fillWidth: true
onClicked: ospopup.open() onClicked: {
ospopup.open()
if (osswipeview.currentIndex == 0)
oslist.forceActiveFocus()
else
suboslist.forceActiveFocus()
}
Material.background: "#ffffff" Material.background: "#ffffff"
Material.foreground: "#c51a4a" Material.foreground: "#c51a4a"
Accessible.ignored: ospopup.visible || dstpopup.visible
Accessible.description: qsTr("Select this button to change the operating system")
Accessible.onPressAction: clicked()
} }
} }
@ -146,9 +152,13 @@ ApplicationWindow {
imageWriter.refreshDriveList() imageWriter.refreshDriveList()
drivePollTimer.start() drivePollTimer.start()
dstpopup.open() dstpopup.open()
dstlist.forceActiveFocus()
} }
Material.background: "#ffffff" Material.background: "#ffffff"
Material.foreground: "#c51a4a" Material.foreground: "#c51a4a"
Accessible.ignored: ospopup.visible || dstpopup.visible
Accessible.description: qsTr("Select this button to change the destination SD card")
Accessible.onPressAction: clicked()
} }
} }
@ -168,6 +178,8 @@ ApplicationWindow {
font.family: roboto.name font.family: roboto.name
Layout.minimumHeight: 40 Layout.minimumHeight: 40
Layout.fillWidth: true Layout.fillWidth: true
Accessible.ignored: ospopup.visible || dstpopup.visible
Accessible.description: qsTr("Select this button to start writing the image")
enabled: false enabled: false
Material.background: "#ffffff" Material.background: "#ffffff"
@ -175,20 +187,10 @@ ApplicationWindow {
onClicked: { onClicked: {
if (!imageWriter.readyToWrite()) if (!imageWriter.readyToWrite())
return; return;
enabled = false
cancelwritebutton.enabled = true confirmwritepopup.askForConfirmation()
cancelwritebutton.visible = true
cancelverifybutton.enabled = true
progressText.text = qsTr("Writing... %1%").arg("0")
progressText.visible = true
progressBar.visible = true
progressBar.indeterminate = true
progressBar.Material.accent = "#ffffff"
osbutton.enabled = false
dstbutton.enabled = false
imageWriter.setVerifyEnabled(true)
imageWriter.startWrite()
} }
Accessible.onPressAction: clicked()
} }
} }
@ -228,6 +230,7 @@ ApplicationWindow {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
visible: false visible: false
font.family: roboto.name font.family: roboto.name
Accessible.onPressAction: clicked()
} }
Button { Button {
id: cancelverifybutton id: cancelverifybutton
@ -242,6 +245,7 @@ ApplicationWindow {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
visible: false visible: false
font.family: roboto.name font.family: roboto.name
Accessible.onPressAction: clicked()
} }
} }
} }
@ -258,7 +262,6 @@ ApplicationWindow {
width: parent.width-100 width: parent.width-100
height: parent.height-50 height: parent.height-50
padding: 0 padding: 0
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
// background of title // background of title
@ -320,28 +323,47 @@ ApplicationWindow {
ListView { ListView {
id: oslist id: oslist
model: osmodel model: osmodel
currentIndex: -1
delegate: osdelegate delegate: osdelegate
width: window.width-100 width: window.width-100
height: window.height-100 height: window.height-100
focus: true
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
width: 10 width: 10
policy: oslist.contentHeight > oslist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded policy: oslist.contentHeight > oslist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded
} }
Keys.onSpacePressed: {
if (currentIndex != -1)
selectOSitem(model.get(currentIndex), true)
}
Accessible.onPressAction: {
if (currentIndex != -1)
selectOSitem(model.get(currentIndex), true)
}
} }
ListView { ListView {
id: suboslist id: suboslist
model: subosmodel model: subosmodel
currentIndex: -1
delegate: osdelegate delegate: osdelegate
width: window.width-100 width: window.width-100
height: window.height-100 height: window.height-100
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
width: 10 width: 10
policy: suboslist.contentHeight > suboslist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded policy: suboslist.contentHeight > suboslist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded
} }
Keys.onSpacePressed: {
if (currentIndex != -1)
selectOSitem(model.get(currentIndex))
}
Accessible.onPressAction: {
if (currentIndex != -1)
selectOSitem(model.get(currentIndex))
}
} }
} }
} }
@ -405,12 +427,14 @@ ApplicationWindow {
Item { Item {
width: window.width-100 width: window.width-100
height: image_download_size ? 100 : 60 height: image_download_size ? 100 : 60
Accessible.name: name+".\n"+description
Rectangle { Rectangle {
id: bgrect id: bgrect
anchors.fill: parent anchors.fill: parent
color: "#f5f5f5" color: "#f5f5f5"
visible: false visible: mouseOver && parent.ListView.view.currentIndex !== index
property bool mouseOver: false
} }
Rectangle { Rectangle {
id: borderrect id: borderrect
@ -464,6 +488,13 @@ ApplicationWindow {
return txt; return txt;
} }
/*
Accessible.role: Accessible.ListItem
Accessible.name: name+".\n"+description
Accessible.focusable: true
Accessible.focused: parent.parent.parent.ListView.view.currentIndex === index
*/
ToolTip { ToolTip {
visible: osMouseArea.containsMouse && typeof(tooltip) == "string" && tooltip != "" visible: osMouseArea.containsMouse && typeof(tooltip) == "string" && tooltip != ""
delay: 1000 delay: 1000
@ -490,80 +521,15 @@ ApplicationWindow {
hoverEnabled: true hoverEnabled: true
onEntered: { onEntered: {
bgrect.visible = true bgrect.mouseOver = true
} }
onExited: { onExited: {
bgrect.visible = false bgrect.mouseOver = false
} }
onClicked: { onClicked: {
if (typeof(subitems) == "object" && subitems.count) { selectOSitem(model)
if (subosmodel.count>1)
{
subosmodel.remove(1, subosmodel.count-1)
}
for (var i=0; i<subitems.count; i++)
{
subosmodel.append(subitems.get(i))
}
osswipeview.setCurrentIndex(1)
} else if (typeof(subitems_url) == "string" && subitems_url != "") {
if (subitems_url == "internal://back")
{
osswipeview.setCurrentIndex(0)
}
else
{
if (subosmodel.count>1)
{
subosmodel.remove(1, subosmodel.count-1)
}
httpRequest(subitems_url, function (x) {
var o = JSON.parse(x.responseText)
if (!"os_list" in o) {
onError(qsTr("Error parsing os_list.json"))
return;
}
var oslist = o["os_list"]
for (var i in oslist) {
subosmodel.append(oslist[i])
}
})
osswipeview.setCurrentIndex(1)
}
} else if (url == "") {
if (!imageWriter.isEmbeddedMode()) {
imageWriter.openFileDialog()
}
else {
if (imageWriter.mountUsbSourceMedia()) {
if (subosmodel.count>1)
{
subosmodel.remove(1, subosmodel.count-1)
}
var oslist = JSON.parse(imageWriter.getUsbSourceOSlist())
for (var i in oslist) {
subosmodel.append(oslist[i])
}
osswipeview.setCurrentIndex(1)
}
else
{
onError(qsTr("Connect an USB stick containing images first.<br>The images must be located in the root folder of the USB stick."))
}
}
} else {
imageWriter.setSrc(url, image_download_size, extract_size, typeof(extract_sha256) != "undefined" ? extract_sha256 : "", typeof(contains_multiple_files) != "undefined" ? contains_multiple_files : false)
osbutton.text = name
ospopup.close()
if (imageWriter.readyToWrite()) {
writebutton.enabled = true
}
}
} }
} }
} }
@ -579,7 +545,6 @@ ApplicationWindow {
width: parent.width-100 width: parent.width-100
height: parent.height-50 height: parent.height-50
padding: 0 padding: 0
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
// background of title // background of title
@ -640,12 +605,37 @@ ApplicationWindow {
delegate: dstdelegate delegate: dstdelegate
width: window.width-100 width: window.width-100
height: window.height-100 height: window.height-100
focus: true
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
width: 10 width: 10
policy: dstlist.contentHeight > dstlist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded policy: dstlist.contentHeight > dstlist.height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded
} }
Keys.onSpacePressed: {
if (currentIndex == -1)
return
drivePollTimer.stop()
dstpopup.close()
imageWriter.setDst(currentItem.device, currentItem.size)
dstbutton.text = currentItem.description
if (imageWriter.readyToWrite()) {
writebutton.enabled = true
}
}
Accessible.onPressAction: {
if (currentIndex == -1)
return
drivePollTimer.stop()
dstpopup.close()
imageWriter.setDst(currentItem.device, currentItem.size)
dstbutton.text = currentItem.description
if (imageWriter.readyToWrite()) {
writebutton.enabled = true
}
}
} }
} }
} }
@ -657,12 +647,24 @@ ApplicationWindow {
Item { Item {
width: window.width-100 width: window.width-100
height: 60 height: 60
Accessible.name: {
var txt = description+" - "+(size/1000000000).toFixed(1)+" gigabytes"
if (mountpoints.length > 0) {
txt += qsTr("Mounted as %1").arg(mountpoints.join(", "))
}
return txt;
}
property string description: model.description
property string device: model.device
property string size: model.size
Rectangle { Rectangle {
id: dstbgrect id: dstbgrect
anchors.fill: parent anchors.fill: parent
color: "#f5f5f5" color: "#f5f5f5"
visible: false visible: mouseOver && parent.ListView.view.currentIndex !== index
property bool mouseOver: false
} }
Rectangle { Rectangle {
id: dstborderrect id: dstborderrect
@ -710,11 +712,11 @@ ApplicationWindow {
hoverEnabled: true hoverEnabled: true
onEntered: { onEntered: {
dstbgrect.visible = true dstbgrect.mouseOver = true
} }
onExited: { onExited: {
dstbgrect.visible = false dstbgrect.mouseOver = false
} }
onClicked: { onClicked: {
@ -730,109 +732,48 @@ ApplicationWindow {
} }
} }
Popup { MsgPopup {
id: msgpopup id: msgpopup
x: 75
y: parent.height/2-100
width: parent.width-150
height: msgpopupbody.implicitHeight+150 //200
padding: 0
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
// 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 { MsgPopup {
id: msgx id: quitpopup
text: "X" continueButton: false
anchors.right: parent.right yesButton: true
anchors.top: parent.top noButton: true
anchors.rightMargin: 25 title: qsTr("Are you sure you want to quit?")
anchors.topMargin: 10 text: qsTr("Raspberry Pi Imager is still busy.<br>Are you sure you want to quit?")
font.family: roboto.name onYes: {
font.bold: true
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
if (continuebutton.visible)
msgpopup.close()
else
Qt.quit() Qt.quit()
} }
} }
MsgPopup {
id: confirmwritepopup
continueButton: false
yesButton: true
noButton: true
title: qsTr("Warning")
onYes: {
writebutton.enabled = false
cancelwritebutton.enabled = true
cancelwritebutton.visible = true
cancelverifybutton.enabled = true
progressText.text = qsTr("Writing... %1%").arg("0")
progressText.visible = true
progressBar.visible = true
progressBar.indeterminate = true
progressBar.Material.accent = "#ffffff"
osbutton.enabled = false
dstbutton.enabled = false
imageWriter.setVerifyEnabled(true)
imageWriter.startWrite()
} }
ColumnLayout { function askForConfirmation()
spacing: 20 {
anchors.fill: parent text = qsTr("All existing data on '%1' will be erased.<br>Are you sure you want to continue?").arg(dstbutton.text)
openPopup()
Text {
id: msgpopupheader
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: true
Layout.topMargin: 10
font.family: roboto.name
font.bold: true
}
Text {
id: msgpopupbody
font.pointSize: 12
wrapMode: Text.Wrap
textFormat: Text.StyledText
font.family: roboto.name
Layout.maximumWidth: msgpopup.width-50
Layout.fillHeight: true
Layout.leftMargin: 25
Layout.topMargin: 25
}
RowLayout {
Layout.alignment: Qt.AlignCenter | Qt.AlignBottom
Layout.bottomMargin: 10
spacing: 20
Button {
id: quitbutton
text: qsTr("QUIT APP")
onClicked: Qt.quit()
Material.foreground: "#ffffff"
Material.background: "#c51a4a"
font.family: roboto.name
visible: imageWriter.isEmbeddedMode()
}
Button {
id: continuebutton
text: qsTr("CONTINUE")
onClicked: {
msgpopup.close()
quitbutton.visible = imageWriter.isEmbeddedMode()
}
Material.foreground: "#ffffff"
Material.background: "#c51a4a"
font.family: roboto.name
}
Text { text: " " }
}
} }
} }
@ -926,19 +867,19 @@ ApplicationWindow {
} }
function onError(msg) { function onError(msg) {
msgpopupheader.text = qsTr("Error") msgpopup.title = qsTr("Error")
msgpopupbody.text = msg msgpopup.text = msg
msgpopup.open() msgpopup.openPopup()
resetWriteButton() resetWriteButton()
} }
function onSuccess() { function onSuccess() {
msgpopupheader.text = qsTr("Write Successful") msgpopup.title = qsTr("Write Successful")
if (osbutton.text === qsTr("Erase")) if (osbutton.text === qsTr("Erase"))
msgpopupbody.text = qsTr("<b>%2</b> has been erased<br><br>You can now remove the SD card from the reader").arg(dstbutton.text) msgpopup.text = qsTr("<b>%1</b> has been erased<br><br>You can now remove the SD card from the reader").arg(dstbutton.text)
else else
msgpopupbody.text = qsTr("<b>%1</b> has been written to <b>%2</b><br><br>You can now remove the SD card from the reader").arg(osbutton.text).arg(dstbutton.text) msgpopup.text = qsTr("<b>%1</b> has been written to <b>%2</b><br><br>You can now remove the SD card from the reader").arg(osbutton.text).arg(dstbutton.text)
msgpopup.open() msgpopup.openPopup()
imageWriter.setDst("") imageWriter.setDst("")
dstbutton.text = qsTr("CHOOSE SD CARD") dstbutton.text = qsTr("CHOOSE SD CARD")
resetWriteButton() resetWriteButton()
@ -974,4 +915,87 @@ ApplicationWindow {
} }
}) })
} }
function selectOSitem(d, selectFirstSubitem)
{
if (typeof(d.subitems) == "object" && d.subitems.count) {
if (subosmodel.count>1)
{
subosmodel.remove(1, subosmodel.count-1)
}
for (var i=0; i<d.subitems.count; i++)
{
subosmodel.append(d.subitems.get(i))
}
if (selectFirstSubitem === true)
suboslist.currentIndex = 0
else
suboslist.currentIndex = -1
osswipeview.setCurrentIndex(1)
} else if (typeof(d.subitems_url) == "string" && d.subitems_url !== "") {
if (d.subitems_url === "internal://back")
{
osswipeview.setCurrentIndex(0)
}
else
{
if (subosmodel.count>1)
{
subosmodel.remove(1, subosmodel.count-1)
}
httpRequest(d.subitems_url, function (x) {
var o = JSON.parse(x.responseText)
if (!"os_list" in o) {
onError(qsTr("Error parsing os_list.json"))
return;
}
var oslist = o["os_list"]
for (var i in oslist) {
subosmodel.append(oslist[i])
}
})
if (selectFirstSubitem === true)
suboslist.currentIndex = 0
else
suboslist.currentIndex = -1
osswipeview.setCurrentIndex(1)
}
} else if (d.url === "") {
if (!imageWriter.isEmbeddedMode()) {
imageWriter.openFileDialog()
}
else {
if (imageWriter.mountUsbSourceMedia()) {
if (subosmodel.count>1)
{
subosmodel.remove(1, subosmodel.count-1)
}
var oslist = JSON.parse(imageWriter.getUsbSourceOSlist())
for (var i in oslist) {
subosmodel.append(oslist[i])
}
if (selectFirstSubitem === true)
suboslist.currentIndex = 0
else
suboslist.currentIndex = -1
osswipeview.setCurrentIndex(1)
}
else
{
onError(qsTr("Connect an USB stick containing images first.<br>The images must be located in the root folder of the USB stick."))
}
}
} else {
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)
osbutton.text = d.name
ospopup.close()
if (imageWriter.readyToWrite()) {
writebutton.enabled = true
}
}
}
} }

View file

@ -16,5 +16,6 @@
<file>icons/ic_sd_storage_40px.svg</file> <file>icons/ic_sd_storage_40px.svg</file>
<file>icons/ic_storage_40px.svg</file> <file>icons/ic_storage_40px.svg</file>
<file>icons/ic_usb_40px.svg</file> <file>icons/ic_usb_40px.svg</file>
<file>MsgPopup.qml</file>
</qresource> </qresource>
</RCC> </RCC>