mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-15 00:34:08 +09:00
- add an option to select the unit for temperature sensor (#73)
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
github "ashleymills/Reachability.swift" "v5.0.0"
|
||||
github "ashleymills/Reachability.swift" "v5.1.0"
|
||||
github "malcommac/Repeat" "0.6.0"
|
||||
|
||||
@@ -168,11 +168,7 @@ internal class Popup: NSView {
|
||||
])
|
||||
if tempValue != nil {
|
||||
self.temperatureCircle?.setValue(tempValue!)
|
||||
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: tempValue!, unit: UnitTemperature.celsius)
|
||||
self.temperatureCircle?.setText(formatter.string(from: measurement))
|
||||
self.temperatureCircle?.setText(Temperature(tempValue!))
|
||||
}
|
||||
}
|
||||
self.chart?.addValue(value.totalUsage)
|
||||
|
||||
@@ -147,10 +147,7 @@ private class GPUView: NSView {
|
||||
view.addSubview(self.temperatureCirle!)
|
||||
|
||||
self.temperatureCirle?.setValue(Double(self.value.temperature))
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: Double(self.value.temperature), unit: UnitTemperature.celsius)
|
||||
self.temperatureCirle?.setText(formatter.string(from: measurement))
|
||||
self.temperatureCirle?.setText(Temperature(Double(self.value.temperature)))
|
||||
self.temperatureChart?.addValue(Double(self.value.temperature) / 100)
|
||||
|
||||
self.addSubview(view)
|
||||
@@ -204,10 +201,7 @@ private class GPUView: NSView {
|
||||
self.stateView?.toolTip = "GPU \(gpu.state ? "enabled" : "disabled")"
|
||||
|
||||
self.temperatureCirle?.setValue(Double(gpu.temperature))
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: Double(gpu.temperature), unit: UnitTemperature.celsius)
|
||||
self.temperatureCirle?.setText(formatter.string(from: measurement))
|
||||
self.temperatureCirle?.setText(Temperature(Double(gpu.temperature)))
|
||||
|
||||
self.utilizationCircle?.setValue(gpu.utilization)
|
||||
self.utilizationCircle?.setText("\(Int(gpu.utilization*100))%")
|
||||
|
||||
@@ -14,6 +14,7 @@ import StatsKit
|
||||
import ModuleKit
|
||||
|
||||
internal class Settings: NSView, Settings_v {
|
||||
private var unitsValue: String = "system"
|
||||
private var updateIntervalValue: String = "3"
|
||||
private let listOfUpdateIntervals: [String] = ["1", "2", "3", "5", "10", "15", "30"]
|
||||
|
||||
@@ -40,6 +41,7 @@ internal class Settings: NSView, Settings_v {
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
self.updateIntervalValue = store.pointee.string(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue)
|
||||
self.unitsValue = store.pointee.string(key: "temperature_units", defaultValue: self.unitsValue)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -60,9 +62,16 @@ internal class Settings: NSView, Settings_v {
|
||||
}
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
let height: CGFloat = ((rowHeight+Constants.Settings.margin) * CGFloat(self.list.pointee.count) + rowHeight) + ((rowHeight+Constants.Settings.margin) * CGFloat(types.count) + 1)
|
||||
let settingsHeight: CGFloat = (rowHeight*2) + Constants.Settings.margin
|
||||
let sensorsListHeight: CGFloat = (rowHeight+Constants.Settings.margin) * CGFloat(self.list.pointee.count) + ((rowHeight+Constants.Settings.margin) * CGFloat(types.count) + 1)
|
||||
let height: CGFloat = settingsHeight + sensorsListHeight
|
||||
let x: CGFloat = height < 360 ? 0 : Constants.Settings.margin
|
||||
let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: self.frame.width - (Constants.Settings.margin*2) - x, height: height))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: self.frame.width - (Constants.Settings.margin*2) - x,
|
||||
height: height
|
||||
))
|
||||
|
||||
self.addSubview(SelectTitleRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: height - rowHeight, width: view.frame.width, height: rowHeight),
|
||||
@@ -72,6 +81,14 @@ internal class Settings: NSView, Settings_v {
|
||||
selected: "\(self.updateIntervalValue) sec"
|
||||
))
|
||||
|
||||
self.addSubview(SelectRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: height - (rowHeight*2) - Constants.Settings.margin, width: view.frame.width, height: rowHeight),
|
||||
title: LocalizedString("Temperature unit"),
|
||||
action: #selector(changeUnits),
|
||||
items: TemperatureUnits,
|
||||
selected: self.unitsValue
|
||||
))
|
||||
|
||||
var y: CGFloat = 0
|
||||
types.reversed().forEach { (typ: SensorType_t) in
|
||||
let filtered = self.list.pointee.filter{ $0.type == typ }
|
||||
@@ -136,4 +153,13 @@ internal class Settings: NSView, Settings_v {
|
||||
self.setInterval(value)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func changeUnits(_ sender: NSMenuItem) {
|
||||
guard let key = sender.representedObject as? String else {
|
||||
return
|
||||
}
|
||||
self.unitsValue = key
|
||||
store.pointee.set(key: "temperature_units", value: key)
|
||||
self.callback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,11 +55,7 @@ struct Sensor_t {
|
||||
get {
|
||||
switch self.type {
|
||||
case SensorType.Temperature.rawValue:
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: (value ?? 0), unit: UnitTemperature.celsius)
|
||||
|
||||
return formatter.string(from: measurement)
|
||||
return Temperature(value ?? 0)
|
||||
case SensorType.Voltage.rawValue:
|
||||
return String(format: "%.3f \(unit)", value ?? 0)
|
||||
case SensorType.Power.rawValue:
|
||||
@@ -72,11 +68,7 @@ struct Sensor_t {
|
||||
get {
|
||||
switch self.type {
|
||||
case SensorType.Temperature.rawValue:
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: (value ?? 0), unit: UnitTemperature.celsius)
|
||||
|
||||
return formatter.string(from: measurement).replacingOccurrences(of: "C", with: "").replacingOccurrences(of: "F", with: "")
|
||||
return Temperature(value ?? 0).replacingOccurrences(of: "C", with: "").replacingOccurrences(of: "F", with: "")
|
||||
case SensorType.Voltage.rawValue:
|
||||
return String(format: "%.1f\(unit)", value ?? 0)
|
||||
case SensorType.Power.rawValue:
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
"Used disk memory" = "Used %0 from %1";
|
||||
"Disk to show" = "Disk to show";
|
||||
|
||||
// Sensors
|
||||
"Temperature unit" = "Temperature unit";
|
||||
|
||||
// Network
|
||||
"Uploading" = "Upload";
|
||||
"Downloading" = "Download";
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
"Used disk memory" = "Wykorzystano %0 z %1";
|
||||
"Disk to show" = "Aktywny dysk";
|
||||
|
||||
// Sensors
|
||||
"Temperature unit" = "Jednostka temperatury";
|
||||
|
||||
// Network
|
||||
"Uploading" = "Wysyłka";
|
||||
"Downloading" = "Pobieranie";
|
||||
|
||||
@@ -93,11 +93,14 @@
|
||||
"Compressed" = "Сжатая";
|
||||
"Free" = "Свободная";
|
||||
|
||||
// DiskF
|
||||
// Disk
|
||||
"Show removable disks" = "Показать съемные диски";
|
||||
"Used disk memory" = "Использовано %0 с %1";
|
||||
"Disk to show" = "Активный диск";
|
||||
|
||||
// Sensors
|
||||
"Temperature unit" = "Единица измерения температуры";
|
||||
|
||||
// Network
|
||||
"Uploading" = "Висилання";
|
||||
"Downloading" = "Загрузка";
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
"Used disk memory" = "kullanılan %0 , toplam %1";
|
||||
"Disk to show" = "Gösterilecek disk";
|
||||
|
||||
// Sensors
|
||||
"Temperature unit" = "Sıcaklık birimi";
|
||||
|
||||
// Network
|
||||
"Uploading" = "Yükleme";
|
||||
"Downloading" = "İndirme";
|
||||
|
||||
@@ -93,11 +93,14 @@
|
||||
"Compressed" = "Стисненна";
|
||||
"Free" = "Вільна";
|
||||
|
||||
// DiskF
|
||||
// Disk
|
||||
"Show removable disks" = "Показати зйомні диски";
|
||||
"Used disk memory" = "Використано %0 з %1";
|
||||
"Disk to show" = "Активний диск";
|
||||
|
||||
// Sensors
|
||||
"Temperature unit" = "Одиниця виміру температури";
|
||||
|
||||
// Network
|
||||
"Uploading" = "Вислання";
|
||||
"Downloading" = "Завантаження";
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
"Used disk memory" = "%1 中已用 %0";
|
||||
"Disk to show" = "显示的磁盘";
|
||||
|
||||
// Sensors
|
||||
"Temperature unit" = "Temperature unit";
|
||||
|
||||
// Network
|
||||
"Uploading" = "上传";
|
||||
"Downloading" = "下载";
|
||||
|
||||
@@ -418,6 +418,43 @@ public extension NSView {
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
func SelectRow(frame: NSRect, title: String, action: Selector, items: [KeyValue_t], selected: String) -> NSView {
|
||||
let row: NSView = NSView(frame: frame)
|
||||
|
||||
let rowTitle: NSTextField = LabelField(frame: NSRect(x: 0, y: (row.frame.height - 16)/2, width: row.frame.width - 52, height: 17), title)
|
||||
rowTitle.font = NSFont.systemFont(ofSize: 13, weight: .light)
|
||||
rowTitle.textColor = .textColor
|
||||
|
||||
let select: NSPopUpButton = NSPopUpButton(frame: NSRect(x: row.frame.width - 50, y: (row.frame.height-26)/2, width: 50, height: 26))
|
||||
select.target = self
|
||||
select.action = action
|
||||
|
||||
let menu = NSMenu()
|
||||
items.forEach { (item) in
|
||||
if item.key.contains("separator") {
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
} else {
|
||||
let interfaceMenu = NSMenuItem(title: item.value, action: nil, keyEquivalent: "")
|
||||
interfaceMenu.representedObject = item.key
|
||||
menu.addItem(interfaceMenu)
|
||||
if selected == item.key {
|
||||
interfaceMenu.state = .on
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select.menu = menu
|
||||
select.sizeToFit()
|
||||
|
||||
rowTitle.setFrameSize(NSSize(width: row.frame.width - select.frame.width, height: rowTitle.frame.height))
|
||||
select.setFrameOrigin(NSPoint(x: row.frame.width - select.frame.width, y: select.frame.origin.y))
|
||||
|
||||
row.addSubview(select)
|
||||
row.addSubview(rowTitle)
|
||||
|
||||
return row
|
||||
}
|
||||
}
|
||||
|
||||
public extension Notification.Name {
|
||||
@@ -827,6 +864,25 @@ public enum updateIntervals: updateInterval {
|
||||
}
|
||||
extension updateIntervals: CaseIterable {}
|
||||
|
||||
public struct KeyValue_t {
|
||||
let key: String
|
||||
let value: String
|
||||
let additional: Any?
|
||||
|
||||
init(key: String, value: String, additional: Any? = nil) {
|
||||
self.key = key
|
||||
self.value = value
|
||||
self.additional = additional
|
||||
}
|
||||
}
|
||||
|
||||
public let TemperatureUnits: [KeyValue_t] = [
|
||||
KeyValue_t(key: "system", value: "System"),
|
||||
KeyValue_t(key: "separator", value: "separator"),
|
||||
KeyValue_t(key: "celsius", value: "Celsius", additional: UnitTemperature.celsius),
|
||||
KeyValue_t(key: "fahrenheit", value: "Fahrenheit", additional: UnitTemperature.fahrenheit)
|
||||
]
|
||||
|
||||
public func showNotification(title: String, subtitle: String, id: String = UUID().uuidString, icon: NSImage? = nil) -> NSUserNotification {
|
||||
let notification = NSUserNotification()
|
||||
|
||||
@@ -962,3 +1018,19 @@ public func LocalizedString(_ key: String, _ params: String..., comment: String
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
public func Temperature(_ value: Double) -> String {
|
||||
let stringUnit: String = Store.shared.string(key: "temperature_units", defaultValue: "system")
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
formatter.unitOptions = .providedUnit
|
||||
|
||||
var measurement = Measurement(value: value, unit: UnitTemperature.celsius)
|
||||
if stringUnit != "system" {
|
||||
if let temperatureUnit = TemperatureUnits.first(where: { $0.key == stringUnit }), let unit = temperatureUnit.additional as? UnitTemperature {
|
||||
measurement.convert(to: unit)
|
||||
}
|
||||
}
|
||||
|
||||
return formatter.string(from: measurement)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import Cocoa
|
||||
|
||||
public class Store {
|
||||
public static let shared = Store()
|
||||
private let defaults = UserDefaults.standard
|
||||
|
||||
public init() {}
|
||||
|
||||
Reference in New Issue
Block a user