extend smart stuff, add its own dialog, add action to trigger it etc.

svn path=/trunk/extragear/sysadmin/partitionmanager/; revision=1108004
This commit is contained in:
Volker Lanz 2010-03-27 13:47:32 +00:00
parent 597a574df5
commit 180fa4643d
20 changed files with 1574 additions and 145 deletions

View File

@ -25,6 +25,15 @@
<entry name="treeLogColumnVisible" type="IntList" hidden="true">
<default>1,1,1</default>
</entry>
<entry name="treeSmartAttributesColumnWidths" type="IntList" hidden="true">
<default>32,430,96,96,64,64,64,96,96,96</default>
</entry>
<entry name="treeSmartAttributesColumnPositions" type="IntList" hidden="true">
<default>0,1,2,3,4,5,6,7,8,9</default>
</entry>
<entry name="treeSmartAttributesColumnVisible" type="IntList" hidden="true">
<default>1,1,0,0,0,0,0,0,1,1</default>
</entry>
<entry name="firstRun" type="Bool">
<label context="@label">Is this the first time KDE Partition Manager is being run?</label>
<default>true</default>

View File

@ -20,6 +20,7 @@
#include "core/device.h"
#include "core/partitiontable.h"
#include "core/smartstatus.h"
#include <kdebug.h>
#include <klocale.h>
@ -42,7 +43,7 @@ Device::Device(const QString& name, const QString& devicenode, qint32 heads, qin
m_Cylinders(cylinders),
m_SectorSize(sectorSize),
m_IconName(iconname.isEmpty() ? "drive-hardisk" : iconname),
m_SmartStatus(devicenode)
m_SmartStatus(new SmartStatus(devicenode))
{
}

View File

@ -23,8 +23,6 @@
#include "util/libpartitionmanagerexport.h"
#include "core/smartstatus.h"
#include <QString>
#include <QObject>
#include <qglobal.h>
@ -32,6 +30,7 @@
class PartitionTable;
class CreatePartitionTableOperation;
class CoreBackend;
class SmartStatus;
/** @brief A device.
@ -70,7 +69,8 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT Device : public QObject
void setIconName(const QString& name) { m_IconName = name; }
const QString& iconName() const { return m_IconName; } /**< @return suggested icon name for this Device */
const SmartStatus& smartStatus() const { return m_SmartStatus; }
SmartStatus& smartStatus() { return *m_SmartStatus; }
const SmartStatus& smartStatus() const { return *m_SmartStatus; }
protected:
void setPartitionTable(PartitionTable* ptable) { m_PartitionTable = ptable; }
@ -84,7 +84,7 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT Device : public QObject
qint32 m_Cylinders;
qint32 m_SectorSize;
QString m_IconName;
SmartStatus m_SmartStatus;
SmartStatus* m_SmartStatus;
};
#endif

252
src/core/smartattribute.cpp Normal file
View File

