formatDialog.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. ########################################################################
  2. # Wiizard - A Wii games manager
  3. # Copyright (C) 2023 CYBERDEViL
  4. #
  5. # This file is part of Wiizard.
  6. #
  7. # Wiizard is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # Wiizard is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ########################################################################
  21. from PyQt5.QtWidgets import (
  22. QDialog,
  23. QLabel,
  24. QGridLayout,
  25. QComboBox,
  26. QCheckBox,
  27. QPushButton,
  28. QMessageBox
  29. )
  30. from PyQt5.QtCore import QVariant
  31. import pywwt
  32. import wiizard.globals as Global
  33. import wiizard.const as Const
  34. from wiizard.translations import _
  35. """
  36. ============= FORMAT =============
  37. Partition: [partition select ]
  38. Recover : [X]
  39. [CANCEL] [FORMAT]
  40. ==================================
  41. """
  42. class FormatDialog(QDialog):
  43. def __init__(self, parent=None):
  44. QDialog.__init__(self, parent=parent)
  45. self.setWindowTitle(_("Format"))
  46. layout = QGridLayout(self)
  47. label = QLabel(_("Partition:"), self)
  48. self.partitionCombo = QComboBox(self)
  49. self.partitionCombo.setPlaceholderText(_("Select partition"))
  50. layout.addWidget(label , 0, 0, 1, 1)
  51. layout.addWidget(self.partitionCombo, 0, 1, 1, 2)
  52. self.recoverCheck = QCheckBox(_("Try to recover Wii games"), self)
  53. self.recoverCheck.setToolTip(_("Try to recover Wii games on a WBFS "
  54. "formatted partition"))
  55. self.recoverCheck.setEnabled(False)
  56. layout.addWidget(self.recoverCheck , 1, 1, 1, 2)
  57. cancelButton = QPushButton(_("Cancel"), self)
  58. self.formatButton = QPushButton(_("Format"), self)
  59. layout.addWidget(cancelButton , 2, 1, 1, 1)
  60. layout.addWidget(self.formatButton , 2, 2, 1, 1)
  61. Global.DevicesModel.deviceAdded.connect(self.__onDeviceAdded)
  62. Global.DevicesModel.deviceRemoved.connect(self.__onDeviceRemoved)
  63. self.refreshPartitions()
  64. self.formatButton.setEnabled(False)
  65. self.partitionCombo.currentIndexChanged.connect(self.__onIndexChange)
  66. self.formatButton.clicked.connect(self.__onFormatClicked)
  67. cancelButton.clicked.connect(self.reject)
  68. def refreshPartitions(self):
  69. for path in Global.DevicesModel.devices:
  70. device = Global.DevicesModel.devices[path]
  71. self.__addDevice(device)
  72. def __onIndexChange(self, index):
  73. # Only enabled format button when a partition is selected
  74. if index == -1:
  75. self.formatButton.setEnabled(False)
  76. else:
  77. self.formatButton.setEnabled(True)
  78. # Only enable recover checkbox on wbfs partitions
  79. currentDevicePath = self.partitionCombo.currentData()
  80. if not currentDevicePath:
  81. self.recoverCheck.setEnabled(False)
  82. return
  83. device = Global.DevicesModel.devices[currentDevicePath]
  84. if device in Global.DevicesModel.wbfsPartitions:
  85. self.recoverCheck.setEnabled(True)
  86. else:
  87. self.recoverCheck.setEnabled(False)
  88. def __onFormatClicked(self):
  89. devicePath = self.partitionCombo.currentData()
  90. recover = (self.recoverCheck.isEnabled() and self.recoverCheck.isChecked())
  91. recoverStr = ""
  92. if recover:
  93. recoverStr += (_("<br>However it will try to recover Wii games (no "
  94. "guaranties!)."))
  95. answer = QMessageBox.question(self, _("Confirmation"),
  96. _("Are you sure you want to format "
  97. f"'<b>{devicePath}</b>' ?<br>"
  98. "<b>All data on that partition will be lost!</b>"
  99. f"{recoverStr}"))
  100. if answer != QMessageBox.Yes:
  101. return
  102. # Format the partition
  103. result = None
  104. try:
  105. result = pywwt.format_to_wbfs(devicePath, recover=recover, testMode=False)
  106. except pywwt.error as err:
  107. QMessageBox.critical(self, _("Failed"), _(f"Format failed! Error: {err}"))
  108. else:
  109. if result:
  110. QMessageBox.information(self, _("Success"), _("Format success!"))
  111. Global.DevicesModel.rescanWbfsPartitions()
  112. else:
  113. QMessageBox.critical(self, _("Failed"), _("Format failed!"))
  114. self.accept()
  115. def __addDevice(self, device):
  116. if device.type != "partition":
  117. return
  118. if device.isMounted():
  119. return
  120. fsType = device.getFsType()
  121. if fsType == "swap":
  122. return
  123. if not fsType:
  124. if device in Global.DevicesModel.wbfsPartitions:
  125. fsType = "wbfs"
  126. else:
  127. fsType = "unknown"
  128. size = device.getSize()
  129. # TODO make a format size function
  130. sizeLabel = "Bytes"
  131. if size > Const.GiB:
  132. size = round(size / Const.GiB, 2)
  133. sizeLabel = "GiB"
  134. elif size > Const.MiB:
  135. size = round(size / Const.MiB, 2)
  136. sizeLabel = "MiB"
  137. self.partitionCombo.addItem(f"{device.path} [{size} {sizeLabel}] "
  138. f"[{device.vendor} - {device.model}] "
  139. f"({fsType})", QVariant(device.path))
  140. def __onDeviceAdded(self, devicePath):
  141. device = Global.DevicesModel.devices[devicePath]
  142. self.__addDevice(device)
  143. def __onDeviceRemoved(self, devicePath):
  144. index = self.partitionCombo.findData(QVariant(devicePath))
  145. if index != -1:
  146. self.partitionCombo.removeItem(index)