2
0

VMWizardSummaryView.swift 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //
  2. // Copyright © 2021 osy. All rights reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. import SwiftUI
  17. struct VMWizardSummaryView: View {
  18. @ObservedObject var wizardState: VMWizardState
  19. @EnvironmentObject private var data: UTMData
  20. var storageDescription: String {
  21. var size = Int64(wizardState.storageSizeGib * wizardState.bytesInGib)
  22. #if arch(arm64)
  23. if wizardState.operatingSystem == .Windows && wizardState.useVirtualization {
  24. if let attributes = try? wizardState.bootImageURL?.resourceValues(forKeys: [.fileSizeKey]), let fileSize = attributes.fileSize {
  25. size = Int64(fileSize)
  26. }
  27. }
  28. #endif
  29. return ByteCountFormatter.string(fromByteCount: size, countStyle: .binary)
  30. }
  31. var coreDescription: String {
  32. let cores = wizardState.systemCpuCount
  33. if cores == 0 {
  34. return NSLocalizedString("Default Cores", comment: "VMWizardSummaryView")
  35. } else {
  36. return String.localizedStringWithFormat(NSLocalizedString("%lld Cores", comment: "VMWizardSummaryView"), cores)
  37. }
  38. }
  39. var body: some View {
  40. VStack {
  41. #if os(macOS)
  42. Text("Summary")
  43. .font(.largeTitle)
  44. ScrollView {
  45. Form {
  46. info
  47. Divider()
  48. system
  49. .disabled(true)
  50. Divider()
  51. boot
  52. .disabled(true)
  53. Divider()
  54. sharing
  55. .disabled(true)
  56. }
  57. }
  58. Spacer()
  59. #else
  60. Form {
  61. Section(header: Text("Information")) {
  62. info
  63. }
  64. Section(header: Text("System")) {
  65. system
  66. .disabled(true)
  67. }
  68. Section(header: Text("Boot")) {
  69. boot
  70. .disabled(true)
  71. }
  72. Section(header: Text("Sharing")) {
  73. sharing
  74. .disabled(true)
  75. }
  76. }.textFieldStyle(.automatic)
  77. #endif
  78. }
  79. #if os(macOS)
  80. .padding([.horizontal, .bottom])
  81. #endif
  82. .navigationTitle(Text("Summary"))
  83. .onAppear {
  84. if wizardState.name == nil {
  85. let os = wizardState.operatingSystem
  86. if os == .Other {
  87. wizardState.name = data.newDefaultVMName()
  88. } else {
  89. wizardState.name = data.newDefaultVMName(base: os.name.localizedString)
  90. }
  91. }
  92. if #available(iOS 15, macOS 12, *) {
  93. wizardState.confusedUserCheck()
  94. } else {
  95. // SwiftUI bug: on older versions you need some delay
  96. DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
  97. wizardState.confusedUserCheck()
  98. }
  99. }
  100. }
  101. }
  102. var info: some View {
  103. Group {
  104. TextField("Name", text: $wizardState.name.bound)
  105. .lineLimit(1)
  106. #if os(macOS)
  107. Toggle("Open VM Settings", isOn: $wizardState.isOpenSettingsAfterCreation)
  108. .disabled(wizardState.isPendingIPSWDownload)
  109. #endif
  110. }
  111. }
  112. var system: some View {
  113. Group {
  114. TextField("Engine", text: .constant(NSLocalizedString(wizardState.useAppleVirtualization ? "Apple Virtualization" : "QEMU", comment: "VMWizardSummaryView")))
  115. Toggle("Use Virtualization", isOn: $wizardState.useVirtualization)
  116. Toggle("Legacy Hardware", isOn: $wizardState.legacyHardware)
  117. if !wizardState.useAppleVirtualization {
  118. TextField("Architecture", text: .constant(wizardState.systemArchitecture.prettyValue))
  119. TextField("System", text: .constant(wizardState.systemTarget.prettyValue))
  120. }
  121. TextField("RAM", text: .constant(ByteCountFormatter.string(fromByteCount: Int64(wizardState.systemMemoryMib * wizardState.bytesInMib), countStyle: .binary)))
  122. TextField("CPU", text: .constant(coreDescription))
  123. TextField("Storage", text: .constant(storageDescription))
  124. if !wizardState.useAppleVirtualization && wizardState.operatingSystem == .Linux {
  125. Toggle("Hardware OpenGL Acceleration", isOn: $wizardState.isGLEnabled)
  126. }
  127. }
  128. }
  129. var boot: some View {
  130. Group {
  131. TextField("Operating System", text: .constant(wizardState.operatingSystem.name.localizedString))
  132. if let bootImageURL = wizardState.bootImageURL {
  133. TextField("Boot Image", text: .constant(bootImageURL.path))
  134. }
  135. if wizardState.operatingSystem == .macOS {
  136. #if os(macOS) && arch(arm64)
  137. TextField("IPSW", text: .constant(wizardState.macRecoveryIpswURL?.path ?? ""))
  138. #else
  139. EmptyView()
  140. #endif
  141. } else if wizardState.operatingSystem == .Linux {
  142. TextField("Kernel", text: .constant(wizardState.linuxKernelURL?.path ?? ""))
  143. TextField("Initial Ramdisk", text: .constant(wizardState.linuxInitialRamdiskURL?.path ?? ""))
  144. TextField("Root Image", text: .constant(wizardState.linuxRootImageURL?.path ?? ""))
  145. TextField("Boot Arguments", text: $wizardState.linuxBootArguments)
  146. #if arch(arm64)
  147. if wizardState.useAppleVirtualization && wizardState.operatingSystem == .Linux {
  148. Toggle("Use Rosetta", isOn: $wizardState.linuxHasRosetta)
  149. }
  150. #endif
  151. }
  152. }
  153. }
  154. var sharing: some View {
  155. Group {
  156. Toggle("Share Directory", isOn: .constant(wizardState.sharingDirectoryURL != nil))
  157. if let sharingPath = wizardState.sharingDirectoryURL?.path {
  158. TextField("Directory", text: .constant(sharingPath))
  159. Toggle("Read Only", isOn: $wizardState.sharingReadOnly)
  160. }
  161. }
  162. }
  163. }
  164. struct VMWizardSummaryView_Previews: PreviewProvider {
  165. @StateObject static var wizardState = VMWizardState()
  166. static var previews: some View {
  167. VMWizardSummaryView(wizardState: wizardState)
  168. }
  169. }