@ -0,0 +1,252 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "core/smartattribute.h"
#include "core/smartstatus.h"
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <atasmart.h>
static QString getAttrName(qint32 id);
static QString getAttrDescription(qint32 id);
static QString getPrettyValue(qint64 value, qint64 unit);
static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a);
static QString getRaw(const uint8_t*);
SmartAttribute::SmartAttribute(const SkSmartAttributeParsedData* a) :
m_Id(a->id),
m_Name(getAttrName(a->id)),
m_Desc(getAttrDescription(a->id)),
m_FailureType(a->prefailure ? PreFailure : OldAge),
m_UpdateType(a->online ? Online : Offline),
m_Current(a->current_value_valid ? a->current_value : -1),
m_Worst(a->worst_value_valid ? a->worst_value : -1),
m_Threshold(a->threshold_valid ? a->threshold : -1),
m_Raw(getRaw(a->raw)),
m_Assessment(getAssessment(a)),
m_Value(getPrettyValue(a->pretty_value, a->pretty_unit))
{
}
QString SmartAttribute::assessmentToString(Assessment a)
{
switch(a)
{
case Failing:
return i18nc("@item:intable", "failing");
case HasFailed:
return i18nc("@item:intable", "has failed");
case Warning:
return i18nc("@item:intable", "warning");
case Good:
return i18nc("@item:intable", "good");
case NotApplicable:
default:
return i18nc("@item:intable not applicable", "N/A");
}
}
static QString getPrettyValue(qint64 value, qint64 unit)
{
QString rval;
switch (unit)
{
case SK_SMART_ATTRIBUTE_UNIT_MSECONDS:
rval = KGlobal::locale()->formatDuration(value);
break;
case SK_SMART_ATTRIBUTE_UNIT_SECTORS:
rval = i18ncp("@item:intable", "%1 sector", "%1 sectors", value);
break;
case SK_SMART_ATTRIBUTE_UNIT_MKELVIN:
rval = SmartStatus::tempToString(value);
break;
case SK_SMART_ATTRIBUTE_UNIT_NONE:
rval = KGlobal::locale()->formatNumber(value, 0);
break;
case SK_SMART_ATTRIBUTE_UNIT_UNKNOWN:
default:
rval = i18nc("@item:intable not applicable", "N/A");
break;
}
return rval;
}
typedef struct
{
qint32 id;
const QString name;
const QString desc;
} AttrDetails;
static const AttrDetails* attrDetails()
{
static const AttrDetails details[] =
{
{ 1, i18nc("SMART attr name", "Read Error Rate"), i18nc("SMART attr description", "Rate of hardware read errors while reading data from the disk surface.") },
{ 2, i18nc("SMART attr name", "Throughput Performance"), i18nc("SMART attr description", "Overall (general) throughput performance of a hard disk drive. If the value of this attribute is decreasing there is a high probability that there is a problem with the disk.") },
{ 3, i18nc("SMART attr name", "Spin-Up Time"), i18nc("SMART attr description", "Average time of spindle spin up from zero RPM to fully operational.") },
{ 4, i18nc("SMART attr name", "Start/Stop Count"), i18nc("SMART attr description", "A tally of spindle start/stop cycles.") },
{ 5, i18nc("SMART attr name", "Reallocated Sectors Count"), i18nc("SMART attr description", "Count of reallocated sectors. When the hard drive finds a read/write/verification error, it marks this sector as &quot;reallocated&quot; and transfers data to a special reserved area (spare area).") },
{ 6, i18nc("SMART attr name", "Read Channel Margin"), i18nc("SMART attr description", "Margin of a channel while reading data. The function of this attribute is not specified.") },
{ 7, i18nc("SMART attr name", "Seek Error Rate"), i18nc("SMART attr description", "Rate of seek errors of the magnetic heads. If there is a partial failure in the mechanical positioning system, then seek errors will arise.") },
{ 8, i18nc("SMART attr name", "Seek Time Performance"), i18nc("SMART attr description", "Average performance of seek operations of the magnetic heads. If this attribute is decreasing, it is a sign of problems in the mechanical subsystem.") },
{ 9, i18nc("SMART attr name", "Power-On Hours"), i18nc("SMART attr description", "Count of hours in power-on state.") },
{ 10, i18nc("SMART attr name", "Spin Retry Count"), i18nc("SMART attr description", "Count of retry of spin start attempts if the first attempt was unsuccessful. An increase of this attribute value is a sign of problems in the hard disk mechanical subsystem.") },
{ 11, i18nc("SMART attr name", "Recalibration Retries"), i18nc("SMART attr description", "Count of recalibrations requested if the first attempt was unsuccessful. An increase of this attribute value is a sign of problems in the hard disk mechanical subsystem.") },
{ 12, i18nc("SMART attr name", "Power Cycle Count"), i18nc("SMART attr description", "Count of full hard disk power on/off cycles.") },
{ 13, i18nc("SMART attr name", "Soft Read Error Rate"), i18nc("SMART attr description", "Uncorrected read errors reported to the operating system.") },
{ 183, i18nc("SMART attr name", "SATA Downshift Error Count"), i18nc("SMART attr description", "Western Digital and Samsung attribute.") },
{ 184, i18nc("SMART attr name", "End-to-End Error"), i18nc("SMART attr description", "Part of HP's SMART IV technology: After transferring through the cache RAM data buffer the parity data between the host and the hard drive did not match.") },
{ 185, i18nc("SMART attr name", "Head Stability"), i18nc("SMART attr description", "Western Digital attribute.") },
{ 186, i18nc("SMART attr name", "Induced Op-Vibration Detection"), i18nc("SMART attr description", "Western Digital attribute.") },
{ 187, i18nc("SMART attr name", "Reported Uncorrectable Errors"), i18nc("SMART attr description", "Count of errors that could not be recovered using hardware ECC.") },
{ 188, i18nc("SMART attr name", "Command Timeout"), i18nc("SMART attr description", "Count of aborted operations due to HDD timeout.") },
{ 189, i18nc("SMART attr name", "High Fly Writes"), i18nc("SMART attr description", "Count of fly height errors detected.") },
{ 190, i18nc("SMART attr name", "Temperature Difference From 100"), i18nc("SMART attr description", "Value is equal to (100 &ndash; temp. °C), allowing manufacturer to set a minimum threshold which corresponds to a maximum temperature.") },
{ 191, i18nc("SMART attr name", "G-sense Error Rate"), i18nc("SMART attr description", "Count of errors resulting from externally-induced shock and vibration.") },
{ 192, i18nc("SMART attr name", "Power Off Retract Count"), i18nc("SMART attr description", "Count of power-off or emergency retract cycles") },
{ 193, i18nc("SMART attr name", "Load Cycle Count"), i18nc("SMART attr description", "Count of load/unload cycles into head landing zone position.") },
{ 194, i18nc("SMART attr name", "Temperature"), i18nc("SMART attr description", "Current internal temperature.") },
{ 195, i18nc("SMART attr name", "Hardware ECC Recovered"), i18nc("SMART attr description", "Count of errors that could be recovered using hardware ECC.") },
{ 196, i18nc("SMART attr name", "Reallocation Event Count"), i18nc("SMART attr description", "Count of remap operations. The raw value of this attribute shows the total number of attempts to transfer data from reallocated sectors to a spare area.") },
{ 197, i18nc("SMART attr name", "Current Pending Sector Count"), i18nc("SMART attr description", "Number of &quot;unstable&quot; sectors (waiting to be remapped, because of read errors).") },
{ 198, i18nc("SMART attr name", "Uncorrectable Sector Count"), i18nc("SMART attr description", "Count of uncorrectable errors when reading/writing a sector.") },
{ 199, i18nc("SMART attr name", "UltraDMA CRC Error Count"), i18nc("SMART attr description", "Count of errors in data transfer via the interface cable as determined by ICRC.") },
{ 200, i18nc("SMART attr name", "Multi-Zone Error Rate<br>Write Error Rate"), i18nc("SMART attr description", "The total number of errors when writing a sector.") },
{ 201, i18nc("SMART attr name", "Soft Read Error Rate"), i18nc("SMART attr description", "Number of off-track errors.") },
{ 202, i18nc("SMART attr name", "Data Address Mark Errors"), i18nc("SMART attr description", "Number of Data Address Mark errors (or vendor-specific).") },
{ 203, i18nc("SMART attr name", "Run Out Cancel"), i18nc("SMART attr description", "Number of ECC errors") },
{ 204, i18nc("SMART attr name", "Soft ECC Correction"), i18nc("SMART attr description", "Number of errors corrected by software ECC") },
{ 205, i18nc("SMART attr name", "Thermal Asperity Rate"), i18nc("SMART attr description", "Number of errors due to high temperaure.") },
{ 206, i18nc("SMART attr name", "Flying Height"), i18nc("SMART attr description", "Height of heads above the disk surface. A flying height that is too low increases the chances of a head crash while a flying height that is too high increases the chances of a read/write error.") },
{ 207, i18nc("SMART attr name", "Spin High Current"), i18nc("SMART attr description", "Amount of surge current used to spin up the drive.") },
{ 208, i18nc("SMART attr name", "Spin Buzz"), i18nc("SMART attr description", "Number of buzz routines needed to spin up the drive due to insufficient power.") },
{ 209, i18nc("SMART attr name", "Offline Seek Performance"), i18nc("SMART attr description", "Drive's seek performance during its internal tests.") },
{ 211, i18nc("SMART attr name", "Vibration During Write"), i18nc("SMART attr description", "Vibration During Write") },
{ 212, i18nc("SMART attr name", "Shock During Write"), i18nc("SMART attr description", "Shock During Write") },
{ 220, i18nc("SMART attr name", "Disk Shift"), i18nc("SMART attr description", "Distance the disk has shifted relative to the spindle (usually due to shock or temperature).") },
{ 221, i18nc("SMART attr name", "G-Sense Error Rate"), i18nc("SMART attr description", "The number of errors resulting from externally-induced shock and vibration.") },
{ 222, i18nc("SMART attr name", "Loaded Hours"), i18nc("SMART attr description", "Time spent operating under data load.") },
{ 223, i18nc("SMART attr name", "Load/Unload Retry Count"), i18nc("SMART attr description", "Number of times head changes position.") },
{ 224, i18nc("SMART attr name", "Load Friction"), i18nc("SMART attr description", "Resistance caused by friction in mechanical parts while operating.") },
{ 225, i18nc("SMART attr name", "Load/Unload Cycle Count"), i18nc("SMART attr description", "Total number of load cycles.") },
{ 226, i18nc("SMART attr name", "Load-In Time"), i18nc("SMART attr description", "Total time of loading on the magnetic heads actuator (time not spent in parking area).") },
{ 227, i18nc("SMART attr name", "Torque Amplification Count"), i18nc("SMART attr description", "Number of attempts to compensate for platter speed variations.") },
{ 228, i18nc("SMART attr name", "Power-Off Retract Cycle"), i18nc("SMART attr description", "The number of times the magnetic armature was retracted automatically as a result of cutting power.") },
{ 230, i18nc("SMART attr name", "GMR Head Amplitude"), i18nc("SMART attr description", "Amplitude of &quot;thrashing&quot; (distance of repetitive forward/reverse head motion)") },
{ 231, i18nc("SMART attr name", "Temperature"), i18nc("SMART attr description", "Drive Temperature") },
{ 232, i18nc("SMART attr name", "Endurance Remaining"), i18nc("SMART attr description", "Count of physical erase cycles completed on the drive as a percentage of the maximum physical erase cycles the drive supports") },
{ 233, i18nc("SMART attr name", "Power-On Seconds"), i18nc("SMART attr description", "Time elapsed in the power-on state") },
{ 234, i18nc("SMART attr name", "Unrecoverable ECC Count"), i18nc("SMART attr description", "Count of unrecoverable ECC errors") },
{ 235, i18nc("SMART attr name", "Good Block Rate"), i18nc("SMART attr description", "Count of available reserved blocks as percentage of the total number of reserved blocks") },
{ 240, i18nc("SMART attr name", "Head Flying Hours<br>or Transfer Error Rate (Fujitsu)"), i18nc("SMART attr description", "Time while head is positioning<br>or counts the number of times the link is reset during a data transfer.") },
{ 241, i18nc("SMART attr name", "Total LBAs Written"), i18nc("SMART attr description", "Total LBAs Written") },
{ 242, i18nc("SMART attr name", "Total LBAs Read"), i18nc("SMART attr description", "Total LBAs Read") },
{ 250, i18nc("SMART attr name", "Read Error Retry Rate"), i18nc("SMART attr description", "Number of errors while reading from a disk") },
{ 254, i18nc("SMART attr name", "Free Fall Protection"), i18nc("SMART attr description", "Number of &quot;Free Fall Events&quot; detected") },
{ -1, NULL, NULL }
};
return details;
}
static QString getAttrName(qint32 id)
{
qint32 idx = 0;
while (attrDetails()[idx].id != -1)
{
if (attrDetails()[idx].id == id)
return attrDetails()[idx].name;
idx++;
}
return QString();
}
static QString getAttrDescription(qint32 id)
{
qint32 idx = 0;
while (attrDetails()[idx].id != -1)
{
if (attrDetails()[idx].id == id)
return attrDetails()[idx].desc;
idx++;
}
return QString();
}
static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a)
{
SmartAttribute::Assessment rval = SmartAttribute::NotApplicable;
bool failed = false;
bool hasFailed = false;
if (a->prefailure)
{
if (a->good_now_valid && !a->good_now)
failed = true;
if (a->good_in_the_past_valid && !a->good_in_the_past)
hasFailed = true;
}
else if (a->threshold_valid)
{
if (a->current_value_valid && a->current_value <= a->threshold)
failed = true;
else if (a->worst_value_valid && a->worst_value <= a->threshold)
hasFailed = true;
}
if (failed)
rval = SmartAttribute::Failing;
else if (hasFailed)
rval = SmartAttribute::HasFailed;
else if (a->warn)
rval = SmartAttribute::Warning;
else if (a->good_now_valid)
rval = SmartAttribute::Good;
return rval;
}
static QString getRaw(const uint8_t* raw)
{
QString rval = "0x";
for (qint32 i = 5; i >= 0; i--)
rval += QString("%1").arg(raw[i], 2, 16, QChar('0'));
return rval;
}

