mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-11-04 09:42:42 +01:00 
			
		
		
		
	Added custom tooltip with device icon, device name and battery status
This commit is contained in:
		@@ -1,8 +1,11 @@
 | 
			
		||||
#include "modules/upower/upower.hpp"
 | 
			
		||||
 | 
			
		||||
#include "gtkmm/icontheme.h"
 | 
			
		||||
#include "gtkmm/label.h"
 | 
			
		||||
#include "gtkmm/tooltip.h"
 | 
			
		||||
#include "modules/upower/upower_tooltip.hpp"
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules {
 | 
			
		||||
namespace waybar::modules::upower {
 | 
			
		||||
UPower::UPower(const std::string& id, const Json::Value& config)
 | 
			
		||||
    : AModule(config, "upower", id),
 | 
			
		||||
      box_(Gtk::ORIENTATION_HORIZONTAL, 0),
 | 
			
		||||
@@ -26,6 +29,23 @@ UPower::UPower(const std::string& id, const Json::Value& config)
 | 
			
		||||
    hideIfEmpty = config_["hide-if-empty"].asBool();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Tooltip Spacing
 | 
			
		||||
  if (config_["tooltip-spacing"].isUInt()) {
 | 
			
		||||
    tooltip_spacing = config_["tooltip-spacing"].asUInt();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Tooltip
 | 
			
		||||
  if (config_["tooltip"].isBool()) {
 | 
			
		||||
    tooltip_enabled = config_["tooltip"].asBool();
 | 
			
		||||
  }
 | 
			
		||||
  box_.set_has_tooltip(tooltip_enabled);
 | 
			
		||||
  if (tooltip_enabled) {
 | 
			
		||||
    // Sets the window to use when showing the tooltip
 | 
			
		||||
    upower_tooltip = new UPowerTooltip(iconSize, tooltip_spacing);
 | 
			
		||||
    box_.set_tooltip_window(*upower_tooltip);
 | 
			
		||||
    box_.signal_query_tooltip().connect(sigc::mem_fun(*this, &UPower::show_tooltip_callback));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GError* error = NULL;
 | 
			
		||||
  client = up_client_new_full(NULL, &error);
 | 
			
		||||
  if (client == NULL) {
 | 
			
		||||
@@ -174,6 +194,10 @@ void UPower::resetDevices() {
 | 
			
		||||
  dp.emit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool UPower::show_tooltip_callback(int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& tooltip) {
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto UPower::update() -> void {
 | 
			
		||||
  std::lock_guard<std::mutex> guard(m_Mutex);
 | 
			
		||||
 | 
			
		||||
@@ -204,7 +228,7 @@ auto UPower::update() -> void {
 | 
			
		||||
 | 
			
		||||
  std::string percentString = "";
 | 
			
		||||
 | 
			
		||||
  std::string tooltip = "";
 | 
			
		||||
  uint tooltipCount = 0;
 | 
			
		||||
 | 
			
		||||
  if (devices.size() == 0 && !displayDeviceValid && hideIfEmpty) {
 | 
			
		||||
    event_box_.set_visible(false);
 | 
			
		||||
@@ -213,18 +237,12 @@ auto UPower::update() -> void {
 | 
			
		||||
 | 
			
		||||
  event_box_.set_visible(true);
 | 
			
		||||
 | 
			
		||||
  // TODO: Tooltip
 | 
			
		||||
  if (!devices.empty()) {
 | 
			
		||||
    for (auto& e : devices) {
 | 
			
		||||
      const gchar* objectPath = up_device_get_object_path(e.second);
 | 
			
		||||
      double       percentage;
 | 
			
		||||
      g_object_get(e.second, "percentage", &percentage, NULL);
 | 
			
		||||
      printf("Device: %s, VALID: %f\n", objectPath, percentage);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    printf("No devices\n");
 | 
			
		||||
  // Tooltip
 | 
			
		||||
  if (tooltip_enabled) {
 | 
			
		||||
    tooltipCount = upower_tooltip->updateTooltip(devices);
 | 
			
		||||
    // Disable the tooltip if there aren't any devices in the tooltip
 | 
			
		||||
    box_.set_has_tooltip(!devices.empty() && tooltipCount > 0);
 | 
			
		||||
  }
 | 
			
		||||
  // box_.set_tooltip
 | 
			
		||||
 | 
			
		||||
  // Set percentage
 | 
			
		||||
  if (displayDeviceValid) {
 | 
			
		||||
@@ -243,4 +261,4 @@ update:
 | 
			
		||||
  AModule::update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace waybar::modules
 | 
			
		||||
}  // namespace waybar::modules::upower
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										158
									
								
								src/modules/upower/upower_tooltip.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/modules/upower/upower_tooltip.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
			
		||||
#include "modules/upower/upower_tooltip.hpp"
 | 
			
		||||
 | 
			
		||||
#include "gtkmm/box.h"
 | 
			
		||||
#include "gtkmm/enums.h"
 | 
			
		||||
#include "gtkmm/icontheme.h"
 | 
			
		||||
#include "gtkmm/image.h"
 | 
			
		||||
#include "gtkmm/label.h"
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules::upower {
 | 
			
		||||
UPowerTooltip::UPowerTooltip(uint iconSize_, uint tooltipSpacing_)
 | 
			
		||||
    : Gtk::Window(), iconSize(iconSize_), tooltipSpacing(tooltipSpacing_) {
 | 
			
		||||
  contentBox = new Gtk::Box(Gtk::ORIENTATION_VERTICAL);
 | 
			
		||||
  add(*contentBox);
 | 
			
		||||
  contentBox->show();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UPowerTooltip::~UPowerTooltip() {}
 | 
			
		||||
 | 
			
		||||
uint UPowerTooltip::updateTooltip(Devices& devices) {
 | 
			
		||||
  // Removes all old devices
 | 
			
		||||
  for (auto child : contentBox->get_children()) {
 | 
			
		||||
    child->~Widget();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint deviceCount = 0;
 | 
			
		||||
  // Adds all valid devices
 | 
			
		||||
  for (auto pair : devices) {
 | 
			
		||||
    UpDevice*   device = pair.second;
 | 
			
		||||
    std::string objectPath = pair.first;
 | 
			
		||||
 | 
			
		||||
    if (!G_IS_OBJECT(device)) continue;
 | 
			
		||||
 | 
			
		||||
    Gtk::Box* box = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, tooltipSpacing);
 | 
			
		||||
 | 
			
		||||
    UpDeviceKind kind;
 | 
			
		||||
    double       percentage;
 | 
			
		||||
    gchar*       native_path;
 | 
			
		||||
    gchar*       model;
 | 
			
		||||
    gchar*       icon_name;
 | 
			
		||||
 | 
			
		||||
    g_object_get(device,
 | 
			
		||||
                 "kind",
 | 
			
		||||
                 &kind,
 | 
			
		||||
                 "percentage",
 | 
			
		||||
                 &percentage,
 | 
			
		||||
                 "native-path",
 | 
			
		||||
                 &native_path,
 | 
			
		||||
                 "model",
 | 
			
		||||
                 &model,
 | 
			
		||||
                 "icon-name",
 | 
			
		||||
                 &icon_name,
 | 
			
		||||
                 NULL);
 | 
			
		||||
 | 
			
		||||
    // Skip Line_Power and BAT0 devices
 | 
			
		||||
    if (kind == UP_DEVICE_KIND_LINE_POWER || strcmp(native_path, "BAT0") == 0) continue;
 | 
			
		||||
 | 
			
		||||
    Gtk::Box* modelBox = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL);
 | 
			
		||||
    box->add(*modelBox);
 | 
			
		||||
    // Set device icon
 | 
			
		||||
    std::string deviceIconName = getDeviceIcon(kind);
 | 
			
		||||
    Gtk::Image* deviceIcon = new Gtk::Image();
 | 
			
		||||
    deviceIcon->set_pixel_size(iconSize);
 | 
			
		||||
    if (!Gtk::IconTheme::get_default()->has_icon(deviceIconName)) {
 | 
			
		||||
      deviceIconName = "battery-missing-symbolic";
 | 
			
		||||
    }
 | 
			
		||||
    deviceIcon->set_from_icon_name(deviceIconName, Gtk::ICON_SIZE_INVALID);
 | 
			
		||||
    modelBox->add(*deviceIcon);
 | 
			
		||||
 | 
			
		||||
    // Set model
 | 
			
		||||
    Gtk::Label* modelLabel = new Gtk::Label(model);
 | 
			
		||||
    modelBox->add(*modelLabel);
 | 
			
		||||
 | 
			
		||||
    Gtk::Box* chargeBox = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL);
 | 
			
		||||
    box->add(*chargeBox);
 | 
			
		||||
 | 
			
		||||
    // Set icon
 | 
			
		||||
    Gtk::Image* icon = new Gtk::Image();
 | 
			
		||||
    icon->set_pixel_size(iconSize);
 | 
			
		||||
    if (!Gtk::IconTheme::get_default()->has_icon(icon_name)) {
 | 
			
		||||
      icon_name = (char*)"battery-missing-symbolic";
 | 
			
		||||
    }
 | 
			
		||||
    icon->set_from_icon_name(icon_name, Gtk::ICON_SIZE_INVALID);
 | 
			
		||||
    chargeBox->add(*icon);
 | 
			
		||||
 | 
			
		||||
    // Set percentage
 | 
			
		||||
    std::string percentString = std::to_string(int(percentage + 0.5)) + "%";
 | 
			
		||||
    Gtk::Label* percentLabel = new Gtk::Label(percentString);
 | 
			
		||||
    chargeBox->add(*percentLabel);
 | 
			
		||||
 | 
			
		||||
    contentBox->add(*box);
 | 
			
		||||
 | 
			
		||||
    deviceCount++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  contentBox->show_all();
 | 
			
		||||
  return deviceCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string UPowerTooltip::getDeviceIcon(UpDeviceKind& kind) {
 | 
			
		||||
  switch (kind) {
 | 
			
		||||
    case UP_DEVICE_KIND_LINE_POWER:
 | 
			
		||||
      return "ac-adapter-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_BATTERY:
 | 
			
		||||
      return "battery";
 | 
			
		||||
    case UP_DEVICE_KIND_UPS:
 | 
			
		||||
      return "uninterruptible-power-supply-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_MONITOR:
 | 
			
		||||
      return "video-display-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_MOUSE:
 | 
			
		||||
      return "input-mouse-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_KEYBOARD:
 | 
			
		||||
      return "input-keyboard-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_PDA:
 | 
			
		||||
      return "pda-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_PHONE:
 | 
			
		||||
      return "phone-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_MEDIA_PLAYER:
 | 
			
		||||
      return "multimedia-player-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_TABLET:
 | 
			
		||||
      return "computer-apple-ipad-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_COMPUTER:
 | 
			
		||||
      return "computer-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_GAMING_INPUT:
 | 
			
		||||
      return "input-gaming-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_PEN:
 | 
			
		||||
      return "input-tablet-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_TOUCHPAD:
 | 
			
		||||
      return "input-touchpad-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_MODEM:
 | 
			
		||||
      return "modem-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_NETWORK:
 | 
			
		||||
      return "network-wired-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_HEADSET:
 | 
			
		||||
      return "audio-headset-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_HEADPHONES:
 | 
			
		||||
      return "audio-headphones-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_OTHER_AUDIO:
 | 
			
		||||
    case UP_DEVICE_KIND_SPEAKERS:
 | 
			
		||||
      return "audio-speakers-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_VIDEO:
 | 
			
		||||
      return "camera-web-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_PRINTER:
 | 
			
		||||
      return "printer-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_SCANNER:
 | 
			
		||||
      return "scanner-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_CAMERA:
 | 
			
		||||
      return "camera-photo-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_BLUETOOTH_GENERIC:
 | 
			
		||||
      return "bluetooth-active-symbolic";
 | 
			
		||||
    case UP_DEVICE_KIND_TOY:
 | 
			
		||||
    case UP_DEVICE_KIND_REMOTE_CONTROL:
 | 
			
		||||
    case UP_DEVICE_KIND_WEARABLE:
 | 
			
		||||
    case UP_DEVICE_KIND_LAST:
 | 
			
		||||
    default:
 | 
			
		||||
      return "battery-symbolic";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}  // namespace waybar::modules::upower
 | 
			
		||||
		Reference in New Issue
	
	Block a user