Skip to content

Commit

Permalink
Reorganize code
Browse files Browse the repository at this point in the history
  • Loading branch information
AzzamAlsharafi committed Sep 6, 2022
1 parent 6ff942c commit aed4558
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 116 deletions.
187 changes: 88 additions & 99 deletions extension.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,83 @@
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const St = imports.gi.St;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;

const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const UIQuickSettings = imports.ui.quickSettings;
const GLib = imports.gi.GLib;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Main = imports.ui.main;
const AggregateMenu = Main.panel.statusArea.aggregateMenu; // GNOME 42 System Menu
const QuickSettingsMenu = Main.panel.statusArea.quickSettings; // GNOME 43 System Menu

const Config = imports.misc.config;
const [major] = Config.PACKAGE_VERSION.split('.');
const [major] = Config.PACKAGE_VERSION.split(".");
const shellVersion = Number.parseInt(major);

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const optionsUtils = Me.imports.optionsUtils;

// AggregateMenu for GNOME 42, QuickSettings for GNOME 43.
const AggregateMenu = Main.panel.statusArea.aggregateMenu;
const QuickSettingsMenu = Main.panel.statusArea.quickSettings;
const extensionIcon = Gio.icon_new_for_string(Me.dir.get_path() + "/icons/controls-big-symbolic.svg");

const extensionIcon = Gio.icon_new_for_string(Me.dir.get_path() + '/icons/controls-big-symbolic.svg');
function init() {}