86
src/core/smartattribute.h Normal file
View File

@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#if !defined(SMARTATTRIBUTE__H)
#define SMARTATTRIBUTE__H
#include <QString>
struct SkSmartAttributeParsedData;
class SmartAttribute
{
public:
enum FailureType
{
PreFailure,
OldAge
};
enum UpdateType
{
Online,
Offline
};
enum Assessment
{
NotApplicable,
Failing,
HasFailed,
Warning,
Good
};
public:
SmartAttribute(const SkSmartAttributeParsedData* a);
public:
qint32 id() const { return m_Id; }
const QString& name() const { return m_Name; }
const QString& desc() const { return m_Desc; }
FailureType failureType() const { return m_FailureType; }
UpdateType updateType() const { return m_UpdateType; }
qint32 current() const { return m_Current; }
qint32 worst() const { return m_Worst; }
qint32 threshold() const { return m_Threshold; }
const QString& raw() const { return m_Raw; }
Assessment assessment() const { return m_Assessment; }
const QString& value() const { return m_Value; }
QString assessmentToString() const { return assessmentToString(assessment()); }
static QString assessmentToString(Assessment a);
private:
qint32 m_Id;
QString m_Name;
QString m_Desc;
FailureType m_FailureType;
UpdateType m_UpdateType;
qint32 m_Current;
qint32 m_Worst;
qint32 m_Threshold;
QString m_Raw;
Assessment m_Assessment;
QString m_Value;
};
#endif

View File

