refactor DeviceInfoWidget

- Adds battery widget and real-time battery monitoring
- Creates custom battery widget component for visual battery status display
- Integrates comprehensive battery information including charging state,
current level, connection type (USB/USB-C), and power consumption
- Implements automatic battery status updates every 30 seconds to keep
information current during device connection
- Refactors battery data retrieval into separate service function for
better code organization and reusability
- Enhances device info header with charging status, power consumption,
and connection type indicators alongside visual battery widget
This commit is contained in:
uncor3
2025-09-26 17:27:03 +00:00
parent 4f5417cbcc
commit 43aa783433
7 changed files with 447 additions and 87 deletions
+133
View File
@@ -0,0 +1,133 @@
// https://github.com/p-dobrzynski-dev/QtCustomWidgets/blob/master/batterywidget.cpp
#include "batterywidget.h"
#include <QDebug>
#include <QFontMetrics>
#include <QPainter>
#include <QPainterPath>
#include <QResizeEvent>
BatteryWidget::BatteryWidget(float value, bool isCharging, QWidget *parent)
: QWidget(parent), m_value(value), m_isCharging(isCharging)
{
setMinimumSize(50, 40);
setMaximumSize(60, 40);
}
void BatteryWidget::resizeEvent(QResizeEvent *)
{
widgetFrame = this->rect();
widgetFrame.setSize(QSize(widgetFrame.width(), widgetFrame.height() / 2));
widgetFrame.moveTop(widgetFrame.center().y());
float scaleValue = 0.95;
QSizeF mainBatteryFrameSize =
QSizeF(widgetFrame.width() * scaleValue, widgetFrame.height());
mainBatteryFrame.setSize(mainBatteryFrameSize);
mainBatteryFrame.moveTopLeft(widgetFrame.topLeft());
QSizeF tipBatteryFrameSize =
QSizeF(widgetFrame.width() / 3, widgetFrame.height() / 2);
tipBatteryFrame.setSize(tipBatteryFrameSize);
QPointF tipBatteryFramePoint =
QPointF(widgetFrame.topRight().x() - tipBatteryFrameSize.width(),
widgetFrame.topRight().y() + tipBatteryFrameSize.height() / 2);
tipBatteryFrame.moveTopLeft(tipBatteryFramePoint);
float batteryLevelOffset = mainBatteryFrame.height() / 20;
QSizeF batteryLevelFrameSize =
QSizeF(mainBatteryFrame.width() - 2 * batteryLevelOffset,
mainBatteryFrame.height() - 2 * batteryLevelOffset);
batteryLevelFrame.setSize(batteryLevelFrameSize);
QPointF batteryFramePoint =
QPointF(mainBatteryFrame.topLeft().x() + batteryLevelOffset,
mainBatteryFrame.topLeft().y() + batteryLevelOffset);
batteryLevelFrame.moveTopLeft(batteryFramePoint);
}
void BatteryWidget::setValue(float newValue)
{
m_value = newValue;
this->update();
}
float BatteryWidget::getValue() const { return m_value; }
void BatteryWidget::setChargingState(bool state)
{
m_isCharging = state;
this->update();
this->repaint();
}
void BatteryWidget::updateContext(bool isCharging, float newValue)
{
m_isCharging = isCharging;
m_value = newValue;
this->update();
this->repaint();
}
bool BatteryWidget::getChargingState() { return m_isCharging; }
void BatteryWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPen pen = QPen(Qt::red);
QBrush brush = QBrush(Qt::white);
painter.setPen(pen);
// Drawing battery frame
float widgetCorner = widgetFrame.height() / 15;
QPainterPath FramePath;
FramePath.setFillRule(Qt::WindingFill);
FramePath.addRoundedRect(mainBatteryFrame, widgetCorner, widgetCorner);
FramePath.addRoundedRect(tipBatteryFrame, widgetCorner, widgetCorner);
FramePath = FramePath.simplified();
pen.setColor(Qt::gray);
pen.setWidth(widgetFrame.width() / 75);
painter.setPen(pen);
painter.drawPath(FramePath);
painter.setBrush(QBrush(QColor("#44bd32")));
painter.setPen(Qt::NoPen);
QRectF batteryLevelRect = QRectF();
QSize batterySizeRect =
QSize(batteryLevelFrame.width() * m_value / m_maxValue,
batteryLevelFrame.height());
batteryLevelRect.setSize(batterySizeRect);
batteryLevelRect.moveTo(batteryLevelFrame.topLeft());
painter.drawRoundedRect(batteryLevelRect, widgetCorner, widgetCorner);
pen.setColor(Qt::white);
painter.setPen(pen);
QFont textFont = QFont();
textFont.setPixelSize(widgetFrame.height() / 2);
painter.setFont(textFont);
QFontMetrics fm(textFont);
QString percentageLevelString = QString("%1%").arg(m_value);
float textWidth = fm.horizontalAdvance(percentageLevelString);
float textHeight = fm.height();
QPointF textPosition = QPointF(widgetFrame.center().x() - textWidth / 2,
widgetFrame.center().y() + textHeight / 3);
painter.drawText(textPosition, percentageLevelString);
float chargerSize = widgetFrame.height() / 2;
// if (isCharging) {
// QPixmap pixmap(":/img/charge.png");
// painter.drawPixmap(widgetFrame.center().x() - chargerSize * 1.5,
// widgetFrame.top() + chargerSize / 2, chargerSize,
// chargerSize, pixmap);
// }
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef BATTERYWIDGET_H
#define BATTERYWIDGET_H
#include <QWidget>
class BatteryWidget : public QWidget
{
Q_OBJECT
public:
BatteryWidget(float value, bool isCharging, QWidget *parent);
bool getChargingState();
void setChargingState(bool state);
void updateContext(bool isCharging, float newValue);
// New methods for value management
void setValue(float newValue);
float getValue() const;
private:
QRectF widgetFrame;
QRectF mainBatteryFrame;
QRectF tipBatteryFrame;
QRectF batteryLevelFrame;
bool m_isCharging = false;
float m_value = 0.0f;
float m_minValue = 0.0f;
float m_maxValue = 100.0f;
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
};
#endif // BATTERYWIDGET_H
+43
View File
@@ -0,0 +1,43 @@
#include "../../iDescriptor.h"
#include "plist/plist.h"
#include <QDebug>
#include <libimobiledevice/diagnostics_relay.h>
#include <string>
void get_battery_info(std::string productType, idevice_t idevice,
bool is_iphone, plist_t &diagnostics)
{
diagnostics_relay_client_t diagnostics_client = nullptr;
try {
if (diagnostics_relay_client_start_service(idevice, &diagnostics_client,
nullptr) !=
DIAGNOSTICS_RELAY_E_SUCCESS) {
qDebug() << "Failed to start diagnostics relay service.";
return;
}
bool newerThaniPhone8 =
is_product_type_newer(productType, std::string("iPhone8,1"));
const char *batteryQuery =
is_iphone
? newerThaniPhone8 ? "AppleSmartBattery" : "AppleARMPMUCharger"
: "AppleARMPMUCharger";
if (diagnostics_relay_query_ioregistry_entry(
diagnostics_client, nullptr, batteryQuery, &diagnostics) !=
DIAGNOSTICS_RELAY_E_SUCCESS &&
!diagnostics) {
qDebug()
<< "Failed to query diagnostics relay for AppleARMPMUCharger.";
if (diagnostics_client)
diagnostics_relay_client_free(diagnostics_client);
}
} catch (const std::exception &e) {
if (diagnostics_client)
diagnostics_relay_client_free(diagnostics_client);
qDebug() << "Exception in get_battery_info: " << e.what();
}
}
+63 -80
View File
@@ -36,8 +36,8 @@ std::string safeGetXML(const char *key, pugi::xml_node dict)
// TODO: return tyype
DeviceInfo fullDeviceInfo(const pugi::xml_document &doc,
afc_client_t &afcClient, plist_t &diagnostics,
DeviceInfo &d)
afc_client_t &afcClient,
IDescriptorInitDeviceResult &result)
{
pugi::xml_node dict = doc.child("plist").child("dict");
auto safeGet = [&](const char *key) -> std::string {
@@ -67,7 +67,7 @@ DeviceInfo fullDeviceInfo(const pugi::xml_document &doc,
}
return false;
};
DeviceInfo &d = result.deviceInfo;
d.deviceName = safeGet("DeviceName");
d.deviceClass = safeGet("DeviceClass");
d.deviceColor = safeGet("DeviceColor");
@@ -115,38 +115,71 @@ DeviceInfo fullDeviceInfo(const pugi::xml_document &doc,
DeviceInfo::ActivationState::Unactivated; // Default value
}
// TODO:RegionInfo: LL/A
d.productType = parse_product_type(safeGet("ProductType"));
std::string rawProductType = safeGet("ProductType");
d.productType = parse_product_type(rawProductType);
d.rawProductType = rawProductType;
d.jailbroken = detect_jailbroken(afcClient);
d.is_iPhone = safeGet("DeviceClass") == "iPhone";
uint64_t cycleCount;
plist_get_uint_val(
PlistNavigator(diagnostics)["IORegistry"]["BatteryData"]["CycleCount"],
&cycleCount);
/*BatteryInfo*/
plist_t diagnostics = nullptr;
get_battery_info(rawProductType, result.device, d.is_iPhone, diagnostics);
if (!diagnostics) {
qDebug() << "Failed to get diagnostics plist.";
return d;
}
char *batterySerialNumber = nullptr;
plist_get_string_val(
plist_print(diagnostics);
uint64_t cycleCount =
PlistNavigator(diagnostics)["IORegistry"]["BatteryData"]["CycleCount"]
.getUInt();
std::string batterySerialNumber =
PlistNavigator(
diagnostics)["IORegistry"]["BatteryData"]["BatterySerialNumber"],
&batterySerialNumber);
uint64_t designCapacity = 0;
plist_get_uint_val(
diagnostics)["IORegistry"]["BatteryData"]["BatterySerialNumber"]
.getString();
uint64_t designCapacity =
PlistNavigator(
diagnostics)["IORegistry"]["BatteryData"]["DesignCapacity"],
&designCapacity);
diagnostics)["IORegistry"]["BatteryData"]["DesignCapacity"]
.getUInt();
uint64_t absoluteCapacity = 0;
plist_get_uint_val(
PlistNavigator(diagnostics)["IORegistry"]["AbsoluteCapacity"],
&absoluteCapacity);
uint64_t appleRawCurrentCapacity =
PlistNavigator(diagnostics)["IORegistry"]["AppleRawCurrentCapacity"]
.getUInt();
d.batteryInfo.health =
QString::number((absoluteCapacity * 100) / designCapacity) + "%";
QString::number((appleRawCurrentCapacity * 100) / designCapacity) + "%";
d.batteryInfo.cycleCount = cycleCount;
d.batteryInfo.serialNumber = batterySerialNumber
d.batteryInfo.serialNumber = !batterySerialNumber.empty()
? batterySerialNumber
: "Error retrieving serial number";
d.batteryInfo.isCharging =
PlistNavigator(diagnostics)["IORegistry"]["IsCharging"].getBool();
d.batteryInfo.fullyCharged =
PlistNavigator(diagnostics)["IORegistry"]["FullyCharged"].getBool();
d.batteryInfo.currentBatteryLevel =
PlistNavigator(diagnostics)["IORegistry"]["CurrentCapacity"].getUInt();
d.batteryInfo.usbConnectionType =
PlistNavigator(
diagnostics)["IORegistry"]["AdapterDetails"]["Description"]
.getString() == "usb type-c"
? BatteryInfo::ConnectionType::USB_TYPEC
: BatteryInfo::ConnectionType::USB;
d.batteryInfo.adapterVoltage =
PlistNavigator(diagnostics)["IORegistry"]["AppleRawAdapterDetails"][0]
["AdapterVoltage"]
.getUInt();
d.batteryInfo.watts =
PlistNavigator(
diagnostics)["IORegistry"]["AppleRawAdapterDetails"][0]["Watts"]
.getUInt();
plist_free(diagnostics);
diagnostics = nullptr;
@@ -167,7 +200,6 @@ IDescriptorInitDeviceResult init_idescriptor_device(const char *udid)
// LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING = -19,
lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
lockdownd_service_descriptor_t lockdownService = nullptr;
diagnostics_relay_client_t diagnostics_client = nullptr;
afc_client_t afcClient = nullptr;
try {
idevice_error_t ret = idevice_new_with_options(&result.device, udid,
@@ -211,13 +243,6 @@ IDescriptorInitDeviceResult init_idescriptor_device(const char *udid)
return result;
}
if (diagnostics_relay_client_start_service(
result.device, &diagnostics_client, nullptr) !=
DIAGNOSTICS_RELAY_E_SUCCESS) {
qDebug() << "Failed to start diagnostics relay service.";
return result;
}
pugi::xml_document infoXml;
get_device_info_xml(udid, 0, 0, infoXml, client, result.device);
@@ -232,62 +257,20 @@ IDescriptorInitDeviceResult init_idescriptor_device(const char *udid)
return result;
}
plist_t diagnostics = nullptr;
std::string productType =
safeGetXML("ProductType", infoXml.child("plist").child("dict"));
bool is_iphone =
safeGetXML("DeviceClass", infoXml.child("plist").child("dict")) ==
"iPhone";
if (is_iphone) {
qDebug() << "iPhone is newer than iPhone 8 ?"
<< is_product_type_newer(productType,
std::string("iPhone10,1"));
}
const char *batteryQuery =
is_iphone
? is_product_type_newer(productType, std::string("iPhone8,1"))
? "AppleSmartBattery"
: "AppleARMPMUCharger"
: "AppleARMPMUCharger";
// TODO: iPhone 8 and above should query AppleSmartBattery
// TODO: try catch here
if (diagnostics_relay_query_ioregistry_entry(
diagnostics_client, nullptr, batteryQuery, &diagnostics) !=
DIAGNOSTICS_RELAY_E_SUCCESS &&
!diagnostics) {
qDebug()
<< "Failed to query diagnostics relay for AppleARMPMUCharger.";
// Clean up resources before returning
// if (afcClient)
// afc_client_free(afcClient);
if (lockdownService)
lockdownd_service_descriptor_free(lockdownService);
if (client)
lockdownd_client_free(client);
if (diagnostics_client)
diagnostics_relay_client_free(diagnostics_client);
return result;
}
// if (result.device) idevice_free(result.device);
fullDeviceInfo(infoXml, afcClient, diagnostics, result.deviceInfo);
fullDeviceInfo(infoXml, afcClient, result);
result.afcClient = afcClient;
result.success = true;
// TODO: cleanup needed ?
// if (afcClient)
// afc_client_free(afcClient);
// if (lockdownService)
// lockdownd_service_descriptor_free(lockdownService);
// if (client)
// lockdownd_client_free(client);
// if (diagnostics_client)
// diagnostics_relay_client_free(diagnostics_client);
if (lockdownService)
lockdownd_service_descriptor_free(lockdownService);
if (client)
lockdownd_client_free(client);
return result;
} catch (const std::exception &e) {
+101 -5
View File
@@ -1,4 +1,5 @@
#include "deviceinfowidget.h"
#include "batterywidget.h"
#include "diskusagewidget.h"
#include "fileexplorerwidget.h"
#include "iDescriptor.h"
@@ -16,6 +17,7 @@
#include <QPushButton>
#include <QResizeEvent>
#include <QTabWidget>
#include <QTimer>
#include <QVBoxLayout>
// A custom QGraphicsView that keeps the content fitted with aspect ratio on
@@ -39,7 +41,7 @@ protected:
};
DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
: QWidget(parent), device(device)
: QWidget(parent), m_device(device)
{
// Main layout with horizontal orientation
QHBoxLayout *mainLayout = new QHBoxLayout(this);
@@ -74,15 +76,49 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
// Header
QWidget *headerWidget = new QWidget();
headerWidget->setObjectName("headerWidget");
headerWidget->setStyleSheet("QWidget#headerWidget { "
" border: 1px solid #ccc; "
" border-radius: 6px; "
"}");
QHBoxLayout *headerLayout = new QHBoxLayout(headerWidget);
// headerLayout->setContentsMargins(0, 0, 0, 0);
// headerLayout->setSpacing(10);
headerLayout->setContentsMargins(10, 10, 10, 10);
headerLayout->setSpacing(15);
QLabel *devProductType =
new QLabel(QString::fromStdString(device->deviceInfo.productType));
devProductType->setStyleSheet("font-size: 1rem; font-weight: bold;");
QLabel *diskCapacityLabel = new QLabel(
QString::number(device->deviceInfo.diskInfo.totalDiskCapacity /
(1000 * 1000 * 1000)) +
" GB");
m_chargingStatusLabel =
new QLabel(device->deviceInfo.batteryInfo.isCharging ? "Charging"
: "Not Charging");
m_chargingStatusLabel->setStyleSheet("font-size: 1rem;");
m_chargingWattsLabel =
new QLabel(QString::number(device->deviceInfo.batteryInfo.watts) + "W");
m_cableTypeLabel =
new QLabel(device->deviceInfo.batteryInfo.usbConnectionType ==
BatteryInfo::ConnectionType::USB
? "USB"
: "USB-C");
m_batteryWidget =
new BatteryWidget(device->deviceInfo.batteryInfo.currentBatteryLevel,
device->deviceInfo.batteryInfo.isCharging, this);
headerLayout->addWidget(devProductType);
headerLayout->addWidget(diskCapacityLabel);
headerLayout->addWidget(m_chargingStatusLabel);
headerLayout->addWidget(m_batteryWidget);
headerLayout->addWidget(m_chargingWattsLabel);
headerLayout->addWidget(m_cableTypeLabel);
infoLayout->addWidget(headerWidget);
// add spacer
infoLayout->addSpacerItem(
@@ -102,6 +138,7 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
gridLayout->setColumnStretch(1, 1); // Allow value column to stretch
gridLayout->setColumnStretch(
3, 1); // Allow value column for right side to stretch
gridLayout->setContentsMargins(17, 17, 17, 17);
gridWidget->setLayout(gridLayout);
QList<QPair<QString, QWidget *>> infoItems;
@@ -229,6 +266,11 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
rightSideLayout->addWidget(new DiskUsageWidget(device, this));
rightSideLayout->setAlignment(Qt::AlignCenter);
mainLayout->addLayout(rightSideLayout, 2); // Stretch factor 2
m_updateTimer = new QTimer(this);
connect(m_updateTimer, &QTimer::timeout, this,
&DeviceInfoWidget::updateBatteryInfo);
m_updateTimer->start(30000); // Update every 30 seconds
}
void DeviceInfoWidget::onBatteryMoreClicked()
@@ -237,9 +279,9 @@ void DeviceInfoWidget::onBatteryMoreClicked()
msgBox.setWindowTitle("Battery Details");
QString details =
"Battery Cycle Count: " +
QString::number(device->deviceInfo.batteryInfo.cycleCount) + "\n" +
QString::number(m_device->deviceInfo.batteryInfo.cycleCount) + "\n" +
"Battery Serial Number: " +
QString::fromStdString(device->deviceInfo.batteryInfo.serialNumber);
QString::fromStdString(m_device->deviceInfo.batteryInfo.serialNumber);
msgBox.setText(details);
msgBox.exec();
}
@@ -265,4 +307,58 @@ QPixmap DeviceInfoWidget::getDeviceIcon(const std::string &productType)
}
return icon;
}
void DeviceInfoWidget::updateBatteryInfo()
{
qDebug() << "Updating battery info...";
plist_t diagnostics = nullptr;
get_battery_info(m_device->deviceInfo.rawProductType, m_device->device,
m_device->deviceInfo.is_iPhone, diagnostics);
if (!diagnostics) {
qDebug() << "Failed to get diagnostics plist.";
return;
}
/*DATA*/
DeviceInfo &d = m_device->deviceInfo;
d.batteryInfo.isCharging =
PlistNavigator(diagnostics)["IORegistry"]["IsCharging"].getBool();
d.batteryInfo.fullyCharged =
PlistNavigator(diagnostics)["IORegistry"]["FullyCharged"].getBool();
d.batteryInfo.currentBatteryLevel =
PlistNavigator(diagnostics)["IORegistry"]["CurrentCapacity"].getUInt();
d.batteryInfo.usbConnectionType =
PlistNavigator(
diagnostics)["IORegistry"]["AdapterDetails"]["Description"]
.getString() == "usb type-c"
? BatteryInfo::ConnectionType::USB_TYPEC
: BatteryInfo::ConnectionType::USB;
d.batteryInfo.adapterVoltage =
PlistNavigator(diagnostics)["IORegistry"]["AppleRawAdapterDetails"][0]
["AdapterVoltage"]
.getUInt();
d.batteryInfo.watts =
PlistNavigator(
diagnostics)["IORegistry"]["AppleRawAdapterDetails"][0]["Watts"]
.getUInt();
/*UI*/
m_chargingStatusLabel->setText(d.batteryInfo.isCharging ? "Charging"
: "Not Charging");
m_chargingWattsLabel->setText(QString::number(d.batteryInfo.watts) + "W");
m_cableTypeLabel->setText(d.batteryInfo.usbConnectionType ==
BatteryInfo::ConnectionType::USB
? "USB"
: "USB-C");
m_batteryWidget->updateContext(d.batteryInfo.isCharging,
d.batteryInfo.currentBatteryLevel);
}
+10 -1
View File
@@ -1,6 +1,9 @@
#ifndef DEVICEINFOWIDGET_H
#define DEVICEINFOWIDGET_H
#include "batterywidget.h"
#include "iDescriptor.h"
#include <QLabel>
#include <QTimer>
#include <QWidget>
class DeviceInfoWidget : public QWidget
@@ -15,7 +18,13 @@ private slots:
private:
QPixmap getDeviceIcon(const std::string &productType);
iDescriptorDevice *device;
iDescriptorDevice *m_device;
QTimer *m_updateTimer;
void updateBatteryInfo();
QLabel *m_chargingStatusLabel;
QLabel *m_chargingWattsLabel;
QLabel *m_cableTypeLabel;
BatteryWidget *m_batteryWidget;
};
#endif // DEVICEINFOWIDGET_H
+62 -1
View File
@@ -29,6 +29,15 @@ struct BatteryInfo {
// uint64_t maxCapacity;
// uint64_t fullChargeCapacity;
std::string serialNumber;
bool isCharging;
bool fullyCharged;
uint64_t currentBatteryLevel;
enum class ConnectionType {
USB,
USB_TYPEC,
} usbConnectionType;
uint64_t adapterVoltage; // in mV
uint64_t watts;
};
//! IOS 12
@@ -59,6 +68,7 @@ struct DeviceInfo {
} activationState;
std::string activationStateAcknowledged;
std::string productType;
std::string rawProductType;
bool jailbroken;
std::string basebandActivationTicketVersion;
std::string basebandCertId;
@@ -120,6 +130,7 @@ struct DeviceInfo {
bool productionDevice;
BatteryInfo batteryInfo;
DiskInfo diskInfo;
bool is_iPhone;
};
struct iDescriptorDevice {
@@ -132,6 +143,7 @@ struct iDescriptorDevice {
clients are not long lived, so do not assume this will be valid
*/
afc_client_t afcClient;
bool is_iPhone;
};
struct IDescriptorInitDeviceResult {
@@ -248,6 +260,7 @@ private:
public:
PlistNavigator(plist_t node) : current_node(node) {}
// Existing dictionary key access
PlistNavigator operator[](const char *key)
{
if (!current_node || plist_get_node_type(current_node) != PLIST_DICT) {
@@ -257,8 +270,53 @@ public:
return PlistNavigator(next);
}
// Add array index access
PlistNavigator operator[](int index)
{
if (!current_node || plist_get_node_type(current_node) != PLIST_ARRAY) {
return PlistNavigator(nullptr);
}
if (index < 0 ||
index >= static_cast<int>(plist_array_get_size(current_node))) {
return PlistNavigator(nullptr);
}
plist_t next = plist_array_get_item(current_node, index);
return PlistNavigator(next);
}
operator plist_t() const { return current_node; }
bool valid() const { return current_node != nullptr; }
// Your existing helper methods
bool getBool() const
{
if (!current_node)
return false;
uint8_t value = false;
plist_get_bool_val(current_node, &value);
return value;
}
uint64_t getUInt() const
{
if (!current_node)
return 0;
uint64_t value = 0;
plist_get_uint_val(current_node, &value);
return value;
}
std::string getString() const
{
if (!current_node)
return "";
char *value = nullptr;
plist_get_string_val(current_node, &value);
std::string result = value ? value : "";
if (value)
free(value);
return result;
}
};
afc_error_t safe_afc_read_directory(afc_client_t afcClient, idevice_t device,
@@ -376,4 +434,7 @@ bool query_mobile_gestalt(iDescriptorDevice *id_device, const QStringList &keys,
uint32_t &xml_size, char *&xml_data);
;
std::string safeGetXML(const char *key, pugi::xml_node dict);
std::string safeGetXML(const char *key, pugi::xml_node dict);
void get_battery_info(std::string productType, idevice_t idevice,
bool is_iphone, plist_t &diagnostics);