const TrayMenu = GObject.registerClass(
class TrayMenu extends PanelMenu.Button {
_init() {
super._init(0);
let extensionMenu = null;
let settings = null;
let trayListener = null;

// Tray icon
let icon = new St.Icon({
gicon: extensionIcon,
style_class: 'system-status-icon',
});
function enable() {
settings = ExtensionUtils.getSettings("org.gnome.shell.extensions.ideapad-controls");

this.add_child(icon);
updateLocation(settings);

addOptionsToMenu(this.menu);
}
trayListener = settings.connect("changed::tray-location", () => {
updateLocation(settings);
})
}

function disable() {
if (trayListener != null) {
settings.disconnect(trayListener);
trayListener = null;
}
);

// There are two classes for system menu because GNOME 42 and 43
// use different ways to interact with the system menu.
if (extensionMenu != null) {
extensionMenu.destroy();
extensionMenu = null;
}

optionsUtils.destroy();
}

function updateLocation(settings) {
if(extensionMenu != null){
extensionMenu.destroy();
extensionMenu = null;
}

if (settings.get_boolean("tray-location")) { // Tray mode
extensionMenu = new TrayMenu();
Main.panel.addToStatusArea("ideapad-controls", extensionMenu, 1);
} else { // System menu mode
extensionMenu = getSystemMenu();
}
}

// Each of GNOME 42 and GNOME 43 use a different system menu,
// that's why there are two classes for system menu.
// GNOME 42 uses AggregateMenu (SystemMenu),
// and GNOME 43 uses QuickSettings (QSystemMenu).
function getSystemMenu() {
if (shellVersion < 43) {
log("GNOME 42");
return new SystemMenu();
} else {
log("GNOME 43");
return new QSystemMenu();
}
}

const SystemMenu = GObject.registerClass(
class SystemMenu extends PanelMenu.SystemIndicator {

Expand All @@ -56,7 +91,7 @@ const SystemMenu = GObject.registerClass(
// Places the extension's sub menu after the battery sub menu if it exists,
// otherwise places the extension's sub menu at the first spot. (Change later? First spot might be bad idea)
const menuItems = AggregateMenu.menu._getMenuItems();
const subMenuIndex = AggregateMenu._power ? (menuItems.indexOf(AggregateMenu._power.menu) + 1) : 0
const subMenuIndex = AggregateMenu._power ? (menuItems.indexOf(AggregateMenu._power.menu) + 1) : 0;
AggregateMenu.menu.addMenuItem(this.subMenu, subMenuIndex);

addOptionsToMenu(this.subMenu.menu);
Expand All @@ -76,11 +111,13 @@ const QSystemMenu = GObject.registerClass(
super._init();

// Create extension's sub menu
this.toggleMenu = new UIQuickSettings.QuickMenuToggle({label: "IdeaPad",
this.toggleMenu = new UIQuickSettings.QuickMenuToggle({label: "IdeaPad", // Not enough space for full name :(
gicon: extensionIcon});

this.toggleMenu.menu.setHeader(extensionIcon, Me.metadata.name);

// Since this "toggle" menu isn't being used as a toggle button
// clicking should just open the menu.
this.toggleMenu.connect("clicked", () => {
this.toggleMenu.menu.open();
})
Expand All @@ -97,36 +134,53 @@ const QSystemMenu = GObject.registerClass(
}
);

function addOptionsToMenu(menu) {
let settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.ideapad-controls');
const TrayMenu = GObject.registerClass(
class TrayMenu extends PanelMenu.Button {
_init() {
super._init(0);

let options = optionsUtils.getOptions();
// Tray icon
const icon = new St.Icon({
gicon: extensionIcon,
style_class: "system-status-icon",
});

this.add_child(icon);

addOptionsToMenu(this.menu);
}
}
);


function addOptionsToMenu(menu) {
const options = optionsUtils.getOptions();

// Create a switch item for each option
for (let i = 0; i < options.length; i++) {
// Convert option title to schema key, i.e. "Camera Lock" becomes "camera-lock-option"
const optionKey = options[i].toLowerCase().replace(" ", "-") + "-option";

let optionSwitch = new PopupMenu.PopupSwitchMenuItem(options[i], optionsUtils.getOptionValue(i) === "1");
const optionSwitch = new PopupMenu.PopupSwitchMenuItem(options[i], optionsUtils.getOptionValue(i) === "1");
menu.addMenuItem(optionSwitch);

settings.bind(
optionKey,
optionSwitch,
'visible',
"visible",
Gio.SettingsBindFlags.DEFAULT
);

optionSwitch.connect('toggled', () => {
optionSwitch.connect("toggled", () => {
optionsUtils.getOptionValue(i);
optionsUtils.setOptionValue(i, optionSwitch.state ? 1 : 0)
optionsUtils.setOptionValue(i, optionSwitch.state ? 1 : 0);
});
}

// Setting button
menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());

let settingsButton = new PopupMenu.PopupMenuItem("Extension Settings");
const settingsButton = new PopupMenu.PopupMenuItem("Extension Settings");

settingsButton.connect("activate", () => ExtensionUtils.openPrefs());

Expand All @@ -138,68 +192,3 @@ function addOptionsToMenu(menu) {
"visible",
Gio.SettingsBindFlags.DEFAULT);
}

function updateLocation(trayLocation) {
if (trayLocation) {
if (systemMenu != null) {
systemMenu.destroy();
systemMenu = null;
}

trayMenu = new TrayMenu();
Main.panel.addToStatusArea('ideapad-controlMenu', trayMenu, 1);
} else {
if (trayMenu != null) {
trayMenu.destroy();
trayMenu = null;
}

systemMenu = getSystemMenu();
}
}

// Return appropriate system menu based on shell version.
function getSystemMenu() {
if (shellVersion < 43) {
return new SystemMenu();
} else {
return new QSystemMenu();
}
}

function init() { }

let trayMenu = null;
let systemMenu = null;

let settings = null;
let trayListener = null;

function enable() {
settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.ideapad-controls');

updateLocation(settings.get_boolean("tray-location"));

trayListener = settings.connect("changed::tray-location", () => {
updateLocation(settings.get_boolean("tray-location"));
})
}

function disable() {
if (trayListener != null) {
settings.disconnect(trayListener);
trayListener = null;
}

if (trayMenu != null) {
trayMenu.destroy();
trayMenu = null;
}

if (systemMenu != null) {
systemMenu.destroy();
systemMenu = null;
}

optionsUtils.destroy();
}
12 changes: 7 additions & 5 deletions optionsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const filesDir = "/sys/bus/platform/drivers/ideapad_acpi/VPC2004:00/";

// All options that the extension can support, regardless of the current device running the extension.
const allOptions = ["Conservation Mode", "Camera", "Fn Lock", "Touchpad", "USB Charging"];
// Files names for each option in the driver files
// Files names for each option in the driver files.
const allOptionsFiles = ["conservation_mode", "camera_power", "fn_lock", "touchpad", "usb_charging"];

// Lists to store options supported by this device.
Expand All @@ -26,15 +26,17 @@ function prepareAvailableOptions() {
}
}

// Returns available options in this device
// Returns available options in this device.
function getOptions() {
log("Get options");
if (options == null) {
log("NO OPTIONS?! CREATE THEM!");
prepareAvailableOptions();
}
return options;
}

// Returns available options files in this device
// Returns available options files in this device.
function getOptionsFiles() {
if (optionsFiles == null) {
prepareAvailableOptions();
Expand All @@ -47,15 +49,15 @@ function getOptionValue(optionIndex) {
const file = Gio.File.new_for_path(filesDir + getOptionsFiles()[optionIndex]);
const [, contents, etag] = file.load_contents(null);

const decoder = new TextDecoder('utf-8');
const decoder = new TextDecoder("utf-8");
const contentsString = decoder.decode(contents);

return contentsString.trim();
}

// Write option value to driver file.
function setOptionValue(optionIndex, value) {
GLib.spawn_command_line_async('pkexec bash -c "echo ' + value + ' > ' + filesDir + getOptionsFiles()[optionIndex] + '"');
GLib.spawn_command_line_async("pkexec bash -c 'echo " + value + " > " + filesDir + getOptionsFiles()[optionIndex] + "'");
}

function destroy(){
Expand Down
24 changes: 12 additions & 12 deletions prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,31 @@ function init() { }

function fillPreferencesWindow(window) {
const settings = ExtensionUtils.getSettings(
'org.gnome.shell.extensions.ideapad-controls');
"org.gnome.shell.extensions.ideapad-controls");

let builder = Gtk.Builder.new();
const builder = Gtk.Builder.new();
builder.add_from_file(Me.dir.get_path() + "/template.ui");
let page = builder.get_object('prefs_page');
const page = builder.get_object("prefs_page");


// Extension Menu - Extension menu location ComboBox
let locationComboBox = builder.get_object('location_combo');
const locationComboBox = builder.get_object("location_combo");

locationComboBox.set_active_id(settings.get_boolean("tray-location") ? 'tray' : 'system_menu');
locationComboBox.set_active_id(settings.get_boolean("tray-location") ? "tray" : "system_menu");

locationComboBox.connect("changed", () => {
settings.set_boolean("tray-location", locationComboBox.get_active_id() === "tray");
});

// Extension Menu - Settings button Switch
let settingsButtonSwitch = builder.get_object('settings_button_switch');
const settingsButtonSwitch = builder.get_object("settings_button_switch");

builder.get_object('settings_button_row').activatable_widget = settingsButtonSwitch;
builder.get_object("settings_button_row").activatable_widget = settingsButtonSwitch;

settings.bind(
'settings-button',
"settings-button",
settingsButtonSwitch,
'active',
"active",
Gio.SettingsBindFlags.DEFAULT
);

Expand All @@ -47,9 +47,9 @@ function fillPreferencesWindow(window) {
}

function addOptionsSwitches(builder, settings){
let optionsGroup = builder.get_object('options_group');
const optionsGroup = builder.get_object("options_group");

let options = optionsUtils.getOptions();
const options = optionsUtils.getOptions();

// Create a Switch for each option
for (let i = 0; i < options.length; i++) {
Expand All @@ -67,7 +67,7 @@ function addOptionsSwitches(builder, settings){
settings.bind(
optionKey,
optionSwitch,
'active',
"active",
Gio.SettingsBindFlags.DEFAULT
);

Expand Down

0 comments on commit aed4558

Please sign in to comment.