@ -18,10 +18,14 @@
***************************************************************************/
#include "core/smartstatus.h"
#include "core/smartattribute.h"
#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <QString>
#include <QStringList>
#include <atasmart.h>
#include <errno.h>
@ -30,10 +34,20 @@ SmartStatus::SmartStatus(const QString& device_path) :
m_DevicePath(device_path),
m_InitSuccess(false),
m_Status(false),
m_ModelName(),
m_Serial(),
m_Firmware(),
m_Overall(Bad),
m_SelfTestStatus(Success),
m_Temp(-99),
m_BadSectors(-99),
m_PowerCycles(-99),
m_PoweredOn(-99)
{
update();
}
void SmartStatus::update()
{
SkDisk* skDisk = NULL;
SkBool skSmartStatus = false;
@ -64,10 +78,106 @@ SmartStatus::SmartStatus(const QString& device_path) :
return;
}
const SkIdentifyParsedData* skIdentify;
if (sk_disk_identify_parse(skDisk, &skIdentify) < 0)
kDebug() << "getting identify data failed for " << devicePath() << ": " << strerror(errno);
else
{
setModelName(skIdentify->model);
setFirmware(skIdentify->firmware);
setSerial(skIdentify->serial);
}
const SkSmartParsedData* skParsed;
if (sk_disk_smart_parse(skDisk, &skParsed) < 0)
kDebug() << "parsing disk smart data failed for " << devicePath() << ": " << strerror(errno);
else
{
switch(skParsed->self_test_execution_status)
{
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ABORTED:
setSelfTestStatus(Aborted);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED:
setSelfTestStatus(Interrupted);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_FATAL:
setSelfTestStatus(Fatal);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN:
setSelfTestStatus(ErrorUnknown);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL:
setSelfTestStatus(ErrorEletrical);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO:
setSelfTestStatus(ErrorServo);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ:
setSelfTestStatus(ErrorRead);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING:
setSelfTestStatus(ErrorHandling);
break;
case SK_SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS:
setSelfTestStatus(InProgress);
break;
default:
case SK_SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER:
setSelfTestStatus(Success);
break;
}
}
SkSmartOverall overall;
if (sk_disk_smart_get_overall(skDisk, &overall) < 0)
kDebug() << "getting status failed for " << devicePath() << ": " << strerror(errno);
else
{
switch(overall)
{
case SK_SMART_OVERALL_GOOD:
setOverall(Good);
break;
case SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST:
setOverall(BadPast);
break;
case SK_SMART_OVERALL_BAD_SECTOR:
setOverall(BadSectors);
break;
case SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW:
setOverall(BadNow);
break;
case SK_SMART_OVERALL_BAD_SECTOR_MANY:
setOverall(BadSectorsMany);
break;
default:
case SK_SMART_OVERALL_BAD_STATUS:
setOverall(Bad);
break;
}
}
if (sk_disk_smart_get_temperature(skDisk, &mkelvin) < 0)
kDebug() << "getting temp failed for " << devicePath() << ": " << strerror(errno);
else
setTemp((mkelvin - 273150) / 100);
setTemp(mkelvin);
if (sk_disk_smart_get_bad(skDisk, &skBadSectors) < 0)
kDebug() << "getting bad sectors failed for " << devicePath() << ": " << strerror(errno);
@ -84,6 +194,90 @@ SmartStatus::SmartStatus(const QString& device_path) :
else
setPowerCycles(skPowerCycles);
m_Attributes.clear();
sk_disk_smart_parse_attributes(skDisk, callback, this);
sk_disk_free(skDisk);
setInitSuccess(true);
}
QString SmartStatus::tempToString(qint64 mkelvin)
{
const double celsius = (mkelvin - 273150.0) / 1000.0;
const double fahrenheit = 9.0 * celsius / 5.0 + 32;
return i18nc("@item:intable degrees in Celsius and Fahrenheit", "%1° C / %2° F", KGlobal::locale()->formatNumber(celsius, 1), KGlobal::locale()->formatNumber(fahrenheit, 1));
}
QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s)
{
switch(s)
{
case Aborted:
return i18nc("@item", "Aborted");
case Interrupted:
return i18nc("@item", "Interrupted");
case Fatal:
return i18nc("@item", "Fatal error");
case ErrorUnknown:
return i18nc("@item", "Unknown error");
case ErrorEletrical:
return i18nc("@item", "Eletrical error");
case ErrorServo:
return i18nc("@item", "Servo error");
case ErrorRead:
return i18nc("@item", "Read error");
case ErrorHandling:
return i18nc("@item", "Handling error");
case InProgress:
return i18nc("@item", "Self test in progress");
case Success:
default:
return i18nc("@item", "Success");
}
}
QString SmartStatus::overallAssessmentToString(Overall o)
{
switch(o)
{
case Good:
return i18nc("@item", "Healthy");
case BadPast:
return i18nc("@item", "Has been used outside of its design paramters in the past.");
case BadSectors:
return i18nc("@item", "Has some bad sectors.");
case BadNow:
return i18nc("@item", "Is being used outside of its design paramters right now.");
case BadSectorsMany:
return i18nc("@item", "Has many bad sectors.");
case Bad:
default:
return i18nc("@item", "Disk failure is imminent. Backup all data!");
}
}
void SmartStatus::callback(SkDisk*, const SkSmartAttributeParsedData* a, void* user_data)
{
SmartStatus* self = reinterpret_cast<SmartStatus*>(user_data);
SmartAttribute sm(a);
self->m_Attributes.append(sm);
}

View File

@ -23,39 +23,96 @@
#include <qglobal.h>
#include <QString>
#include <QList>
class SmartAttribute;
struct SkSmartAttributeParsedData;
struct SkDisk;
class SmartStatus
{
public:
enum Overall
{
Good,
BadPast,
BadSectors,
BadNow,
BadSectorsMany,
Bad
};
enum SelfTestStatus
{
Success,
Aborted,
Interrupted,
Fatal,
ErrorUnknown,
ErrorEletrical,
ErrorServo,
ErrorRead,
ErrorHandling,
InProgress
};
public:
typedef QList<SmartAttribute> Attributes;
public:
SmartStatus(const QString& device_path);
public:
void update();
const QString& devicePath() const { return m_DevicePath; }
bool isValid() const { return m_InitSuccess; }
bool status() const { return m_Status; }
qint32 temp() const { return m_Temp; }
const QString& modelName() const { return m_ModelName; }
const QString& serial() const { return m_Serial; }
const QString& firmware() const { return m_Firmware; }
qint64 temp() const { return m_Temp; }
qint64 badSectors() const { return m_BadSectors; }
qint64 powerCycles() const { return m_PowerCycles; }
qint64 poweredOn() const { return m_PoweredOn; }
const Attributes& attributes() const { return m_Attributes; }
Overall overall() const { return m_Overall; }
SelfTestStatus selfTestStatus() const { return m_SelfTestStatus; }
static QString tempToString(qint64 mkelvin);
static QString overallAssessmentToString(Overall o);
static QString selfTestStatusToString(SmartStatus::SelfTestStatus s);
protected:
void setStatus(bool s) { m_Status = s; }
void setTemp(qint32 t) { m_Temp = t; }
void setModelName(const QString& name) { m_ModelName = name; }
void setSerial(const QString& s) { m_Serial = s; }
void setFirmware(const QString& f) { m_Firmware = f; }
void setTemp(qint64 t) { m_Temp = t; }
void setInitSuccess(bool b) { m_InitSuccess = b; }
void setBadSectors(qint64 s) { m_BadSectors = s; }
void setPowerCycles(qint64 p) { m_PowerCycles = p; }
void setPoweredOn(qint64 t) { m_PoweredOn = t; }
void setOverall(Overall o) { m_Overall = o; }
void setSelfTestStatus(SelfTestStatus s) { m_SelfTestStatus = s; }
static void callback(SkDisk* skDisk, const SkSmartAttributeParsedData* a, void* user_data);
private:
const QString m_DevicePath;
bool m_InitSuccess;
bool m_Status;
qint32 m_Temp;
QString m_ModelName;
QString m_Serial;
QString m_Firmware;
Overall m_Overall;
SelfTestStatus m_SelfTestStatus;
qint64 m_Temp;
qint64 m_BadSectors;
qint64 m_PowerCycles;
qint64 m_PoweredOn;
Attributes m_Attributes;
};
#endif

View File

