实例介绍
【实例截图】
【核心代码】
/***************************************************************************
* Copyright (C) 2010 by Peter Hatina *
* email: phatina (at) gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License *
* version 2.1 as published by the Free Software Foundation *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. *
***************************************************************************/
#include "batterymetergui.h"
#include "settings.h"
#include "action.h"
#include "shutdown.h"
#include "common.h"
#ifdef Q_OS_WIN32
# include "winregistry.h"
# include "powerscheme.h"
#endif
#include <limits>
#include <QApplication>
#include <QProcess>
#include <QDateTime>
#include <QFile>
//log time (ms)
const int LOGGER_TIMEOUT = 60000;
BatteryMeterGui::BatteryMeterGui(QObject *parent):
QTimer(parent),
m_tray(new BatteryMeterTrayIcon),
m_menu(new QMenu),
m_act_quit(new QAction(QIcon(":/img/exit.png"), "Quit", m_menu.data())),
m_act_settings(new QAction(QIcon(":/img/settings.png"), "Settings", m_menu.data())),
m_act_info(new QAction(QIcon(":/img/info.png"), "Info", m_menu.data())),
m_act_log(new QAction(QIcon(":/img/log.png"), "Log", m_menu.data())),
#if (defined (Q_OS_WIN32) && (WINVER >= 0x0600))
m_power_menu(new QMenu()),
m_actgrp_power(new QActionGroup(m_power_menu.data())),
m_act_min_power(new QAction("Power saver", m_power_menu.data())),
m_act_max_power(new QAction("Performance", m_power_menu.data())),
m_act_balanced(new QAction("Balanced", m_power_menu.data())),
#endif
m_dlg_info(new InfoDialog),
m_dlg_settings(new SettingsDialog)
{
connect(m_dlg_settings.data(), SIGNAL(newConfiguration()), this, SLOT(readConfiguration()));
// setup menu actions
m_act_quit->setIconVisibleInMenu(true);
m_act_settings->setIconVisibleInMenu(true);
m_act_info->setIconVisibleInMenu(true);
m_act_log->setIconVisibleInMenu(true);
// fill tray menu
m_menu->addAction(m_act_info.data());
m_menu->addAction(m_act_log.data());
m_menu->addAction(m_act_settings.data());
#if (defined (Q_OS_WIN32) && (WINVER >= 0x0600))
m_power_menu.reset(m_menu->addMenu(QIcon(":/img/scheme.png"), "Power scheme"));
m_act_min_power->setCheckable(true);
m_act_min_power->setChecked(m_power_scheme.isMinPower());
m_act_max_power->setCheckable(true);
m_act_max_power->setChecked(m_power_scheme.isMaxPower());
m_act_balanced->setCheckable(true);
m_act_balanced->setChecked(m_power_scheme.isBalanced());
m_actgrp_power->addAction(m_act_min_power);
m_actgrp_power->addAction(m_act_max_power);
m_actgrp_power->addAction(m_act_balanced);
m_actgrp_power->setExclusive(true);
m_power_menu->addAction(m_act_min_power);
m_power_menu->addAction(m_act_balanced);
m_power_menu->addAction(m_act_max_power);
connect(m_act_min_power.data(), SIGNAL(triggered()), this, SLOT(changePowerStatus()));
connect(m_act_max_power.data(), SIGNAL(triggered()), this, SLOT(changePowerStatus()));
connect(m_act_balanced.data(), SIGNAL(triggered()), this, SLOT(changePowerStatus()));
connect(&m_message_listener, SIGNAL(powerSchemeChanged()), this, SLOT(powerStatusChanged()));
if (!m_power_scheme.powrProfLoaded())
{
m_menu->removeAction(m_power_menu->menuAction());
m_dlg_settings->setUseSchemes(false);
}
#endif
m_menu->addSeparator();
m_menu->addAction(m_act_quit.data());
m_tray->setContextMenu(m_menu.data());
m_tray->setIcon(QIcon());
#ifdef USE_LOGGING
// logger
m_logger.setInterval(LOGGER_TIMEOUT);
connect(&m_logger, SIGNAL(timeout()), this, SLOT(onLog()));
#endif
// action connections
connect(this, SIGNAL(timeout()), this, SLOT(update()));
connect(m_act_info.data(), SIGNAL(triggered()), this, SLOT(infoDlgVisibility()));
connect(m_act_settings.data(), SIGNAL(triggered()), m_dlg_settings.data(), SLOT(show()));
connect(m_tray.data(), SIGNAL(clicked()), this, SLOT(infoDlgVisibility()));
connect(m_tray.data(), SIGNAL(hint()), m_dlg_info.data(), SLOT(show()));
connect(m_act_quit.data(), SIGNAL(triggered()), qApp, SLOT(quit()));
connect(m_act_quit.data(), SIGNAL(triggered()), m_tray.data(), SLOT(hide()));
// read config. file
readConfiguration();
}
BatteryMeterGui::~BatteryMeterGui()
{
}
void BatteryMeterGui::update()
{
m_battery_meter.update();
if (!m_battery_meter.batteryPresent() && m_battery_meter.acOnline())
{
// no battery present, we run only on an AC adaptor
m_act_info->setEnabled(false);
m_tray->setPercentage(100);
return;
}
m_act_info->setEnabled(true);
// prepare data for infoDlg
QString charging_state;
switch (m_battery_meter.state())
{
case BatteryMeter::CHARGING:
charging_state = "Charging";
m_tray->setAnimate(true);
break;
case BatteryMeter::CHARGED:
charging_state = "Charged";
m_tray->setAnimate(false);
m_tray->setPercentage(m_battery_meter.percentage());
break;
case BatteryMeter::DISCHARGING:
charging_state = "Discharging";
m_tray->setAnimate(false);
m_tray->setPercentage(m_battery_meter.percentage());
break;
case BatteryMeter::UNKNOWN:
charging_state = "Unknown";
m_tray->setAnimate(false);
m_tray->setPercentage(100);
break;
}
// setup info dialog
m_dlg_info->setPercentage(m_battery_meter.percentage());
m_dlg_info->setCapacity(m_battery_meter.remainCapa(), m_battery_meter.designCapa());
m_dlg_info->setRate(m_battery_meter.rate());
m_dlg_info->setBatteryState(m_battery_meter.state());
m_dlg_info->setAcState(m_battery_meter.acOnline());
m_dlg_info->setTimeRemaining(m_battery_meter.remainTime());
// charged status tooltip
QString toolTip = QString("Battery state: %1 % (").arg(m_battery_meter.percentage());
toolTip = charging_state ")";
unsigned long mins = m_battery_meter.remainTime();
QTime t(mins / 60, mins % 60);
if (t.minute() != 0 || t.hour() != 0)
{
toolTip = QString("\nRemaining time: ") t.toString("hh:mm");
}
else
{
if (!m_battery_meter.acOnline())
{
singleShot(5000, this, SLOT(update()));
}
}
m_tray->setToolTip(toolTip);
if (!m_tray->isVisible())
return;
static unsigned long prev_perc = std::numeric_limits <unsigned long>::max();
//bool discharge = prev_perc > m_battery_meter.percentage()
// || prev_perc == std::numeric_limits <unsigned long>::max();
bool discharge = prev_perc >= m_battery_meter.percentage() &&
m_battery_meter.state() == BatteryMeter::DISCHARGING;
prev_perc = m_battery_meter.percentage();
// process actions
if (discharge)
dischargeActions();
else
chargeActions();
}
void BatteryMeterGui::show()
{
m_tray->show();
}
void BatteryMeterGui::hide()
{
m_tray->hide();
}
void BatteryMeterGui::start()
{
if (this->isActive())
return;
// run timer in seconds interval
// interal comes from config
Settings *settings = Settings::instance();
QTimer::start(settings->updateInterval() * 1000);
#ifdef Q_OS_WIN32
m_message_listener.listen();
connect(&m_message_listener, SIGNAL(powerStatusChanged()), this, SLOT(update()));
#endif
}
void BatteryMeterGui::start(int msec)
{
if (this->isActive())
return;
// run in ms interval
QTimer::start(msec);
#ifdef Q_OS_WIN32
m_message_listener.listen();
connect(&m_message_listener, SIGNAL(powerStatusChanged()), this, SLOT(update()));
#endif
}
void BatteryMeterGui::stop()
{
#ifdef Q_OS_WIN32
disconnect(&m_message_listener, SIGNAL(powerStatusChanged()), this, SLOT(update()));
#endif
}
#ifdef USE_LOGGING
void BatteryMeterGui::onLog()
{
if (m_log_file.isEmpty())
{
// TODO maybe change the behavior
m_logger.stop();
return;
}
QFile fout(m_log_file);
if (!fout.open(QIODevice::Append))
return;
QString str_line = QDateTime::currentDateTime().toString("yyyy.MM.dd-hh:mm:ss");
QString perc = QString("%1").arg(m_battery_meter.percentage());
while (perc.length() < 3)
perc.prepend("0");
str_line = "," perc;
str_line = QString(",%1").arg(m_battery_meter.acOnline() ? "conn" : "disc");
str_line = "\n";
QByteArray line;
line.append(str_line);
fout.write(line);
fout.close();
}
#endif
void BatteryMeterGui::dischargeActions()
{
while (!m_unprocessed_actions.isEmpty() &&
(static_cast <unsigned long> (m_unprocessed_actions.last().level())
>= m_battery_meter.percentage()))
{
// move the action into other container
Action action = m_unprocessed_actions.last();
m_unprocessed_actions.pop_back();
m_processed_actions.push_front(action);
// process the action
switch (action.type())
{
case Action::MESSAGE:
m_tray->showMessage("Battery Meter", action.attr(), QSystemTrayIcon::Information);
break;
case Action::ACTION:
QProcess::execute(action.attr());
break;
case Action::SUSPEND:
Shutdown::suspend();
break;
case Action::HIBERNATE:
Shutdown::hibernate();
break;
case Action::POWEROFF:
Shutdown::shutdown();
break;
default:
break;
}
}
}
void BatteryMeterGui::chargeActions()
{
while (!m_processed_actions.isEmpty() &&
static_cast <unsigned long> (m_processed_actions.first().level())
< m_battery_meter.percentage())
{
Action action = m_processed_actions.first();
m_processed_actions.pop_front();
m_unprocessed_actions.push_back(action);
}
//printActions();
}
#if (defined (Q_OS_WIN32) && (WINVER >= 0x0600))
void BatteryMeterGui::changePowerStatus()
{
if (m_act_min_power->isChecked())
{
m_power_scheme.setMinPower();
}
else if (m_act_max_power->isChecked())
{
m_power_scheme.setMaxPower();
}
else
{
m_power_scheme.setBalanced();
}
}
void BatteryMeterGui::powerStatusChanged()
{
m_act_min_power->setChecked(m_power_scheme.isMinPower());
m_act_max_power->setChecked(m_power_scheme.isMaxPower());
m_act_balanced->setChecked(m_power_scheme.isBalanced());
m_dlg_settings->setMinPower(m_act_min_power->isChecked());
m_dlg_settings->setMaxPower(m_act_max_power->isChecked());
m_dlg_settings->setBalanced(m_act_balanced->isChecked());
}
#endif
void BatteryMeterGui::infoDlgVisibility()
{
if (!m_battery_meter.batteryPresent())
return;
m_dlg_info->isVisible() ? m_dlg_info->hide() : m_dlg_info->show();
}
void BatteryMeterGui::readConfiguration()
{
Settings *settings = Settings::instance();
// load application settings
m_unprocessed_actions = settings->actions();
m_processed_actions.clear();
#ifdef USE_LOGGING
m_logging = settings.logEnabled() && settings.log();
m_log_file = settings.logFile();
#endif
setInterval(settings->updateInterval() * 1000);
// TODO some time, maybe it will be ready
//m_act_log->setVisible(m_logging);
m_act_log->setVisible(false);
// move passed events into processed list
while (!m_unprocessed_actions.isEmpty() &&
(static_cast <unsigned long> (m_unprocessed_actions.last().level())
>= m_battery_meter.percentage()))
{
Action action = m_unprocessed_actions.last();
m_unprocessed_actions.pop_back();
m_processed_actions.push_front(action);
}
#ifdef USE_LOGGING
if (m_logging)
m_logger.start();
else
m_logger.stop();
#endif
}
//------------------------------------------------------------------------------
#ifdef Q_OS_WIN32
MessageListener::MessageListener(QWidget *parent):
QWidget(parent),
m_listen(false)
{
}
MessageListener::~MessageListener()
{
}
void MessageListener::listen(bool l)
{
if (m_listen == l)
return;
m_listen = l;
# if (WINVER > 0x0600)
if (m_listen)
{
// register for the message
m_power_source_notify = RegisterPowerSettingNotification(
reinterpret_cast <void *> (winId()),
&GUID_ACDC_POWER_SOURCE, DEVICE_NOTIFY_WINDOW_HANDLE);
m_battery_perc_notify = RegisterPowerSettingNotification(
reinterpret_cast <void *> (winId()),
&GUID_BATTERY_PERCENTAGE_REMAINING, DEVICE_NOTIFY_WINDOW_HANDLE);
m_power_scheme_notify = RegisterPowerSettingNotification(
reinterpret_cast <void *> (winId()),
&GUID_POWERSCHEME_PERSONALITY, DEVICE_NOTIFY_WINDOW_HANDLE);
}
else
{
UnregisterPowerSettingNotification(m_power_source_notify);
UnregisterPowerSettingNotification(m_battery_perc_notify);
UnregisterPowerSettingNotification(m_power_scheme_notify);
}
# endif
}
bool MessageListener::winEvent(MSG *msg, long *res)
{
if (!m_listen)
return true;
if (msg->message == WM_POWERBROADCAST)
{
# if (WINVER >= 0x0600)
//windows vista, 7
if (msg->wParam == PBT_POWERSETTINGCHANGE)
{
POWERBROADCAST_SETTING *setting = reinterpret_cast
<POWERBROADCAST_SETTING *> (msg->lParam);
if (sizeof(int) == setting->DataLength &&
(setting->PowerSetting == GUID_ACDC_POWER_SOURCE ||
setting->PowerSetting == GUID_BATTERY_PERCENTAGE_REMAINING))
{
// change from ac to battery or back
// or battery cap. comes up and down
emit powerStatusChanged();
}
else if (sizeof(GUID) == setting->DataLength &&
setting->PowerSetting == GUID_POWERSCHEME_PERSONALITY)
{
emit powerSchemeChanged();
}
}
# else
// windows 2000 pro - xp
if (msg->wParam == PBT_APMPOWERSTATUSCHANGE)
{
// change from ac to batt or back
emit powerStatusChanged();
}
# endif
// do not process this message by Qt
return true;
}
return false;
}
#endif
标签: 管理
网友评论
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


支持(0) 盖楼(回复)