diff --git a/common/Logger.esm.js b/common/Logger.esm.js new file mode 100644 index 0000000..831fab8 --- /dev/null +++ b/common/Logger.esm.js @@ -0,0 +1,67 @@ +/* + * This is a part of CPUFreq Manager + * Copyright (C) 2016-2019 konkor + * + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +export var LEVEL = { ERROR: 0, INFO: 1, DEBUG: 2 } + +//DOMAIN ERROR:0:RED, INFO:1:BLUE, DEBUG:2:GREEN +const domain_color = ["00;31","00;34","00;32"]; +const domain_name = ["EE","II","DD"]; +const domain_source = "application"; + +var debug_lvl = LEVEL.ERROR; +var mono = false; + +export function init (level, extension) { + level = level || 0; + debug_lvl = level; + if (extension) mono = true; +} + + + +export function info (source, msg) { + if (!msg) { + msg = source; + source = domain_source; + } + if (debug_lvl > 0) print_msg (1, source, msg); +} + +export function debug (source, msg) { + if (!msg) { + msg = source; + source = domain_source; + } + if (debug_lvl > 1) print_msg (2, source, msg); +} + +export function error (source, msg) { + if (!msg) { + msg = source; + source = domain_source; + } + print_msg (0, source, msg); +} + + + +function print_msg (domain, source, output) { + let d = new Date(); + let ds = d.toString (); + let i = ds.indexOf (" GMT"); + if (i > 0) ds = ds.substring (0, i); + + if (mono) print ("[%s.%s](%s) [cpufreq][%s] %s".format ( + ds,(d.getMilliseconds() / 1000).toFixed(3).slice(2, 5),domain_name[domain],source,output)); + else print ("\x1b[%sm[%s.%s](%s) [cpufreq][%s]\x1b[0m %s".format ( + domain_color[domain],ds,(d.getMilliseconds() / 1000).toFixed(3).slice(2, 5),domain_name[domain],source,output)); + log ("(%s) [cpufreq][%s] %s".format (domain_name[domain], source, output)); +} + + diff --git a/common/Preferences.js b/common/Preferences.js index ac9899a..b240d4e 100644 --- a/common/Preferences.js +++ b/common/Preferences.js @@ -17,7 +17,7 @@ const Lang = imports.lang; const APPDIR = getCurrentFile ()[1]; -const Prefs = imports.prefs; +const Prefs = imports.prefs_gjs; var Preferences = new Lang.Class ({ Name: 'Preferences', diff --git a/convenience.esm.js b/convenience.esm.js new file mode 100644 index 0000000..1c4aced --- /dev/null +++ b/convenience.esm.js @@ -0,0 +1,64 @@ +/* + * This is a part of CPUFreq Manager + * Copyright (C) 2016-2019 konkor + * + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +// import GLib from 'gi://GLib'; +// import Gio from 'gi://Gio'; + +// @deprecated use extension.getSettings() +export function getSettings (extension) { + // schema = schema || 'org.gnome.shell.extensions.cpufreq'; + // const GioSSS = Gio.SettingsSchemaSource; + // let schemaDir = Gio.File.new_for_path (getCurrentFile()[1] + '/schemas'); + // let schemaSource; + + // if (schemaDir.query_exists (null)) + // schemaSource = GioSSS.new_from_directory ( + // schemaDir.get_path (), GioSSS.get_default (), false + // ); + // else{ + // schemaSource = GioSSS.get_default (); + // } + // let schemaObj = schemaSource.lookup (schema, true); + // if (!schemaObj) + // throw new Error ('Schema ' + schema + ' could not be found for extension ' + + // 'cpufreq@konkor. Please check your installation.'); +// + // return new Gio.Settings ({ settings_schema: schemaObj }); + return extension.getSettings(); +} + +export function getCurrentFile () { + let stack = (new Error()).stack; + let stackLine = stack.split('\n')[1]; + if (!stackLine) + throw new Error ('Could not find current file'); + let match = new RegExp ('@(.+):\\d+').exec(stackLine); + if (!match) + throw new Error ('Could not find current file'); + let path = match[1]; + let file = Gio.File.new_for_path (path); + return [file.get_path(), file.get_parent().get_path(), file.get_basename()]; +} + +export function byteArrayToString (array) { + return array instanceof Uint8Array ? new TextDecoder().decode(array):array; +} + +export function get_cpu_number () { + let c = 0; + let cpulist = null; + let ret = GLib.spawn_command_line_sync ("cat /sys/devices/system/cpu/present"); + if (ret[0]) cpulist = byteArrayToString(ret[1]).toString().split("\n", 1)[0].split("-"); + cpulist.forEach ((f) => { + if (parseInt (f) > 0) c = parseInt (f); + }); + return c + 1; +} + diff --git a/cpufreq-preferences b/cpufreq-preferences index 3bfd01a..0a4659b 100755 --- a/cpufreq-preferences +++ b/cpufreq-preferences @@ -33,13 +33,13 @@ function getCurrentFile () { function get_appdir () { let s = getCurrentFile ()[1]; - if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; s = GLib.get_home_dir () + "/.local/share/gnome-shell/extensions/cpufreq@konkor"; - if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; s = "/usr/local/share/gnome-shell/extensions/cpufreq@konkor"; - if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; s = "/usr/share/gnome-shell/extensions/cpufreq@konkor"; - if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; throw "CPUFreq installation not found..."; return s; } diff --git a/debug.sh b/debug.sh new file mode 100755 index 0000000..de3e233 --- /dev/null +++ b/debug.sh @@ -0,0 +1,8 @@ +#!/bin/sh -e +reset +export G_MESSAGES_DEBUG=debug +export MUTTER_DEBUG_DUMMY_MODE_SPECS=1366x768 + +dbus-run-session -- \ + gnome-shell --nested \ + --wayland \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..cd11037 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,140 @@ +import js from '@eslint/js'; + +export default [ + js.configs.recommended, + { + languageOptions: { + globals: { + ARGV: 'readonly', + Debugger: 'readonly', + GIRepositoryGType: 'readonly', + globalThis: 'readonly', + imports: 'readonly', + Intl: 'readonly', + log: 'readonly', + logError: 'readonly', + pkg: 'readonly', + print: 'readonly', + printerr: 'readonly', + window: 'readonly', + TextEncoder: 'readonly', + TextDecoder: 'readonly', + console: 'readonly', + setTimeout: 'readonly', + setInterval: 'readonly', + clearTimeout: 'readonly', + clearInterval: 'readonly', + }, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + }, + rules: { + // See: https://eslint.org/docs/latest/rules/#possible-problems + 'array-callback-return': 'error', + 'no-await-in-loop': 'error', + 'no-constant-binary-expression': 'error', + 'no-constructor-return': 'error', + 'no-new-native-nonconstructor': 'error', + 'no-promise-executor-return': 'error', + 'no-self-compare': 'error', + 'no-template-curly-in-string': 'error', + 'no-unmodified-loop-condition': 'error', + 'no-unreachable-loop': 'error', + 'no-unused-private-class-members': 'error', + 'no-use-before-define': [ + 'error', + { + functions: false, + classes: true, + variables: true, + allowNamedExports: true, + }, + ], + // See: https://eslint.org/docs/latest/rules/#suggestions + 'block-scoped-var': 'error', + 'complexity': 'warn', + 'consistent-return': 'error', + 'default-param-last': 'error', + 'eqeqeq': 'error', + 'no-array-constructor': 'error', + 'no-caller': 'error', + 'no-extend-native': 'error', + 'no-extra-bind': 'error', + 'no-extra-label': 'error', + 'no-iterator': 'error', + 'no-label-var': 'error', + 'no-loop-func': 'error', + 'no-multi-assign': 'warn', + 'no-new-object': 'error', + 'no-new-wrappers': 'error', + 'no-proto': 'error', + 'no-shadow': 'warn', + 'no-unused-vars': [ + 'error', + { + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + }, + ], + 'no-var': 'warn', + 'unicode-bom': 'error', + // GJS Restrictions + 'no-restricted-globals': [ + 'error', + { + name: 'Debugger', + message: 'Internal use only', + }, + { + name: 'GIRepositoryGType', + message: 'Internal use only', + }, + { + name: 'log', + message: 'Use console.log()', + }, + { + name: 'logError', + message: 'Use console.warn() or console.error()', + }, + ], + 'no-restricted-properties': [ + 'error', + { + object: 'imports', + property: 'format', + message: 'Use template strings', + }, + { + object: 'pkg', + property: 'initFormat', + message: 'Use template strings', + }, + { + object: 'Lang', + property: 'copyProperties', + message: 'Use Object.assign()', + }, + { + object: 'Lang', + property: 'bind', + message: 'Use arrow notation or Function.prototype.bind()', + }, + { + object: 'Lang', + property: 'Class', + message: 'Use ES6 classes', + }, + ], + 'no-restricted-syntax': [ + 'error', + { + selector: 'MethodDefinition[key.name="_init"] CallExpression[arguments.length<=1][callee.object.type="Super"][callee.property.name="_init"]', + message: 'Use constructor() and super()', + }, + ], + }, + }, +]; \ No newline at end of file diff --git a/extension.js b/extension.js index 7522e2c..b02e1a8 100644 --- a/extension.js +++ b/extension.js @@ -8,21 +8,21 @@ * with this program. If not, see . */ -const Lang = imports.lang; -const GObject = imports.gi.GObject; -const GLib = imports.gi.GLib; -const Gio = imports.gi.Gio; -const St = imports.gi.St; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; - -const ExtensionUtils = imports.misc.extensionUtils; - -const Me = ExtensionUtils.getCurrentExtension (); -const Logger = Me.imports.common.Logger; -const Convenience = Me.imports.convenience; -const EXTENSIONDIR = Me.dir.get_path (); -const APP_PATH = EXTENSIONDIR + "/cpufreq-application"; +import * as Logger from './common/Logger.esm.js'; + +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; +import St from 'gi://St'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as Convenience from './convenience.esm.js'; + + +//const EXTENSIONDIR = Me.dir.get_path (); +let EXTENSIONDIR; +let APP_PATH; const SAVE_SETTINGS_KEY = 'save-settings'; const EXTENSION_MODE_KEY= 'extension-mode'; @@ -111,54 +111,42 @@ const CpufreqServiceIface = ' \ '; const CpufreqServiceProxy = Gio.DBusProxy.makeProxyWrapper (CpufreqServiceIface); -const CpuFreq = { - init: function () { - this.settings = Convenience.getSettings(); - this.on_settings (null, null); - - this.statusLabel = new St.Label ({ - text: title_text, y_expand: true, y_align: 2, style_class:'cpufreq-text' - }); - this.statusLabel.style = title_style; - let _box = new St.BoxLayout(); - _box.add_actor (this.statusLabel); - this.add_actor (_box); - this.connect ('button-press-event', () => { - var args = extmode ? "--extension" : ""; - if (splash) - if (!this.app_running) this.show_splash (); - if (!guid_battery || (guid_battery == this.guid)) this.launch_app (args); - else this.launch_app (args + " --no-save"); - }); - if (!monitor_timeout) this.statusLabel.set_text (this.get_title ()); - this.add_event (); +const FrequencyIndicator = GObject.registerClass({ +}, class FrequencyIndicator extends PanelMenu.Button { + settings; + proxy; - //TODO: Workaround updating title - this.settings.set_boolean (SAVE_SETTINGS_KEY, !save); - this.settings.set_boolean (SAVE_SETTINGS_KEY, save); + constructor(settings_input) { + super(0.0, "CPU Frequency Indicator", false); - if (settingsID) this.settings.disconnect (settingsID); - settingsID = this.settings.connect ("changed", this.on_settings.bind (this)); + this.settings = settings_input; + if (settings_input == undefined){ + console.error('settings_input is undefined'); + } + } - this.power = new PowerManagerProxy (Gio.DBus.system, UP_BUS_NAME, UP_OBJECT_PATH, (proxy, e) => { - if (e) { - error (e.message); - return; + on_power_state (state, percentage) { + let id = eprofiles[1].guid; + //debug ("on_power_state: %s %s%%".format (this.power.State, this.power.Percentage)); + debug ("on_power_state: %s %s%%".format (state, percentage)); + if (!id) return; + if (state == 2) { + //on battery + if (id == guid_battery) return; + if (percentage < eprofiles[1].percent) { + this.schedule_profile ('--no-save -p ' + id); + guid_battery = id; } - this.on_power_state (proxy.State, proxy.Percentage); - if (save && first_boot && !guid_battery) this.launch_app ("-p user"); - first_boot = false; - GLib.timeout_add (0, 8000, () => { - powerID = this.power.connect ('g-properties-changed', (o,a) => { - //a = a{sv} - this.on_power_state (this.power.State, this.power.Percentage); - }); - }); - }); - }, + } else { + //restoring prev state + if (guid_battery == this.guid) return; + this.schedule_profile ('-p user'); + guid_battery = this.guid; + } + } - on_settings: function (o, key) { + on_settings(o, key) { let s; o = o || this.settings; @@ -226,68 +214,103 @@ const CpuFreq = { //TODO: statusLabel if ((key == LABEL_KEY) && !monitor_timeout) this.statusLabel.set_text (this.get_title ()); - /*if ((key == "power-state") || (key == "power-percentage")) { - debug ("power-state changed..."); - this.on_power_state (o.get_uint ("power-state"), o.get_double ("power-percentage")); - }*/ - }, + } - on_power_state: function (state, percentage) { - let id = eprofiles[1].guid; - //debug ("on_power_state: %s %s%%".format (this.power.State, this.power.Percentage)); - debug ("on_power_state: %s %s%%".format (state, percentage)); - if (!id) return; - if (state == 2) { - //on battery - if (id == guid_battery) return; - if (percentage < eprofiles[1].percent) { - this.schedule_profile ('--no-save -p ' + id); - guid_battery = id; - } - } else { - //restoring prev state - if (guid_battery == this.guid) return; - this.schedule_profile ('-p user'); - guid_battery = this.guid; - } - }, + init () { + this.on_settings (null, null); - unschedule_profile: function () { - GLib.source_remove (scheduleID); - scheduleID = 0; - }, + this.statusLabel = new St.Label ({ + text: title_text, y_expand: true, y_align: 2, style_class:'cpufreq-text' + }); + this.statusLabel.style = title_style; + let _box = new St.BoxLayout(); + _box.add_actor (this.statusLabel); + this.add_actor (_box); + this.connect ('button-press-event', () => { + var args = extmode ? "--extension" : ""; + if (splash) + if (!this.app_running) this.show_splash (); + if (!guid_battery || (guid_battery == this.guid)) this.launch_app (args); + else this.launch_app (args + " --no-save"); + }); + if (!monitor_timeout) this.statusLabel.set_text (this.get_title ()); - schedule_profile: function (options) { - if (scheduleID) this.unschedule_profile (); - scheduleID = GLib.timeout_add (0, 5000, () => { - this.launch_app (options); - scheduleID = 0; + this.add_event (); + + //TODO: Workaround updating title + this.settings.set_boolean (SAVE_SETTINGS_KEY, !save); + this.settings.set_boolean (SAVE_SETTINGS_KEY, save); + + if (settingsID) {this.settings.disconnect (settingsID);} + settingsID = this.settings.connect ("changed", this.on_settings.bind (this)); + + this.power = new PowerManagerProxy (Gio.DBus.system, UP_BUS_NAME, UP_OBJECT_PATH, (proxy, e) => { + if (e) { + error (e.message); + return; + } + this.on_power_state (proxy.State, proxy.Percentage); + if (save && first_boot && !guid_battery) this.launch_app ("-p user"); + first_boot = false; + GLib.timeout_add (0, 8000, () => { + powerID = this.power.connect ('g-properties-changed', (o,a) => { + //a = a{sv} + this.on_power_state (this.power.State, this.power.Percentage); + }); + }); }); - }, + } - launch_app: function (options) { - let extra = ""; - /*if (Logger.debug_lvl == 2) extra = " --debug"; - else if (Logger.debug_lvl == 1) extra = " --verbose";*/ - options = options || ""; - info ("launch_app " + options + extra); - GLib.spawn_command_line_async ("%s %s".format (APP_PATH, options + extra)); - }, + remove_proxy() { + if (this.proxy) { + if (event) this.proxy.disconnectSignal (event); + if (event_style) this.proxy.disconnectSignal (event_style); + delete this.proxy; + } + this.proxy = null; + event = 0; + event_style = 0; + } - get app_running () { - let res = GLib.spawn_command_line_sync ("ps -A"); - let o, n; - if (res[0]) o = Convenience.byteArrayToString (res[1]).toString().split("\n"); - for (let i = 0; i < o.length; i++) { - if (o[i].indexOf ("cpufreq-app") > -1) { - n = parseInt (o[i].trim().split(" ")[0]); - if (Number.isInteger(n) && n > 0) return n; + remove_events () { + this.remove_proxy (); + if (settingsID) this.settings.disconnect (settingsID); + if (powerID) this.power.disconnect (powerID); + if (monitor_event) GLib.source_remove (monitor_event); + event = 0; monitor_event = 0; + settingsID = 0; powerID = 0; + //GLib.spawn_command_line_async ("killall cpufreq-service"); + } + + add_event () { + this.remove_proxy (); + if (monitor_timeout > 0) { + if (!GLib.spawn_command_line_async (EXTENSIONDIR + "/cpufreq-service")) { + console.error ("Unable to start cpufreq service..."); + return; } + this.proxy = new CpufreqServiceProxy (Gio.DBus.session, BUS_NAME, OBJECT_PATH, (proxy, e) => { + if (e) { + error (e.message); + return; + } + event = this.proxy.connectSignal ('MonitorEvent', (o, s, metrics) => { + if (metrics) this.statusLabel.set_text (this.get_title (metrics.toString ())); + }); + event_style = this.proxy.connectSignal ('StyleChanged', (o, s, style) => { + if (style) { + title_style = style.toString (); + this.statusLabel.style = title_style; + } + }); + }); } - return 0; - }, + monitor_event = 0; + // cpufreq-service should stop auto on disabled monitors + //else GLib.spawn_command_line_async ("killall cpufreq-service"); + } - get_title: function (text) { + get_title (text) { if (!text) return title_text; let metrics = JSON.parse (text), s = "", f = 0, units; if (frequency_show) { @@ -318,9 +341,42 @@ const CpuFreq = { this.statusLabel.style = title_style; } return title_text; - }, + } + + launch_app (options) { + let extra = ""; + options = options || ""; + info ("launch_app " + options + extra); + GLib.spawn_command_line_async ("%s %s".format (APP_PATH, options + extra)); + } + + unschedule_profile() { + GLib.source_remove (scheduleID); + scheduleID = 0; + } - get_governor_symbolyc: function (name) { + schedule_profile (options) { + if (scheduleID) {this.unschedule_profile ();} + scheduleID = GLib.timeout_add (0, 5000, () => { + this.launch_app (options); + scheduleID = 0; + }); + } + + get app_running () { + let res = GLib.spawn_command_line_sync ("ps -A"); + let o, n; + if (res[0]) o = Convenience.byteArrayToString (res[1]).toString().split("\n"); + for (let i = 0; i < o.length; i++) { + if (o[i].indexOf ("cpufreq-app") > -1) { + n = parseInt (o[i].trim().split(" ")[0]); + if (Number.isInteger(n) && n > 0) return n; + } + } + return 0; + } + + get_governor_symbolyc (name) { let g = name; if (g == "mixed") g = "\u25cd"; else if (g == "powersave") g = "\uf06c"; @@ -331,16 +387,16 @@ const CpuFreq = { else if (g == "userspace") g = "\uf007"; else g = "\uf0e7"; return g; - }, + } - get_state_symbolyc: function (state) { + get_state_symbolyc (state) { let g = "☺"; if (state == 1) g = ""; else if (state == 2) g = "☹"; return g; - }, + } - get_stylestring: function (state) { + get_stylestring (state) { let s; if (color_show_custom) state += 3; switch (state) { @@ -366,58 +422,9 @@ const CpuFreq = { s = ""; } return s; - }, - - add_event: function () { - this.remove_proxy (); - if (monitor_timeout > 0) { - if (!GLib.spawn_command_line_async (EXTENSIONDIR + "/cpufreq-service")) { - //error ("Unable to start cpufreq service..."); - return; - } - this.proxy = new CpufreqServiceProxy (Gio.DBus.session, BUS_NAME, OBJECT_PATH, (proxy, e) => { - if (e) { - error (e.message); - return; - } - event = this.proxy.connectSignal ('MonitorEvent', (o, s, metrics) => { - if (metrics) this.statusLabel.set_text (this.get_title (metrics.toString ())); - }); - event_style = this.proxy.connectSignal ('StyleChanged', (o, s, style) => { - if (style) { - title_style = style.toString (); - this.statusLabel.style = title_style; - } - }); - }); - } - monitor_event = 0; - // cpufreq-service should stop auto on disabled monitors - //else GLib.spawn_command_line_async ("killall cpufreq-service"); - }, - - remove_proxy: function () { - if (this.proxy) { - if (event) this.proxy.disconnectSignal (event); - if (event_style) this.proxy.disconnectSignal (event_style); - delete this.proxy; - } - this.proxy = null; - event = 0; - event_style = 0; - }, - - remove_events: function () { - this.remove_proxy (); - if (settingsID) this.settings.disconnect (settingsID); - if (powerID) this.power.disconnect (powerID); - if (monitor_event) GLib.source_remove (monitor_event); - event = 0; monitor_event = 0; - settingsID = 0; powerID = 0; - //GLib.spawn_command_line_async ("killall cpufreq-service"); - }, + } - show_splash: function () { + show_splash () { let monitor = Main.layoutManager.focusMonitor; let height = monitor.height < monitor.width ? monitor.height : monitor.width; let width = 512 * height / 1200; @@ -428,90 +435,68 @@ const CpuFreq = { splash.set_position (Math.floor (monitor.width / 2 - splash.width / 2), Math.floor (monitor.height / 2 - splash.height / 2)); - - if (splash.ease) splash.ease ({ + var that = this; + if (splash.ease) { + splash.ease ({ opacity: 20, mode: 8, duration: 1200, - onComplete: () => { remove_actor (splash)} - }); else GLib.timeout_add (0, 1200, () => { return remove_actor (splash)}); - } -}; - -let FrequencyIndicator = null; - -try { - FrequencyIndicator = GObject.registerClass({}, class FrequencyIndicator extends PanelMenu.Button { - _init() { - super._init (0.0, "CPU Frequency Indicator", false); - - this.on_settings = CpuFreq.on_settings.bind (this); - this.on_power_state = CpuFreq.on_power_state.bind (this); - this.unschedule_profile = CpuFreq.unschedule_profile.bind (this); - this.schedule_profile = CpuFreq.schedule_profile.bind (this); - this.launch_app = CpuFreq.launch_app.bind (this); - this.get_title = CpuFreq.get_title.bind (this); - this.get_governor_symbolyc = CpuFreq.get_governor_symbolyc.bind (this); - this.get_state_symbolyc = CpuFreq.get_state_symbolyc.bind (this); - this.get_stylestring = CpuFreq.get_stylestring.bind (this); - this.add_event = CpuFreq.add_event.bind (this); - this.remove_proxy = CpuFreq.remove_proxy.bind (this); - this.remove_events = CpuFreq.remove_events.bind (this); - this.show_splash = CpuFreq.show_splash.bind (this); - - CpuFreq.init.bind (this) (); + onComplete: function () { that.remove_actor (splash);} + }); + }else + { + GLib.timeout_add (0, 1200, function () { return that.remove_actor (splash)}); } - }); -} catch (error) { - log ('Gnome Shell version < 40!', error); - - FrequencyIndicator = new Lang.Class({ - Name: 'CpuFreq', - Extends: PanelMenu.Button, - - _init: function() { - this.parent (0.0, "CPU Frequency Indicator", false); - - this.on_settings = CpuFreq.on_settings.bind (this); - this.on_power_state = CpuFreq.on_power_state.bind (this); - this.unschedule_profile = CpuFreq.unschedule_profile.bind (this); - this.schedule_profile = CpuFreq.schedule_profile.bind (this); - this.launch_app = CpuFreq.launch_app.bind (this); - this.get_title = CpuFreq.get_title.bind (this); - this.get_governor_symbolyc = CpuFreq.get_governor_symbolyc.bind (this); - this.get_state_symbolyc = CpuFreq.get_state_symbolyc.bind (this); - this.get_stylestring = CpuFreq.get_stylestring.bind (this); - this.add_event = CpuFreq.add_event.bind (this); - this.remove_proxy = CpuFreq.remove_proxy.bind (this); - this.remove_events = CpuFreq.remove_events.bind (this); - this.show_splash = CpuFreq.show_splash.bind (this); - - CpuFreq.init.bind (this) (); - } - }); -} + } -function remove_actor (o) { - Main.uiGroup.remove_actor (o); - o.destroy (); - return false; + remove_actor (o) { + Main.uiGroup.remove_actor (o); + o.destroy (); + return false; + } + + show_notify (message, style) { + //var text = new St.Label ({text: message, style_class: style?style:'cpufreq-notify'}); + var text = new St.Label ({text: message, style_class: "modal-dialog audio-selection-content restart-message"}); + text.opacity = 255; + Main.uiGroup.add_actor (text); + + text.set_position (Math.floor (Main.layoutManager.primaryMonitor.width / 2 - text.width / 2), + Math.floor (Main.layoutManager.primaryMonitor.height / 2 - text.height / 2)); + + GLib.timeout_add (0, 1200, () => { return remove_actor (text)}); + } + + show_warn (message) { + show_notify (message, "warn-label"); + } } +); -function show_notify (message, style) { - //var text = new St.Label ({text: message, style_class: style?style:'cpufreq-notify'}); - var text = new St.Label ({text: message, style_class: "modal-dialog audio-selection-content restart-message"}); - text.opacity = 255; - Main.uiGroup.add_actor (text); +export default class CpuFreq extends Extension { + constructor(metadata) { + super(metadata); - text.set_position (Math.floor (Main.layoutManager.primaryMonitor.width / 2 - text.width / 2), - Math.floor (Main.layoutManager.primaryMonitor.height / 2 - text.height / 2)); + this.initTranslations(); + } - GLib.timeout_add (0, 1200, () => { return remove_actor (text)}); -} + enable() { + EXTENSIONDIR = this.path; + APP_PATH = EXTENSIONDIR + "/cpufreq-application"; + console.log(_('Enabling "%s" dir: "%s"').format(this.metadata.name, EXTENSIONDIR)); + this.monitor = new FrequencyIndicator(this.getSettings()); + this.monitor.init(); + Main.panel.addToStatusArea ('cpufreq-indicator'/*this.uuid*/, this.monitor); + } + + disable() { + console.log(_('Disabling %s').format(this.metadata.name)); + this.monitor?.remove_events (); + this.monitor?.destroy (); + this.monitor = null; + } -function show_warn (message) { - show_notify (message, "warn-label"); } -let monitor; + Logger.init (Logger.LEVEL.ERROR, true); function info (msg) { @@ -525,17 +510,3 @@ function debug (msg) { function error (msg) { Logger.error ("extension", msg); } - -function init () { -} - -function enable () { - monitor = new FrequencyIndicator (); - Main.panel.addToStatusArea ('cpufreq-indicator', monitor); -} - -function disable () { - monitor.remove_events (); - monitor.destroy (); - monitor = null; -} diff --git a/metadata.json b/metadata.json index 707b9be..d4dd59b 100644 --- a/metadata.json +++ b/metadata.json @@ -3,9 +3,10 @@ "name": "cpufreq", "settings-schema": "org.gnome.shell.extensions.cpufreq", "shell-version": [ - "3.14","3.16","3.18","3.20","3.22","3.24","3.26","3.28","3.30","3.32","3.34","3.36","3.38","40","41","42","43","44" + "45" ], "url": "https://github.com/konkor/cpufreq", "uuid": "cpufreq@konkor", - "version": 54 + "gettext-domain": "org-konkor-cpufreq", + "version": 55 } diff --git a/metadata.json.in b/metadata.json.in index 99fe4d7..124f736 100644 --- a/metadata.json.in +++ b/metadata.json.in @@ -3,9 +3,10 @@ "name": "cpufreq", "settings-schema": "org.gnome.shell.extensions.cpufreq", "shell-version": [ - "3.14","3.16","3.18","3.20","3.22","3.24","3.26","3.28","3.30","3.32","3.34","3.36","3.38","40","41","42","43","44" + "45" ], "url": "https://github.com/konkor/cpufreq", "uuid": "cpufreq@konkor", + "gettext-domain": "org-konkor-cpufreq", "version": @VERSION@ } diff --git a/prefs.js b/prefs.js index b6f366d..bc43dae 100644 --- a/prefs.js +++ b/prefs.js @@ -8,19 +8,17 @@ * with this program. If not, see . */ -const Lang = imports.lang; -const GObject = imports.gi.GObject; -const GLib = imports.gi.GLib; -const Gio = imports.gi.Gio; -const Gtk = imports.gi.Gtk; -const Gdk = imports.gi.Gdk; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; -var Format = imports.format; -String.prototype.format = Format.format; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; +import Gtk from 'gi://Gtk'; +import Gdk from 'gi://Gdk'; -const APPDIR = get_appdir (); -imports.searchPath.unshift(APPDIR); -const Logger = imports.common.Logger; +//const APPDIR = get_appdir (); +const APPDIR = './'; + +import * as Logger from './common/Logger.esm.js'; const SAVE_SETTINGS_KEY = 'save-settings'; const NOTIFY_KEY = 'notifications'; @@ -41,12 +39,8 @@ const COLOR_SHOW_CUSTOM_NORMAL_KEY = 'color-show-custom-normal'; const COLOR_SHOW_CUSTOM_WARNING_KEY = 'color-show-custom-warning'; const COLOR_SHOW_CUSTOM_CRITICAL_KEY = 'color-show-custom-critical'; -const Gettext = imports.gettext.domain ('org-konkor-cpufreq'); -const _ = Gettext.gettext; -const EXTENSIONDIR = getCurrentFile ()[1]; -imports.searchPath.unshift (EXTENSIONDIR); -const Convenience = imports.convenience; +import * as Convenience from './convenience.esm.js'; var EventType = { CHARGING: 0, @@ -86,10 +80,8 @@ let eprofiles = [ let settings = false; -var CPUFreqPreferences = new Lang.Class({ - Name: 'CPUFreqPreferences', - - _init: function () { +var CPUFreqPreferences =GObject.registerClass({}, class CPUFreqPreferences{ + constructor() { this.parent (0.0, "CPUFreq Preferences", false); let label, s; diff --git a/prefs_gjs.js b/prefs_gjs.js new file mode 100644 index 0000000..c55e2b4 --- /dev/null +++ b/prefs_gjs.js @@ -0,0 +1,550 @@ +/* + * This is a part of CPUFreq Manager + * Copyright (C) 2016-2019 konkor + * + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +const Lang = imports.lang; +const GObject = imports.gi.GObject; +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; +const Gtk = imports.gi.Gtk; +const Gdk = imports.gi.Gdk; + +var Format = imports.format; +String.prototype.format = Format.format; + +const APPDIR = get_appdir (); +imports.searchPath.unshift(APPDIR); +const Logger = imports.common.Logger; + +const SAVE_SETTINGS_KEY = 'save-settings'; +const NOTIFY_KEY = 'notifications'; +const DARK_THEME_KEY = 'dark-theme'; +const PROFILES_KEY = 'profiles'; +const EPROFILES_KEY = 'event-profiles'; +const MONITOR_KEY = 'monitor'; +const LABEL_KEY = 'label'; +const LABEL_SHOW_KEY = 'label-show'; +const UNITS_SHOW_KEY = 'units-show'; +const LOAD_SHOW_KEY = 'load-show'; +const GOVS_SHOW_KEY = 'governors-show'; +const FREQ_SHOW_KEY = 'frequency-show'; + +const COLOR_SHOW_KEY = 'color-show'; +const COLOR_SHOW_CUSTOM_KEY = 'color-show-custom'; +const COLOR_SHOW_CUSTOM_NORMAL_KEY = 'color-show-custom-normal'; +const COLOR_SHOW_CUSTOM_WARNING_KEY = 'color-show-custom-warning'; +const COLOR_SHOW_CUSTOM_CRITICAL_KEY = 'color-show-custom-critical'; + +const Gettext = imports.gettext.domain ('org-konkor-cpufreq'); +const _ = Gettext.gettext; + +const EXTENSIONDIR = getCurrentFile ()[1]; +imports.searchPath.unshift (EXTENSIONDIR); +const Convenience = imports.convenience; + +var EventType = { +CHARGING: 0, +DISCHARGING: 1 +}; + +const suggestions = ["☃","⚡","㎒","㎓","","","","","","","","CPU"]; + +let save = false; +let dark = false; +let profiles = []; +let monitor_timeout = 500; +let label_text = "\u269b"; +let label_show = false; +let frequency_show = true; +let governor_show = false; +let load_show = false; +let units_show = true; +let system_notifications = false; + +let auto_profiles = [ + {name:_("Battery"), guid:"battery"}, + {name:_("Balanced"), guid:"balanced"}, + {name:_("High Performance"), guid:"performance"} +]; + +let color_show = false; +let color_show_custom = false; +let color_show_custom_normal = '#ebebeb'; +let color_show_custom_warning = '#ebebeb'; +let color_show_custom_critical = '#ff0000'; + +let eprofiles = [ + {percent:0, event:EventType.CHARGING, guid:""}, + {percent:100, event:EventType.DISCHARGING, guid:""} +]; + +let settings = false; + +var CPUFreqPreferences = new Lang.Class({ + Name: 'CPUFreqPreferences', + + _init: function () { + this.parent (0.0, "CPUFreq Preferences", false); + let label, s; + + settings = Convenience.getSettings (); + save = settings.get_boolean (SAVE_SETTINGS_KEY); + dark = settings.get_boolean (DARK_THEME_KEY); + monitor_timeout = settings.get_int (MONITOR_KEY); + label_text = settings.get_string (LABEL_KEY); + label_show = settings.get_boolean (LABEL_SHOW_KEY); + load_show = settings.get_boolean (LOAD_SHOW_KEY); + governor_show = settings.get_boolean (GOVS_SHOW_KEY); + frequency_show = settings.get_boolean (FREQ_SHOW_KEY); + units_show = settings.get_boolean (UNITS_SHOW_KEY); + system_notifications = settings.get_boolean (NOTIFY_KEY); + + color_show = settings.get_boolean (COLOR_SHOW_KEY); + color_show_custom = settings.get_boolean (COLOR_SHOW_CUSTOM_KEY); + color_show_custom_normal = settings.get_string (COLOR_SHOW_CUSTOM_NORMAL_KEY); + color_show_custom_warning = settings.get_string (COLOR_SHOW_CUSTOM_WARNING_KEY); + color_show_custom_critical = settings.get_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY); + + s = settings.get_string (EPROFILES_KEY); + if (s) try { + eprofiles = JSON.parse (s); + } catch (e) { + Logger.error ("%s\nPARSING DATA: %s".format (e.message, s)); + } + s = settings.get_string (PROFILES_KEY); + if (s) try { + profiles = JSON.parse (s); + } catch (e) { + Logger.error ("%s\nPARSING DATA: %s".format (e.message, s)); + } + + this.notebook = new Gtk.Notebook ({expand:true}); + let cssp = get_css_provider (); + if (cssp) { + Gtk.StyleContext.add_provider_for_screen ( + this.notebook.get_screen(), cssp, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + } + + this.general = new PageGeneralCPUFreq (); + this.notebook.add (this.general); + label = new Gtk.Label ({label: _("General")}); + this.notebook.set_tab_label (this.general, label); + + this.monitor_page = new PageMonitorCPUFreq (); + this.notebook.add (this.monitor_page); + label = new Gtk.Label ({label: _("Monitor")}); + this.notebook.set_tab_label (this.monitor_page, label); + + this.power = new PagePowerCPUFreq (); + this.notebook.add (this.power); + label = new Gtk.Label ({label: _("Power Events")}); + this.notebook.set_tab_label (this.power, label); + + this.notebook.show_all (); + } +}); + + +var PageGeneralCPUFreq = new Lang.Class({ + Name: 'PageGeneralCPUFreq', + Extends: Gtk.Box, + + _init: function () { + this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6}); + this.border_width = 6; + + this.add (new Gtk.Label ({label: "" + _("System") + (""), use_markup:true, xalign:0, margin_top:8})); + this.cb_startup = Gtk.CheckButton.new_with_label (_("Remember settings")); + this.cb_startup.tooltip_text = _("Check to restore settings on startup"); + this.cb_startup.margin = 6; + this.add (this.cb_startup); + this.cb_startup.active = save; + this.cb_startup.connect ('toggled', () => { + save = this.cb_startup.active; + settings.set_boolean (SAVE_SETTINGS_KEY, save); + }); + + this.cb_notify = Gtk.CheckButton.new_with_label (_("Notifications")); + this.cb_notify.tooltip_text = _("Show System Notifications on Critical States"); + this.cb_notify.margin = 6; + this.add (this.cb_notify); + this.cb_notify.active = system_notifications; + this.cb_notify.connect ('toggled', () => { + system_notifications = this.cb_notify.active; + settings.set_boolean (NOTIFY_KEY, system_notifications); + }); + + this.add (new Gtk.Label ({label: _("Extension"), use_markup:true, xalign:0, margin_top:12})); + this.cb_mode = Gtk.CheckButton.new_with_label (_("Extension mode")); + this.cb_mode.tooltip_text = _("Run main application without window decorations"); + this.cb_mode.margin = 6; + this.add (this.cb_mode); + this.cb_mode.active = settings.get_boolean ("extension-mode");; + this.cb_mode.connect ('toggled', () => { + settings.set_boolean ("extension-mode", this.cb_mode.active); + }); + this.cb_splash = Gtk.CheckButton.new_with_label (_("Splash Screen")); + this.cb_splash.tooltip_text = _("Show a splash screen on selecting main application"); + this.cb_splash.margin = 6; + this.add (this.cb_splash); + this.cb_splash.active = settings.get_boolean ("show-splash");; + this.cb_splash.connect ('toggled', () => { + settings.set_boolean ("show-splash", this.cb_splash.active); + }); + + this.add (new Gtk.Label ({label: _("User Interface"), use_markup:true, xalign:0, margin_top:12})); + this.cb_dark = Gtk.CheckButton.new_with_label (_("Dark theme")); + this.cb_dark.tooltip_text = _("Prefer dark theme"); + this.cb_dark.margin = 6; + this.add (this.cb_dark); + this.cb_dark.active = dark; + this.cb_dark.connect ('toggled', () => { + dark = this.cb_dark.active; + settings.set_boolean (DARK_THEME_KEY, dark); + }); + + this.show_all (); + } +}); + +var PageMonitorCPUFreq = new Lang.Class({ + Name: 'PageMonitorCPUFreq', + Extends: Gtk.Box, + + _init: function () { + this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6}); + let id = 0, i = 0, rb; + this.border_width = 6; + + let hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8}); + this.pack_start (hbox, false, false, 0); + hbox.add (new Gtk.Label ({label: _("Monitoring Interval (ms)")})); + this.timeout = Gtk.SpinButton.new_with_range (0, 1000000, 50); + this.timeout.tooltip_text = _("1000ms - default, 0 - disable"); + this.timeout.value = monitor_timeout; + this.timeout.connect ('value_changed', () => { + monitor_timeout = this.timeout.value; + settings.set_int (MONITOR_KEY, monitor_timeout); + }); + hbox.pack_end (this.timeout, false, false, 0); + + hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:6, margin_left:32}); + this.pack_start (hbox, false, false, 0); + hbox.pack_start (new Gtk.Label ({label: _("Show"), xalign:0.0}), false, false, 0); + + let cb_units = Gtk.CheckButton.new_with_label (_("Frequency")); + cb_units.tooltip_text = _("Monitor frequency"); + cb_units.margin_start = 32; + cb_units.active = frequency_show; + hbox.pack_start (cb_units, true, true, 8); + cb_units.connect ('toggled', (o) => { + frequency_show = o.active; + settings.set_boolean (FREQ_SHOW_KEY, frequency_show); + }); + + cb_units = Gtk.CheckButton.new_with_label (_("Governors")); + cb_units.tooltip_text = _("Monitor governors"); + cb_units.active = governor_show; + hbox.pack_start (cb_units, true, true, 8); + cb_units.connect ('toggled', (o) => { + governor_show = o.active; + settings.set_boolean (GOVS_SHOW_KEY, governor_show); + }); + + cb_units = Gtk.CheckButton.new_with_label (_("Loading")); + cb_units.tooltip_text = _("Monitor system loading"); + cb_units.active = load_show; + hbox.pack_start (cb_units, true, true, 8); + cb_units.connect ('toggled', (o) => { + load_show = o.active; + settings.set_boolean (LOAD_SHOW_KEY, load_show); + }); + + this.cb_units = Gtk.CheckButton.new_with_label (_("Show Measurement Units")); + this.cb_units.tooltip_text = _("Show measurement units for frequencies"); + this.cb_units.margin = 6; + this.add (this.cb_units); + this.cb_units.active = units_show; + this.cb_units.connect ('toggled', (o) => { + units_show = o.active; + settings.set_boolean (UNITS_SHOW_KEY, units_show); + }); + + this.cb_label = Gtk.CheckButton.new_with_label (_("Show Custom Label")); + this.cb_label.tooltip_text = _("Always show the custom label"); + this.cb_label.margin = 6; + this.add (this.cb_label); + this.cb_label.active = label_show; + this.cb_label.connect ('toggled', (o) => { + label_show = o.active; + settings.set_boolean (LABEL_SHOW_KEY, label_show); + }); + + hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8}); + this.pack_start (hbox, false, false, 0); + hbox.add (new Gtk.Label ({label: _("Custom label when monitoring disabled")})); + this.store = new Gtk.ListStore (); + this.store.set_column_types ([GObject.TYPE_STRING]); + this.completion = new Gtk.EntryCompletion (); + this.completion.minimum_key_length = 0; + this.completion.set_model (this.store); + this.completion.set_text_column (0); + suggestions.forEach ( l => { + this.store.set (this.store.append (), [0], [l]); + }); + + this.label = new Gtk.Entry (); + this.label.set_completion (this.completion); + this.label.get_style_context().add_class ("cpufreq-text"); + this.label.tooltip_text = _("Label or just a symbol to show when monitor disabled"); + this.label.set_text (label_text); + this.label.connect ('changed', (o) => { + var s = o.text; + settings.set_string (LABEL_KEY, s); + }); + + hbox.pack_end (this.label, false, false, 0); + + hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:6}); + this.pack_start (hbox, false, false, 0); + this.cb_color = Gtk.CheckButton.new_with_label (_("Use color")); + this.cb_color.tooltip_text = _("Colorful Monitor's title depending on warning state"); + this.cb_color.active = color_show; + hbox.pack_start (this.cb_color, true, true, 0); + this.cb_color.connect ('toggled', (o) => { + color_show = o.active; + settings.set_boolean (COLOR_SHOW_KEY, color_show); + this.colorbox.sensitive = color_show && color_show_custom; + }); + rb = Gtk.RadioButton.new_with_label_from_widget (null, _("Default colors")); + rb.active = !settings.get_boolean (COLOR_SHOW_CUSTOM_KEY); + rb.id = 0; + hbox.pack_start(rb, true, true, 8); + rb.connect ('toggled', (o) => { + color_show_custom = !o.active; + settings.set_boolean (COLOR_SHOW_CUSTOM_KEY, color_show_custom); + }); + rb = Gtk.RadioButton.new_with_label_from_widget (rb, _("Custom colors")); + rb.active = settings.get_boolean (COLOR_SHOW_CUSTOM_KEY); + rb.id = 1; + hbox.pack_start (rb, true, true, 8); + rb.connect ('toggled', (o) => { + color_show_custom = o.active; + settings.set_boolean (COLOR_SHOW_CUSTOM_KEY, color_show_custom); + this.colorbox.sensitive = color_show && color_show_custom; + }); + + this.colorbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8}); + this.pack_start (this.colorbox, false, false, 0); + + this.colorbox.add (new Gtk.Label ({label: _("Normal")})); + let [ ,color] = Gdk.Color.parse (color_show_custom_normal); + this.color_normal = Gtk.ColorButton.new_with_color (color); + this.color_normal.connect ('color-set', (o) => { + settings.set_string (COLOR_SHOW_CUSTOM_NORMAL_KEY, this.color_string (o.rgba)); + }); + this.colorbox.pack_start (this.color_normal, true, false, 0); + + this.colorbox.add (new Gtk.Label ({label: _("Warning")})); + [ ,color] = Gdk.Color.parse (color_show_custom_warning); + this.color_warning = Gtk.ColorButton.new_with_color (color); + this.color_warning.connect ('color-set', (o) => { + settings.set_string (COLOR_SHOW_CUSTOM_WARNING_KEY, this.color_string (o.rgba)); + }); + this.colorbox.pack_start (this.color_warning, true, false, 0); + + this.colorbox.add (new Gtk.Label ({label: _("Critical")})); + [ ,color] = Gdk.Color.parse (color_show_custom_critical); + this.color_critical = Gtk.ColorButton.new_with_color (color); + this.color_critical.connect ('color-set', (o) => { + settings.set_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY, this.color_string (o.rgba)); + }); + this.colorbox.pack_start (this.color_critical, true, false, 0); + this.colorbox.sensitive = color_show && color_show_custom; + + this.show_all (); + }, + + color_string: function (rgba) { + let s = "#%02x%02x%02x".format ( + this.scale_round (rgba.red), + this.scale_round (rgba.green), + this.scale_round (rgba.blue) + ); + return s; + }, + + scale_round: function (val) { + val = Math.floor (val * 255 + 0.5); + val = Math.max (val, 0); + val = Math.min (val, 255); + return val; + } +}); + +var PagePowerCPUFreq = new Lang.Class({ + Name: 'PagePowerCPUFreq', + Extends: Gtk.Box, + + _init: function () { + this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6}); + this.border_width = 6; + + this.unplug = new PowerProfile (eprofiles[EventType.DISCHARGING], + _("On Battery"), + _("You can set less than 100% of the battery level. ") + + _("It will do not apply \"Powersaving Profile\" immediately on the event. ") + + _("It could be helpful on temporary disconnections, issues with a power connector, etc.") + ); + this.add (this.unplug); + this.unplug.combo.connect ('changed', (o) => { + if (o.active == 0) + eprofiles[EventType.DISCHARGING].guid = ""; + else if (o.active <= auto_profiles.length) + eprofiles[EventType.DISCHARGING].guid = auto_profiles[o.active - 1].guid; + else + eprofiles[EventType.DISCHARGING].guid = profiles[o.active - auto_profiles.length - 1].guid; + //this.unplug.slider.set_value (100); + settings.set_string (EPROFILES_KEY, JSON.stringify (eprofiles)); + }); + this.unplug.slider.connect ('value_changed', (o) => { + eprofiles[EventType.DISCHARGING].percent = Math.round (o.get_value ()); + settings.set_string (EPROFILES_KEY, JSON.stringify (eprofiles)); + }); + + this.show_all (); + } +}); + +var PowerProfile = new Lang.Class({ + Name: 'PowerProfile', + Extends: Gtk.Box, + + _init: function (profile, text, tooltip) { + this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6}); + this.tooltip_text = tooltip; + this.border_width = 6; + let id = 0, i = 1; + + let hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL}); + this.pack_start (hbox, false, false, 0); + hbox.add (new Gtk.Label ({label:""+text+"",use_markup:true,xalign:0})); + this.combo = new Gtk.ComboBoxText (); + this.combo.tooltip_text = _("Power Profile"); + this.combo.append_text (_("do nothing")); + auto_profiles.forEach (s => { + this.combo.append_text (s.name); + if (s.guid == profile.guid) id = i; + i++; + }); + profiles.forEach (s => { + this.combo.append_text (s.name + " (user profile)"); + if (s.guid == profile.guid) id = i; + i++; + }); + this.combo.active = id; + hbox.pack_end (this.combo, false, false, 0); + + hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL}); + hbox.margin_top = 8; + this.add (hbox); + this.label = new Gtk.Label ({label:_("Level"), use_markup:true, xalign:0}); + hbox.pack_start (this.label, true, true, 0); + this.info = new Gtk.Label ({label:""+profile.percent+"%", use_markup:true}); + hbox.pack_end (this.info, false, false, 0); + this.slider = Gtk.Scale.new_with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1); + this.slider.draw_value = false; + this.slider.set_value (profile.percent); + this.add (this.slider); + this.slider.connect('value_changed', (o) => { + this.update_info (Math.round (o.get_value ()).toString ()); + }); + + this.show_all (); + }, + + update_info: function (info) { + this.info.set_markup ("" + info + "%"); + } +}); + +const css_theme = " \ +.cpufreq-text { font-family: cpufreq, roboto, cantarell} \ +"; + +function get_css_provider () { + let cssp = new Gtk.CssProvider (); + try { + cssp.load_from_data (css_theme); + } catch (e) { + print (e); + cssp = null; + } + return cssp; +} + +function getCurrentFile () { + let stack = (new Error()).stack; + let stackLine = stack.split('\n')[1]; + if (!stackLine) + throw new Error ('Could not find current file'); + let match = new RegExp ('@(.+):\\d+').exec(stackLine); + if (!match) + throw new Error ('Could not find current file'); + let path = match[1]; + let file = Gio.File.new_for_path (path); + return [file.get_path(), file.get_parent().get_path(), file.get_basename()]; +} + +function debug (msg) { + if (msg) print ("[cpufreq][prefs] " + msg); +} + +function error (msg) { + log ("[cpufreq][prefs] (EE) " + msg); +} + +function init () { + Convenience.initTranslations (); +} + +function buildPrefsWidget () { + if (Gtk.MAJOR_VERSION > 3) { + GLib.spawn_command_line_async (APPDIR + "/cpufreq-preferences"); + let widget = new DumpWidget (); + return widget; + } + let widget = new CPUFreqPreferences (); + return widget.notebook; +} + +var DumpWidget = new Lang.Class({ + Name: 'DumpWidget', + Extends: Gtk.Box, + + _init: function () { + this.parent ({}); + /*this.connect ('realize', () => { + this.get_parent ().get_parent ().close (); + });*/ + } +}); + +function get_appdir () { + let s = getCurrentFile ()[1]; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; + s = GLib.get_home_dir () + "/.local/share/gnome-shell/extensions/cpufreq@konkor"; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; + s = "/usr/local/share/gnome-shell/extensions/cpufreq@konkor"; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; + s = "/usr/share/gnome-shell/extensions/cpufreq@konkor"; + if (GLib.file_test (s + "/prefs_gjs.js", GLib.FileTest.EXISTS)) return s; + throw "CPUFreq installation not found..."; + return s; +} diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index 5c80854..c827b09 100644 Binary files a/schemas/gschemas.compiled and b/schemas/gschemas.compiled differ