@ -20,6 +20,8 @@
#include "gui/devicepropsdialog.h"
#include "gui/devicepropswidget.h"
#include "gui/smartdialog.h"
#include "core/device.h"
#include "core/partitiontable.h"
#include "core/smartstatus.h"
@ -30,11 +32,16 @@
#include <kdebug.h>
#include <kpushbutton.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <QTreeWidgetItem>
#include <QPointer>
/** Creates a new DevicePropsDialog
@param parent pointer to the parent widget
@param d the Device the Partition is on
@param p the Partition to show properties for
@param d the Device to show properties for
*/
DevicePropsDialog::DevicePropsDialog(QWidget* parent, Device& d) :
KDialog(parent),
@ -114,17 +121,11 @@ void DevicePropsDialog::setupDialog()
dialogWidget().smartStatusText().setText(i18nc("@label SMART disk status", "BAD"));
dialogWidget().smartStatusIcon().setPixmap(SmallIcon("dialog-warning"));
}
const QString temp = KGlobal::locale()->formatNumber(device().smartStatus().temp() / 10.0, 1);
dialogWidget().temperature().setText(i18nc("@label temperature in celsius", "%1° C", temp));
dialogWidget().badSectors().setText(KGlobal::locale()->formatNumber(device().smartStatus().badSectors(), 0));
dialogWidget().poweredOn().setText(KGlobal::locale()->formatDuration(device().smartStatus().poweredOn()));
dialogWidget().powerCycles().setText(KGlobal::locale()->formatNumber(device().smartStatus().powerCycles(), 0));
}
else
{
dialogWidget().smartStatusText().setText(i18nc("@label", "(unknown)"));
dialogWidget().hideSmartLabels();
dialogWidget().buttonSmartMore().setVisible(false);
}
setMinimumSize(dialogWidget().size());
@ -135,6 +136,7 @@ void DevicePropsDialog::setupConnections()
{
connect(&dialogWidget().radioSectorBased(), SIGNAL(toggled(bool)), SLOT(setDirty(bool)));
connect(&dialogWidget().radioCylinderBased(), SIGNAL(toggled(bool)), SLOT(setDirty(bool)));
connect(&dialogWidget().buttonSmartMore(), SIGNAL(clicked(bool)), SLOT(onButtonSmartMore(bool)));
}
void DevicePropsDialog::setDirty(bool)
@ -152,3 +154,10 @@ bool DevicePropsDialog::sectorBasedAlignment() const
{
return dialogWidget().radioSectorBased().isChecked();
}
void DevicePropsDialog::onButtonSmartMore(bool)
{
QPointer<SmartDialog> dlg = new SmartDialog(this, device());
dlg->exec();
delete dlg;
}

View File

@ -58,8 +58,11 @@ class DevicePropsDialog : public KDialog
DevicePropsWidget& dialogWidget() { Q_ASSERT(m_DialogWidget); return *m_DialogWidget; }
const DevicePropsWidget& dialogWidget() const { Q_ASSERT(m_DialogWidget); return *m_DialogWidget; }
void onButtonSmartMore();
protected slots:
void setDirty(bool);
void onButtonSmartMore(bool);
private:
Device& m_Device;

View File

@ -0,0 +1,34 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "gui/devicepropswidget.h"
#include <kdebug.h>
DevicePropsWidget::DevicePropsWidget(QWidget* parent) :
QWidget(parent)
{
setupUi(this);
}
void DevicePropsWidget::hideTypeRadioButtons()
{
radioSectorBased().setVisible(false);
radioCylinderBased().setVisible(false);
}

View File

@ -31,7 +31,7 @@ class PartTableWidget;
class DevicePropsWidget : public QWidget, public Ui::DevicePropsWidgetBase
{
public:
DevicePropsWidget(QWidget* parent) : QWidget(parent) { setupUi(this); }
DevicePropsWidget(QWidget* parent);
public:
PartTableWidget& partTableWidget() { Q_ASSERT(m_PartTableWidget); return *m_PartTableWidget; }
@ -52,38 +52,11 @@ class DevicePropsWidget : public QWidget, public Ui::DevicePropsWidgetBase
QSpacerItem& spacerType() { Q_ASSERT(m_SpacerType); return *m_SpacerType; }
void hideTypeRadioButtons()
{
radioSectorBased().setVisible(false);
radioCylinderBased().setVisible(false);
}
QLabel& smartStatusText() { Q_ASSERT(m_LabelSmartStatusText); return *m_LabelSmartStatusText; }
QLabel& smartStatusIcon() { Q_ASSERT(m_LabelSmartStatusIcon); return *m_LabelSmartStatusIcon; }
QLabel& temperature() { Q_ASSERT(m_LabelSmartTemperature); return *m_LabelSmartTemperature; }
QLabel& badSectors() { Q_ASSERT(m_LabelSmartBadSectors); return *m_LabelSmartBadSectors; }
QLabel& poweredOn() { Q_ASSERT(m_LabelSmartPoweredOn); return *m_LabelSmartPoweredOn; }
QLabel& powerCycles() { Q_ASSERT(m_LabelSmartPowerCycles); return *m_LabelSmartPowerCycles; }
KPushButton& buttonSmartMore() { Q_ASSERT(m_ButtonSmartMore); return *m_ButtonSmartMore; }
QLabel& labelTemperature() { Q_ASSERT(m_LabelTextSmartTemperature); return *m_LabelTextSmartTemperature; }
QLabel& labelBadSectors() { Q_ASSERT(m_LabelTextSmartBadSectors); return *m_LabelTextSmartBadSectors; }
QLabel& labelPoweredOn() { Q_ASSERT(m_LabelTextSmartPoweredOn); return *m_LabelTextSmartPoweredOn; }
QLabel& labelPowerCycles() { Q_ASSERT(m_LabelTextSmartPowerCycles); return *m_LabelTextSmartPowerCycles; }
void hideSmartLabels()
{
smartStatusIcon().setVisible(false);
temperature().setVisible(false);
badSectors().setVisible(false);
poweredOn().setVisible(false);
powerCycles().setVisible(false);
labelTemperature().setVisible(false);
labelBadSectors().setVisible(false);
labelPoweredOn().setVisible(false);
labelPowerCycles().setVisible(false);
}
void hideTypeRadioButtons();
};
#endif

View File

