From 3fb0eeabce23a572d64d8bedf20f504e0273b6cb Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Sun, 15 Sep 2019 15:51:50 +0200 Subject: [PATCH] added option to set update time for each module --- Stats/Modules/Battery/Battery.swift | 74 +++++++++++++++++++++++ Stats/Modules/Battery/BatteryReader.swift | 7 ++- Stats/Modules/CPU/CPU.swift | 74 +++++++++++++++++++++++ Stats/Modules/CPU/CPUReader.swift | 8 ++- Stats/Modules/Disk/Disk.swift | 74 +++++++++++++++++++++++ Stats/Modules/Disk/DiskReader.swift | 13 ++-- Stats/Modules/Memory/Memory.swift | 74 +++++++++++++++++++++++ Stats/Modules/Memory/MemoryReader.swift | 8 ++- Stats/Modules/Module.swift | 1 + Stats/Modules/Network/Network.swift | 3 + Stats/Modules/Network/NetworkReader.swift | 11 ++-- Stats/Modules/Reader.swift | 1 + 12 files changed, 336 insertions(+), 12 deletions(-) diff --git a/Stats/Modules/Battery/Battery.swift b/Stats/Modules/Battery/Battery.swift index ca570ff4..0def5cce 100644 --- a/Stats/Modules/Battery/Battery.swift +++ b/Stats/Modules/Battery/Battery.swift @@ -19,6 +19,7 @@ class Battery: Module { public var tabAvailable: Bool = true public var tabInitialized: Bool = false public var tabView: NSTabViewItem = NSTabViewItem() + public var updateInterval: Int public var widgetType: WidgetType = Widgets.Battery public let percentageView: Observable @@ -33,6 +34,8 @@ class Battery: Module { self.percentageView = Observable(defaults.object(forKey: "\(self.name)_percentage") != nil ? defaults.bool(forKey: "\(self.name)_percentage") : false) self.timeView = Observable(defaults.object(forKey: "\(self.name)_time") != nil ? defaults.bool(forKey: "\(self.name)_time") : false) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Battery + self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.integer(forKey: "\(name)_interval") : 3 + self.reader.updateInterval << self.updateInterval } func start() { @@ -86,6 +89,9 @@ class Battery: Module { } } + submenu.addItem(NSMenuItem.separator()) + submenu.addItem(generateIntervalMenu()) + if active { menu.submenu = submenu } @@ -137,5 +143,73 @@ class Battery: Module { self.initMenu(active: true) menuBar!.updateWidget(name: self.name) } + + func generateIntervalMenu() -> NSMenuItem { + let updateInterval = NSMenuItem(title: "Update interval", action: nil, keyEquivalent: "") + + let updateIntervals = NSMenu() + let updateInterval_1 = NSMenuItem(title: "1s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_1.state = self.updateInterval == 1 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_1.target = self + let updateInterval_2 = NSMenuItem(title: "3s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_2.state = self.updateInterval == 3 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_2.target = self + let updateInterval_3 = NSMenuItem(title: "5s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_3.state = self.updateInterval == 5 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_3.target = self + let updateInterval_4 = NSMenuItem(title: "10s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_4.state = self.updateInterval == 10 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_4.target = self + let updateInterval_5 = NSMenuItem(title: "15s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_5.state = self.updateInterval == 15 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_5.target = self + + updateIntervals.addItem(updateInterval_1) + updateIntervals.addItem(updateInterval_2) + updateIntervals.addItem(updateInterval_3) + updateIntervals.addItem(updateInterval_4) + updateIntervals.addItem(updateInterval_5) + + updateInterval.submenu = updateIntervals + + return updateInterval + } + + @objc func changeInterval(_ sender: NSMenuItem) { + var interval: Int = self.updateInterval + + switch sender.title { + case "1s": + interval = 1 + case "3s": + interval = 3 + case "5s": + interval = 5 + case "10s": + interval = 10 + case "15s": + interval = 15 + default: + break + } + + + if interval == self.updateInterval { + return + } + + for item in self.submenu.items { + if item.title == "Update interval" { + for subitem in item.submenu!.items { + subitem.state = NSControl.StateValue.off + } + } + } + + sender.state = NSControl.StateValue.on + self.updateInterval = interval + self.defaults.set(interval, forKey: "\(name)_interval") + self.reader.updateInterval << interval + } } diff --git a/Stats/Modules/Battery/BatteryReader.swift b/Stats/Modules/Battery/BatteryReader.swift index 07aa08a9..e885adf1 100644 --- a/Stats/Modules/Battery/BatteryReader.swift +++ b/Stats/Modules/Battery/BatteryReader.swift @@ -30,6 +30,7 @@ struct BatteryUsage { class BatteryReader: Reader { public var value: Observable<[Double]>! + public var updateInterval: Observable = Observable(0) public var usage: Observable = Observable(BatteryUsage()) public var updateTimer: Timer! @@ -52,6 +53,10 @@ class BatteryReader: Reader { init() { self.value = Observable([]) read() + self.updateInterval.subscribe(observer: self) { (value, _) in + self.stop() + self.start() + } } func start() { @@ -59,7 +64,7 @@ class BatteryReader: Reader { if updateTimer != nil { return } - updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true) + updateTimer = Timer.scheduledTimer(timeInterval: TimeInterval(self.updateInterval.value), target: self, selector: #selector(read), userInfo: nil, repeats: true) } func stop() { diff --git a/Stats/Modules/CPU/CPU.swift b/Stats/Modules/CPU/CPU.swift index 6ba063d8..8d07586b 100644 --- a/Stats/Modules/CPU/CPU.swift +++ b/Stats/Modules/CPU/CPU.swift @@ -23,6 +23,7 @@ class CPU: Module { public var tabInitialized: Bool = false public var widgetType: WidgetType public var chart: LineChartView = LineChartView() + public var updateInterval: Int private let defaults = UserDefaults.standard private var submenu: NSMenu = NSMenu() @@ -32,7 +33,9 @@ class CPU: Module { self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.hyperthreading = Observable(defaults.object(forKey: "\(name)_hyperthreading") != nil ? defaults.bool(forKey: "\(name)_hyperthreading") : false) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini + self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.integer(forKey: "\(name)_interval") : 3 + self.reader.updateInterval << self.updateInterval if self.widgetType == Widgets.BarChart { (self.reader as! CPUReader).perCoreMode = true (self.reader as! CPUReader).hyperthreading = self.hyperthreading.value @@ -87,6 +90,9 @@ class CPU: Module { submenu.addItem(hyperthreading) } + submenu.addItem(NSMenuItem.separator()) + submenu.addItem(generateIntervalMenu()) + if active { menu.submenu = submenu } @@ -153,4 +159,72 @@ class CPU: Module { self.hyperthreading << (sender.state == NSControl.StateValue.on) (self.reader as! CPUReader).hyperthreading = sender.state == NSControl.StateValue.on } + + func generateIntervalMenu() -> NSMenuItem { + let updateInterval = NSMenuItem(title: "Update interval", action: nil, keyEquivalent: "") + + let updateIntervals = NSMenu() + let updateInterval_1 = NSMenuItem(title: "1s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_1.state = self.updateInterval == 1 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_1.target = self + let updateInterval_2 = NSMenuItem(title: "3s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_2.state = self.updateInterval == 3 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_2.target = self + let updateInterval_3 = NSMenuItem(title: "5s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_3.state = self.updateInterval == 5 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_3.target = self + let updateInterval_4 = NSMenuItem(title: "10s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_4.state = self.updateInterval == 10 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_4.target = self + let updateInterval_5 = NSMenuItem(title: "15s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_5.state = self.updateInterval == 15 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_5.target = self + + updateIntervals.addItem(updateInterval_1) + updateIntervals.addItem(updateInterval_2) + updateIntervals.addItem(updateInterval_3) + updateIntervals.addItem(updateInterval_4) + updateIntervals.addItem(updateInterval_5) + + updateInterval.submenu = updateIntervals + + return updateInterval + } + + @objc func changeInterval(_ sender: NSMenuItem) { + var interval: Int = self.updateInterval + + switch sender.title { + case "1s": + interval = 1 + case "3s": + interval = 3 + case "5s": + interval = 5 + case "10s": + interval = 10 + case "15s": + interval = 15 + default: + break + } + + + if interval == self.updateInterval { + return + } + + for item in self.submenu.items { + if item.title == "Update interval" { + for subitem in item.submenu!.items { + subitem.state = NSControl.StateValue.off + } + } + } + + sender.state = NSControl.StateValue.on + self.updateInterval = interval + self.defaults.set(interval, forKey: "\(name)_interval") + self.reader.updateInterval << interval + } } diff --git a/Stats/Modules/CPU/CPUReader.swift b/Stats/Modules/CPU/CPUReader.swift index 76ae07d0..a9ee836f 100644 --- a/Stats/Modules/CPU/CPUReader.swift +++ b/Stats/Modules/CPU/CPUReader.swift @@ -23,6 +23,7 @@ struct TopProcess { class CPUReader: Reader { public var value: Observable<[Double]>! + public var updateInterval: Observable = Observable(0) public var usage: Observable = Observable(CPUUsage()) public var processes: Observable<[TopProcess]> = Observable([TopProcess]()) public var available: Bool = true @@ -57,13 +58,18 @@ class CPUReader: Reader { } read() } + + self.updateInterval.subscribe(observer: self) { (value, _) in + self.stop() + self.start() + } } func start() { if updateTimer != nil { return } - updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true) + updateTimer = Timer.scheduledTimer(timeInterval: TimeInterval(self.updateInterval.value), target: self, selector: #selector(read), userInfo: nil, repeats: true) if topProcess.isRunning { return diff --git a/Stats/Modules/Disk/Disk.swift b/Stats/Modules/Disk/Disk.swift index d12034ae..3aad0e65 100644 --- a/Stats/Modules/Disk/Disk.swift +++ b/Stats/Modules/Disk/Disk.swift @@ -22,6 +22,7 @@ class Disk: Module { public var tabView: NSTabViewItem = NSTabViewItem() public var reader: Reader = DiskReader() + public var updateInterval: Int private var submenu: NSMenu = NSMenu() private let defaults = UserDefaults.standard @@ -30,6 +31,8 @@ class Disk: Module { self.available = Observable(true) self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini + self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.integer(forKey: "\(name)_interval") : 3 + self.reader.updateInterval << self.updateInterval } func initTab() { @@ -67,6 +70,9 @@ class Disk: Module { } } + submenu.addItem(NSMenuItem.separator()) + submenu.addItem(generateIntervalMenu()) + if active { menu.submenu = submenu } @@ -116,4 +122,72 @@ class Disk: Module { self.initMenu(active: true) self.active << true } + + func generateIntervalMenu() -> NSMenuItem { + let updateInterval = NSMenuItem(title: "Update interval", action: nil, keyEquivalent: "") + + let updateIntervals = NSMenu() + let updateInterval_1 = NSMenuItem(title: "1s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_1.state = self.updateInterval == 1 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_1.target = self + let updateInterval_2 = NSMenuItem(title: "3s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_2.state = self.updateInterval == 3 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_2.target = self + let updateInterval_3 = NSMenuItem(title: "5s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_3.state = self.updateInterval == 5 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_3.target = self + let updateInterval_4 = NSMenuItem(title: "10s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_4.state = self.updateInterval == 10 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_4.target = self + let updateInterval_5 = NSMenuItem(title: "15s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_5.state = self.updateInterval == 15 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_5.target = self + + updateIntervals.addItem(updateInterval_1) + updateIntervals.addItem(updateInterval_2) + updateIntervals.addItem(updateInterval_3) + updateIntervals.addItem(updateInterval_4) + updateIntervals.addItem(updateInterval_5) + + updateInterval.submenu = updateIntervals + + return updateInterval + } + + @objc func changeInterval(_ sender: NSMenuItem) { + var interval: Int = self.updateInterval + + switch sender.title { + case "1s": + interval = 1 + case "3s": + interval = 3 + case "5s": + interval = 5 + case "10s": + interval = 10 + case "15s": + interval = 15 + default: + break + } + + + if interval == self.updateInterval { + return + } + + for item in self.submenu.items { + if item.title == "Update interval" { + for subitem in item.submenu!.items { + subitem.state = NSControl.StateValue.off + } + } + } + + sender.state = NSControl.StateValue.on + self.updateInterval = interval + self.defaults.set(interval, forKey: "\(name)_interval") + self.reader.updateInterval << interval + } } diff --git a/Stats/Modules/Disk/DiskReader.swift b/Stats/Modules/Disk/DiskReader.swift index f7714c46..f4699c08 100644 --- a/Stats/Modules/Disk/DiskReader.swift +++ b/Stats/Modules/Disk/DiskReader.swift @@ -9,20 +9,25 @@ import Foundation class DiskReader: Reader { - var value: Observable<[Double]>! - var available: Bool = true - var updateTimer: Timer! + public var value: Observable<[Double]>! + public var updateInterval: Observable = Observable(0) + public var available: Bool = true + public var updateTimer: Timer! init() { self.value = Observable([]) read() + self.updateInterval.subscribe(observer: self) { (value, _) in + self.stop() + self.start() + } } func start() { if updateTimer != nil { return } - updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true) + updateTimer = Timer.scheduledTimer(timeInterval: TimeInterval(self.updateInterval.value), target: self, selector: #selector(read), userInfo: nil, repeats: true) } func stop() { diff --git a/Stats/Modules/Memory/Memory.swift b/Stats/Modules/Memory/Memory.swift index 8aac9238..6af5f343 100644 --- a/Stats/Modules/Memory/Memory.swift +++ b/Stats/Modules/Memory/Memory.swift @@ -22,6 +22,7 @@ class Memory: Module { public var tabInitialized: Bool = false public var tabView: NSTabViewItem = NSTabViewItem() public var chart: LineChartView = LineChartView() + public var updateInterval: Int private let defaults = UserDefaults.standard private var submenu: NSMenu = NSMenu() @@ -30,6 +31,8 @@ class Memory: Module { self.available = Observable(true) self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini + self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.integer(forKey: "\(name)_interval") : 3 + self.reader.updateInterval << self.updateInterval } func initMenu(active: Bool) { @@ -72,6 +75,9 @@ class Memory: Module { } } + submenu.addItem(NSMenuItem.separator()) + submenu.addItem(generateIntervalMenu()) + if active { menu.submenu = submenu } @@ -127,4 +133,72 @@ class Memory: Module { self.initMenu(active: true) self.active << true } + + func generateIntervalMenu() -> NSMenuItem { + let updateInterval = NSMenuItem(title: "Update interval", action: nil, keyEquivalent: "") + + let updateIntervals = NSMenu() + let updateInterval_1 = NSMenuItem(title: "1s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_1.state = self.updateInterval == 1 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_1.target = self + let updateInterval_2 = NSMenuItem(title: "3s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_2.state = self.updateInterval == 3 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_2.target = self + let updateInterval_3 = NSMenuItem(title: "5s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_3.state = self.updateInterval == 5 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_3.target = self + let updateInterval_4 = NSMenuItem(title: "10s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_4.state = self.updateInterval == 10 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_4.target = self + let updateInterval_5 = NSMenuItem(title: "15s", action: #selector(changeInterval), keyEquivalent: "") + updateInterval_5.state = self.updateInterval == 15 ? NSControl.StateValue.on : NSControl.StateValue.off + updateInterval_5.target = self + + updateIntervals.addItem(updateInterval_1) + updateIntervals.addItem(updateInterval_2) + updateIntervals.addItem(updateInterval_3) + updateIntervals.addItem(updateInterval_4) + updateIntervals.addItem(updateInterval_5) + + updateInterval.submenu = updateIntervals + + return updateInterval + } + + @objc func changeInterval(_ sender: NSMenuItem) { + var interval: Int = self.updateInterval + + switch sender.title { + case "1s": + interval = 1 + case "3s": + interval = 3 + case "5s": + interval = 5 + case "10s": + interval = 10 + case "15s": + interval = 15 + default: + break + } + + + if interval == self.updateInterval { + return + } + + for item in self.submenu.items { + if item.title == "Update interval" { + for subitem in item.submenu!.items { + subitem.state = NSControl.StateValue.off + } + } + } + + sender.state = NSControl.StateValue.on + self.updateInterval = interval + self.defaults.set(interval, forKey: "\(name)_interval") + self.reader.updateInterval << interval + } } diff --git a/Stats/Modules/Memory/MemoryReader.swift b/Stats/Modules/Memory/MemoryReader.swift index 3c85ce15..75fba7bb 100644 --- a/Stats/Modules/Memory/MemoryReader.swift +++ b/Stats/Modules/Memory/MemoryReader.swift @@ -16,6 +16,7 @@ struct MemoryUsage { class MemoryReader: Reader { public var value: Observable<[Double]>! + public var updateInterval: Observable = Observable(0) public var usage: Observable = Observable(MemoryUsage()) public var processes: Observable<[TopProcess]> = Observable([TopProcess]()) public var available: Bool = true @@ -49,13 +50,18 @@ class MemoryReader: Reader { } read() + + self.updateInterval.subscribe(observer: self) { (value, _) in + self.stop() + self.start() + } } func start() { if updateTimer != nil { return } - updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true) + updateTimer = Timer.scheduledTimer(timeInterval: TimeInterval(self.updateInterval.value), target: self, selector: #selector(read), userInfo: nil, repeats: true) if topProcess.isRunning { return diff --git a/Stats/Modules/Module.swift b/Stats/Modules/Module.swift index 9f0fd936..7ae0236a 100644 --- a/Stats/Modules/Module.swift +++ b/Stats/Modules/Module.swift @@ -24,6 +24,7 @@ protocol Module: class { var tabInitialized: Bool { get } var reader: Reader { get } + var updateInterval: Int { get } func start() func stop() diff --git a/Stats/Modules/Network/Network.swift b/Stats/Modules/Network/Network.swift index 35f7c10a..1002b124 100644 --- a/Stats/Modules/Network/Network.swift +++ b/Stats/Modules/Network/Network.swift @@ -20,6 +20,7 @@ class Network: Module { public var tabAvailable: Bool = false public var tabInitialized: Bool = false public var tabView: NSTabViewItem = NSTabViewItem() + public var updateInterval: Int private let defaults = UserDefaults.standard private var submenu: NSMenu = NSMenu() @@ -28,6 +29,8 @@ class Network: Module { self.available = Observable(self.reader.available) self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.NetworkDots + self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.integer(forKey: "\(name)_interval") : 3 + self.reader.updateInterval << self.updateInterval } func initTab() { diff --git a/Stats/Modules/Network/NetworkReader.swift b/Stats/Modules/Network/NetworkReader.swift index 4c04a347..4e205a6e 100644 --- a/Stats/Modules/Network/NetworkReader.swift +++ b/Stats/Modules/Network/NetworkReader.swift @@ -9,12 +9,13 @@ import Cocoa class NetworkReader: Reader { - var value: Observable<[Double]>! - var available: Bool = true - var updateTimer: Timer! + public var value: Observable<[Double]>! + public var updateInterval: Observable = Observable(0) + public var available: Bool = true + public var updateTimer: Timer! - var netProcess: Process = Process() - var pipe: Pipe = Pipe() + private var netProcess: Process = Process() + private var pipe: Pipe = Pipe() init() { self.value = Observable([]) diff --git a/Stats/Modules/Reader.swift b/Stats/Modules/Reader.swift index ae97568a..fe26bbf9 100644 --- a/Stats/Modules/Reader.swift +++ b/Stats/Modules/Reader.swift @@ -10,6 +10,7 @@ import Foundation protocol Reader { var value: Observable<[Double]>! { get } + var updateInterval: Observable { get } var available: Bool { get } var updateTimer: Timer! { get set }