@ -7,11 +7,11 @@
<x>0</x>
<y>0</y>
<width>576</width>
<height>496</height>
<height>343</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="5">
<item row="0" column="0" colspan="2">
<widget class="PartTableWidget" name="m_PartTableWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -36,7 +36,7 @@
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<item row="1" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -52,7 +52,7 @@
</property>
</spacer>
</item>
<item row="2" column="0" colspan="2">
<item row="2" column="0">
<widget class="QLabel" name="m_LabelTextType">
<property name="text">
<string>Partition table:</string>
@ -62,7 +62,7 @@
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<item row="2" column="1">
<widget class="QLabel" name="m_LabelType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -75,7 +75,7 @@
</property>
</widget>
</item>
<item row="3" column="2" colspan="3">
<item row="3" column="1">
<layout class="QHBoxLayout" name="m_TypeLayout">
<item>
<widget class="QRadioButton" name="m_RadioCylinderBased">
@ -106,14 +106,14 @@
</item>
</layout>
</item>
<item row="4" column="0" colspan="5">
<item row="4" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item row="5" column="0">
<widget class="QLabel" name="m_LabelTextCapacity">
<property name="text">
<string>Capacity:</string>
@ -123,7 +123,7 @@
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<item row="5" column="1">
<widget class="QLabel" name="m_LabelCapacity">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -136,7 +136,7 @@
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<item row="6" column="0">
<widget class="QLabel" name="m_LabelTextTotalSectors">
<property name="text">
<string>Total sectors:</string>
@ -146,7 +146,7 @@
</property>
</widget>
</item>
<item row="6" column="2" colspan="2">
<item row="6" column="1">
<widget class="QLabel" name="m_LabelTotalSectors">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -159,14 +159,14 @@
</property>
</widget>
</item>
<item row="7" column="0" colspan="5">
<item row="7" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<item row="8" column="0">
<widget class="QLabel" name="m_LabelTextCHS">
<property name="text">
<string>Cylinders/Heads/Sectors:</string>
@ -176,7 +176,7 @@
</property>
</widget>
</item>
<item row="8" column="2" colspan="2">
<item row="8" column="1">
<widget class="QLabel" name="m_LabelCHS">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -189,7 +189,7 @@
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<item row="9" column="0">
<widget class="QLabel" name="m_LabelTextSectorSize">
<property name="text">
<string>Logical sector size:</string>
@ -199,7 +199,7 @@
</property>
</widget>
</item>
<item row="9" column="2" colspan="2">
<item row="9" column="1">
<widget class="QLabel" name="m_LabelSectorSize">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -212,7 +212,7 @@
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<item row="10" column="0">
<widget class="QLabel" name="m_LabelTextCylinderSize">
<property name="text">
<string>Cylinder size:</string>
@ -222,7 +222,7 @@
</property>
</widget>
</item>
<item row="10" column="2" colspan="2">
<item row="10" column="1">
<widget class="QLabel" name="m_LabelCylinderSize">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -235,14 +235,14 @@
</property>
</widget>
</item>
<item row="11" column="0" colspan="5">
<item row="11" column="0" colspan="2">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="12" column="0" colspan="2">
<item row="12" column="0">
<widget class="QLabel" name="m_LabelTextPrimariesMax">
<property name="text">
<string>Primaries/Max:</string>
@ -252,7 +252,7 @@
</property>
</widget>
</item>
<item row="12" column="2" colspan="2">
<item row="12" column="1">
<widget class="QLabel" name="m_LabelPrimariesMax">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -265,14 +265,14 @@
</property>
</widget>
</item>
<item row="13" column="0" colspan="5">
<item row="13" column="0" colspan="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="14" column="0" colspan="2">
<item row="14" column="0">
<widget class="QLabel" name="m_LabelTextSmartStatus">
<property name="text">
<string>SMART status:</string>
@ -282,7 +282,7 @@
</property>
</widget>
</item>
<item row="14" column="2" colspan="2">
<item row="14" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="m_LabelSmartStatusIcon">
@ -299,82 +299,27 @@
</item>
<item>
<widget class="QLabel" name="m_LabelSmartStatusText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="KPushButton" name="m_ButtonSmartMore">
<property name="text">
<string>More...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="16" column="0" colspan="2">
<widget class="QLabel" name="m_LabelTextSmartTemperature">
<property name="text">
<string>Temperature:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="16" column="2" colspan="2">
<widget class="QLabel" name="m_LabelSmartTemperature">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="17" column="0" colspan="2">
<widget class="QLabel" name="m_LabelTextSmartBadSectors">
<property name="text">
<string>Bad sectors:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="17" column="2" colspan="2">
<widget class="QLabel" name="m_LabelSmartBadSectors">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="18" column="0" colspan="2">
<widget class="QLabel" name="m_LabelTextSmartPoweredOn">
<property name="text">
<string>Powered on for:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="18" column="2" colspan="2">
<widget class="QLabel" name="m_LabelSmartPoweredOn">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="19" column="0" colspan="2">
<widget class="QLabel" name="m_LabelTextSmartPowerCycles">
<property name="text">
<string>Power cycles:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="19" column="2" colspan="2">
<widget class="QLabel" name="m_LabelSmartPowerCycles">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="20" column="0" colspan="5">
<item row="15" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -384,8 +329,8 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
<width>17</width>
<height>17</height>
</size>
</property>
</spacer>
@ -393,6 +338,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KPushButton</class>
<extends>QPushButton</extends>
<header>kpushbutton.h</header>
</customwidget>
<customwidget>
<class>PartTableWidget</class>
<extends>QWidget</extends>

View File

@ -24,6 +24,7 @@
#include "gui/createpartitiontabledialog.h"
#include "gui/filesystemsupportdialog.h"
#include "gui/devicepropsdialog.h"
#include "gui/smartdialog.h"
#include "config/configureoptionsdialog.h"
@ -32,6 +33,7 @@
#include "core/device.h"
#include "core/partition.h"
#include "core/smartstatus.h"
#include "ops/operation.h"
#include "ops/createpartitiontableoperation.h"
@ -242,6 +244,12 @@ void MainWindow::setupActions()
importPartitionTable->setStatusTip(i18nc("@info:status", "Import a partition table from a text file."));
importPartitionTable->setIcon(BarIcon("document-import"));
KAction* smartStatusDevice = actionCollection()->addAction("smartStatusDevice", this, SLOT(onSmartStatusDevice()));
smartStatusDevice->setEnabled(false);
smartStatusDevice->setText(i18nc("@action:inmenu", "SMART Status"));
smartStatusDevice->setToolTip(i18nc("@info:tooltip", "Show SMART status"));
smartStatusDevice->setStatusTip(i18nc("@info:status", "Show the device's SMART status if supported"));
KAction* propertiesDevice = actionCollection()->addAction("propertiesDevice", this, SLOT(onPropertiesDevice()));
propertiesDevice->setEnabled(false);
propertiesDevice->setText(i18nc("@action:inmenu", "Properties"));
@ -400,6 +408,7 @@ void MainWindow::enableActions()
actionCollection()->action("createNewPartitionTable")->setEnabled(CreatePartitionTableOperation::canCreate(pmWidget().selectedDevice()));
actionCollection()->action("exportPartitionTable")->setEnabled(pmWidget().selectedDevice() && pmWidget().selectedDevice()->partitionTable() && operationStack().size() == 0);
actionCollection()->action("importPartitionTable")->setEnabled(CreatePartitionTableOperation::canCreate(pmWidget().selectedDevice()));
actionCollection()->action("smartStatusDevice")->setEnabled(pmWidget().selectedDevice() != NULL && pmWidget().selectedDevice()->smartStatus().isValid());
actionCollection()->action("propertiesDevice")->setEnabled(pmWidget().selectedDevice() != NULL);
actionCollection()->action("undoOperation")->setEnabled(operationStack().size() > 0);
@ -941,6 +950,18 @@ void MainWindow::onConfigureOptions()
dlg->show();
}
void MainWindow::onSmartStatusDevice()
{
Q_ASSERT(pmWidget().selectedDevice());
if (pmWidget().selectedDevice())
{
QPointer<SmartDialog> dlg = new SmartDialog(this, *pmWidget().selectedDevice());
dlg->exec();
delete dlg;
}
}
void MainWindow::onPropertiesDevice(const QString&)
{
Q_ASSERT(pmWidget().selectedDevice());

View File

@ -161,6 +161,7 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT MainWindow : public KXmlGuiWindow, publi
void onFileSystemSupport();
void onSmartStatusDevice();
void onPropertiesDevice(const QString& device_node = QString());
private:

View File

@ -49,6 +49,7 @@
<Action name="exportPartitionTable"/>
<Action name="importPartitionTable"/>
<separator/>
<Action name="smartStatusDevice"/>
<Action name="propertiesDevice"/>
</Menu>
<Menu name="partition">

130
src/gui/smartdialog.cpp Normal file
View File

@ -0,0 +1,130 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "gui/smartdialog.h"
#include "gui/smartdialogwidget.h"
#include "core/device.h"
#include "core/smartstatus.h"
#include "core/smartattribute.h"
#include "util/helpers.h"
#include <kdebug.h>
#include <kpushbutton.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <QTreeWidgetItem>
#include <config.h>
/** Creates a new SmartDialog
@param parent pointer to the parent widget
@param d the Device
*/
SmartDialog::SmartDialog(QWidget* parent, Device& d) :
KDialog(parent),
m_Device(d),
m_DialogWidget(new SmartDialogWidget(this))
{
setMainWidget(&dialogWidget());
setCaption(i18nc("@title:window", "SMART Properties: <filename>%1</filename>", device().deviceNode()));
setButtons(Close);
setupDialog();
setupConnections();
restoreDialogSize(KConfigGroup(KGlobal::config(), "smartDialog"));
}
/** Destroys a SmartDialog */
SmartDialog::~SmartDialog()
{
KConfigGroup kcg(KGlobal::config(), "smartDialog");
saveDialogSize(kcg);
}
void SmartDialog::setupDialog()
{
if (device().smartStatus().isValid())
{
if (device().smartStatus().status())
{
dialogWidget().statusText().setText(i18nc("@label SMART disk status", "good"));
dialogWidget().statusIcon().setVisible(false);
}
else
{
dialogWidget().statusText().setText(i18nc("@label SMART disk status", "BAD"));
dialogWidget().statusIcon().setPixmap(SmallIcon("dialog-warning"));
}
dialogWidget().modelName().setText(device().smartStatus().modelName());
dialogWidget().firmware().setText(device().smartStatus().firmware());
dialogWidget().serialNumber().setText(device().smartStatus().serial());
dialogWidget().temperature().setText(SmartStatus::tempToString(device().smartStatus().temp()));
const QString badSectors = device().smartStatus().badSectors() > 0
? KGlobal::locale()->formatNumber(device().smartStatus().badSectors(), 0)
: i18nc("@label SMART number of bad sectors", "none");
dialogWidget().badSectors().setText(badSectors);
dialogWidget().poweredOn().setText(KGlobal::locale()->formatDuration(device().smartStatus().poweredOn()));
dialogWidget().powerCycles().setText(KGlobal::locale()->formatNumber(device().smartStatus().powerCycles(), 0));
dialogWidget().overallAssessment().setText(SmartStatus::overallAssessmentToString(device().smartStatus().overall()));
dialogWidget().selfTests().setText(SmartStatus::selfTestStatusToString(device().smartStatus().selfTestStatus()));
dialogWidget().treeSmartAttributes().clear();
const QFont f = KGlobalSettings::smallestReadableFont();
const QString size = f.pixelSize() != -1 ? QString("%1px").arg(f.pixelSize()) : QString("%1pt").arg(f.pointSize());
const QString st = QString("<span style=\"font-family:%1;font-size:%2;\">").arg(f.family()).arg(size);
foreach (const SmartAttribute& a, device().smartStatus().attributes())
{
QTreeWidgetItem* item = new QTreeWidgetItem(
QStringList()
<< KGlobal::locale()->formatNumber(a.id(), 0)
<< QString("<b>%1</b><br>%2").arg(a.name()).arg(st + a.desc() + "</style>")
<< (a.failureType() == SmartAttribute::PreFailure ? i18nc("@item:intable", "Pre-Failure") : i18nc("@item:intable", "Old-Age"))
<< (a.updateType() == SmartAttribute::Online ? i18nc("@item:intable", "Online") : i18nc("@item:intable", "Offline"))
<< KGlobal::locale()->formatNumber(a.worst(), 0)
<< KGlobal::locale()->formatNumber(a.current(), 0)
<< KGlobal::locale()->formatNumber(a.threshold(), 0)
<< a.raw()
<< a.assessmentToString()
<< a.value()
);
item->setSizeHint(0, QSize(0, 64));
dialogWidget().treeSmartAttributes().addTopLevelItem(item);
}
}
else
dialogWidget().statusText().setText(i18nc("@label", "(unknown)"));
setMinimumSize(dialogWidget().size());
resize(dialogWidget().size());
}
void SmartDialog::setupConnections()
{
}

63
src/gui/smartdialog.h Normal file
View File

@ -0,0 +1,63 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#if !defined(SMARTDIALOG__H)
#define SMARTDIALOG__H
#include <kdialog.h>
class Device;
class SmartDialogWidget;
class QWidget;
class QString;
class QPoint;
/** @brief Show SMART properties.
Dialog that shows SMART status and properties for a device
@author vl@fidra.de
*/
class SmartDialog : public KDialog
{
Q_OBJECT
Q_DISABLE_COPY(SmartDialog)
public:
SmartDialog(QWidget* parent, Device& d);
~SmartDialog();
protected:
void setupDialog();
void setupConnections();
Device& device() { return m_Device; }
const Device& device() const { return m_Device; }
SmartDialogWidget& dialogWidget() { Q_ASSERT(m_DialogWidget); return *m_DialogWidget; }
const SmartDialogWidget& dialogWidget() const { Q_ASSERT(m_DialogWidget); return *m_DialogWidget; }
private:
Device& m_Device;
SmartDialogWidget* m_DialogWidget;
};
#endif

View File

@ -0,0 +1,135 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "gui/smartdialogwidget.h"
#include "util/helpers.h"
#include <klocale.h>
#include <kdebug.h>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QTextDocument>
#include <QAbstractTextDocumentLayout>
#include <QPoint>
#include <config.h>
class SmartAttrDelegate : public QStyledItemDelegate
{
public:
SmartAttrDelegate() : QStyledItemDelegate() {}
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
};
void SmartAttrDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QString text = index.data().toString();
painter->save();
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
QTextDocument doc;
doc.setHtml(text);
doc.setPageSize(option.rect.size());
painter->setClipRect(option.rect);
qint32 offset = (option.rect.height() - doc.size().height()) / 2;
if (offset < 0)
offset = 0;
painter->translate(option.rect.x(), option.rect.y() + offset);
doc.drawContents(painter);
painter->restore();
}
SmartDialogWidget::SmartDialogWidget(QWidget* parent) :
QWidget(parent),
m_SmartAttrDelegate(new SmartAttrDelegate())
{
setupUi(this);
setupConnections();
loadConfig();
treeSmartAttributes().setItemDelegateForColumn(1, m_SmartAttrDelegate);
treeSmartAttributes().header()->setContextMenuPolicy(Qt::CustomContextMenu);
}
SmartDialogWidget::~SmartDialogWidget()
{
saveConfig();
}
void SmartDialogWidget::loadConfig()
{
QList<int> colWidths = Config::treeSmartAttributesColumnWidths();
QList<int> colPositions = Config::treeSmartAttributesColumnPositions();
QList<int> colVisible = Config::treeSmartAttributesColumnVisible();
QHeaderView* header = treeSmartAttributes().header();
for (int i = 0; i < treeSmartAttributes().columnCount(); i++)
{
if (colPositions[0] != -1 && colPositions.size() > i)
header->moveSection(header->visualIndex(i), colPositions[i]);
if (colVisible[0] != -1 && colVisible.size() > i)
treeSmartAttributes().setColumnHidden(i, colVisible[i] == 0);
if (colWidths[0] != -1 && colWidths.size() > i)
treeSmartAttributes().setColumnWidth(i, colWidths[i]);
}
}
void SmartDialogWidget::saveConfig() const
{
QList<int> colWidths;
QList<int> colPositions;
QList<int> colVisible;
for (int i = 0; i < treeSmartAttributes().columnCount(); i++)
{
colPositions.append(treeSmartAttributes().header()->visualIndex(i));
colVisible.append(treeSmartAttributes().isColumnHidden(i) ? 0 : 1);
colWidths.append(treeSmartAttributes().columnWidth(i));
}
Config::setTreeSmartAttributesColumnPositions(colPositions);
Config::setTreeSmartAttributesColumnVisible(colVisible);
Config::setTreeSmartAttributesColumnWidths(colWidths);
Config::self()->writeConfig();
}
void SmartDialogWidget::setupConnections()
{
connect(treeSmartAttributes().header(), SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onHeaderContextMenu(const QPoint&)));
}
void SmartDialogWidget::onHeaderContextMenu(const QPoint& p)
{
showColumnsContextMenu(p, treeSmartAttributes());
}

View File

@ -0,0 +1,69 @@
/***************************************************************************
* Copyright (C) 2010 by Volker Lanz <vl@fidra.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#if !defined(SMARTDIALOGWIDGET__H)
#define SMARTDIALOGWIDGET__H
#include "ui_smartdialogwidgetbase.h"
class QStyledItemDelegate;
class QPoint;
/** @brief Central widget in the SmartDialogWidget
@author vl@fidra.de
*/
class SmartDialogWidget : public QWidget, public Ui::SmartDialogWidgetBase
{
Q_OBJECT
public:
SmartDialogWidget(QWidget* parent);
~SmartDialogWidget();
public:
QLabel& statusText() { Q_ASSERT(m_LabelSmartStatusText); return *m_LabelSmartStatusText; }
QLabel& statusIcon() { Q_ASSERT(m_LabelSmartStatusIcon); return *m_LabelSmartStatusIcon; }
QLabel& modelName() { Q_ASSERT(m_LabelSmartModelName); return *m_LabelSmartModelName; }
QLabel& firmware() { Q_ASSERT(m_LabelSmartFirmware); return *m_LabelSmartFirmware; }
QLabel& serialNumber() { Q_ASSERT(m_LabelSmartSerialNumber); return *m_LabelSmartSerialNumber; }
QLabel& temperature() { Q_ASSERT(m_LabelSmartTemperature); return *m_LabelSmartTemperature; }
QLabel& badSectors() { Q_ASSERT(m_LabelSmartBadSectors); return *m_LabelSmartBadSectors; }
QLabel& poweredOn() { Q_ASSERT(m_LabelSmartPoweredOn); return *m_LabelSmartPoweredOn; }
QLabel& powerCycles() { Q_ASSERT(m_LabelSmartPowerCycles); return *m_LabelSmartPowerCycles; }
QLabel& selfTests() { Q_ASSERT(m_LabelSmartSelfTests); return *m_LabelSmartSelfTests; }
QLabel& overallAssessment() { Q_ASSERT(m_LabelSmartOverallAssessment); return *m_LabelSmartOverallAssessment; }
QTreeWidget& treeSmartAttributes() { Q_ASSERT(m_TreeSmartAttributes); return *m_TreeSmartAttributes; }
const QTreeWidget& treeSmartAttributes() const { Q_ASSERT(m_TreeSmartAttributes); return *m_TreeSmartAttributes; }
protected:
void setupConnections();
void loadConfig();
void saveConfig() const;
protected slots:
void onHeaderContextMenu(const QPoint& p);
private:
QStyledItemDelegate* m_SmartAttrDelegate;
};
#endif

View File

@ -0,0 +1,441 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SmartDialogWidgetBase</class>
<widget class="QWidget" name="SmartDialogWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>649</width>
<height>483</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_LabelTextSmartStatus">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SMART status:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="m_LabelSmartStatusIcon">
<property name="maximumSize">
<size>
<width>16</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_LabelSmartStatusText">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="m_LabelTextSmartModelName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Model:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartModelName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="m_LabelTextSmartSerialNumber">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Serial number:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartSerialNumber">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="m_LabelTextSmartFirmware">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Firmware revision:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartFirmware">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="m_LabelTextSmartTemperature">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Temperature:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartTemperature">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="m_LabelTextSmartBadSectors">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Bad sectors:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartBadSectors">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="m_LabelTextSmartPoweredOn">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Powered on for:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartPoweredOn">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="m_LabelTextSmartPowerCycles">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Power cycles:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartPowerCycles">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="15" column="0" colspan="3">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>641</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="16" column="0" colspan="3">
<widget class="QTreeWidget" name="m_TreeSmartAttributes">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Id</string>
</property>
</column>
<column>
<property name="text">
<string>Attribute</string>
</property>
</column>
<column>
<property name="text">
<string>Failure Type</string>
</property>
</column>
<column>
<property name="text">
<string>Update Type</string>
</property>
</column>
<column>
<property name="text">
<string>Worst</string>
</property>
</column>
<column>
<property name="text">
<string>Current</string>
</property>
</column>
<column>
<property name="text">
<string>Threshold</string>
</property>
</column>
<column>
<property name="text">
<string>Raw</string>
</property>
</column>
<column>
<property name="text">
<string>Assessment</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
</widget>
</item>
<item row="17" column="0" colspan="3">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>638</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="m_LabelTextSmartOverallAssessment">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Overall assessment:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="13" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartOverallAssessment">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="m_LabelTextSmartSelfTests">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Self tests:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="1" colspan="2">
<widget class="QLabel" name="m_LabelSmartSelfTests">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>