diff --git a/src/common/data.h b/src/common/data.h index 24308c1..468a2c1 100644 --- a/src/common/data.h +++ b/src/common/data.h @@ -1,460 +1,459 @@ /* This file is part of KNemo Copyright (C) 2004 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp KNemo is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KNemo 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DATA_H #define DATA_H #include #include #include #include #include #include #include #include #include -#include +#include class KCalendarSystem; /** * This file contains data structures used to store information about * an interface. It is shared between the daemon and the control center * module. * * @short Shared data structures * @author Percy Leonhardt */ namespace KNemoIface { enum Type { UnknownType, Ethernet, PPP }; enum IfaceState { UnknownState = 0, Unavailable = 1, Available = 2, Up = 4, Connected = 8, RxTraffic = 16, TxTraffic = 32 }; } namespace KNemoStats { enum TrafficUnits { UnitB = 0, UnitK, UnitM, UnitG }; enum TrafficDirection { TrafficIn = 0, TrafficOut, TrafficTotal }; enum WarnType { Peak = 0, Offpeak, PeakOffpeak }; enum PeriodUnits { Hour = 0, Day, Week, Month, BillPeriod, Year, HourArchive }; // Powers of 2 enum TrafficType { AllTraffic = 0, OffpeakTraffic = 1 }; }; static const QLatin1String NETLOAD_THEME("netloadtheme"); static const QLatin1String TEXT_THEME("texttheme"); static const QLatin1String SYSTEM_THEME("systemtheme"); static const QLatin1String ICON_ERROR("error"); static const QLatin1String ICON_OFFLINE("offline"); static const QLatin1String ICON_IDLE("idle"); static const QLatin1String ICON_RX("receive"); static const QLatin1String ICON_TX("transmit"); static const QLatin1String ICON_RX_TX("transmit-receive"); // config groups static const QLatin1String confg_general("General"); static const QLatin1String confg_interface("Interface_"); static const QLatin1String confg_plotter("Plotter_"); static const QLatin1String confg_statsRule("StatsRule_"); static const QLatin1String confg_warnRule("WarnRule_"); static const QLatin1String conf_firstStart("FirstStart"); static const QLatin1String conf_autoStart("AutoStart"); static const QLatin1String conf_interfaces("Interfaces"); // interface static const QLatin1String conf_alias("Alias"); // interface icon static const QLatin1String conf_hideWhenNotAvail("HideWhenNotAvailable"); static const QLatin1String conf_hideWhenNotExist("HideWhenNotExisting"); static const QLatin1String conf_trafficThreshold("TrafficThreshold"); static const QLatin1String conf_iconTheme("IconSet"); static const QLatin1String conf_colorIncoming("ColorIncoming"); static const QLatin1String conf_colorOutgoing("ColorOutgoing"); static const QLatin1String conf_colorDisabled("ColorDisabled"); static const QLatin1String conf_colorUnavailable("ColorUnavailable"); static const QLatin1String conf_dynamicColor("DynamicColor"); static const QLatin1String conf_colorIncomingMax("ColorIncomingMax"); static const QLatin1String conf_colorOutgoingMax("ColorOutgoingMax"); static const QLatin1String conf_barScale("BarScale"); static const QLatin1String conf_inMaxRate("InMaxRate"); static const QLatin1String conf_outMaxRate("OutMaxRate"); static const QLatin1String conf_iconFont("IconFont"); // interface statistics static const QLatin1String conf_activateStatistics("ActivateStatistics"); static const QLatin1String conf_calendarSystem("CalendarSystem"); static const QLatin1String conf_statsRules("StatsRules"); static const QLatin1String conf_warnRules("WarnRules"); // interface billing static const QLatin1String conf_statsStartDate("StartDate"); static const QLatin1String conf_statsPeriodUnits("PeriodUnits"); static const QLatin1String conf_statsPeriodCount("PeriodCount"); static const QLatin1String conf_logOffpeak("LogOffpeak"); static const QLatin1String conf_offpeakStartTime("OffpeakStartTime"); static const QLatin1String conf_offpeakEndTime("OffpeakEndTime"); static const QLatin1String conf_weekendIsOffpeak("WeekendIsOffpeak"); static const QLatin1String conf_weekendDayStart("WeekendDayStart"); static const QLatin1String conf_weekendDayEnd("WeekendDayEnd"); static const QLatin1String conf_weekendTimeStart("WeekendTimeStart"); static const QLatin1String conf_weekendTimeEnd("WeekendTimeEnd"); // warning static const QLatin1String conf_warnPeriodUnits("PeriodUnits"); static const QLatin1String conf_warnPeriodCount("PeriodCount"); static const QLatin1String conf_warnTrafficType("TrafficType"); static const QLatin1String conf_warnTrafficDirection("TrafficDirection"); static const QLatin1String conf_warnTrafficUnits("TrafficUnits"); static const QLatin1String conf_warnThreshold("Threshold"); static const QLatin1String conf_warnCustomText("CustomText"); // interface context menu static const QLatin1String conf_numCommands("NumCommands"); static const QLatin1String conf_runAsRoot("RunAsRoot"); static const QLatin1String conf_command("Command"); static const QLatin1String conf_menuText("MenuText"); // tooltip static const QLatin1String conf_toolTipContent("ToolTipContent"); // general static const QLatin1String conf_pollInterval("PollInterval"); static const QLatin1String conf_saveInterval("SaveInterval"); -static const QLatin1String conf_statisticsDir("StatisticsDir"); static const QLatin1String conf_useBitrate("UseBitrate"); static const QLatin1String conf_plotterPos("PlotterPos"); static const QLatin1String conf_plotterSize("PlotterSize"); static const QLatin1String conf_statisticsPos("StatisticsPos"); static const QLatin1String conf_statisticsSize("StatisticsSize"); static const QLatin1String conf_statusPos("StatusPos"); static const QLatin1String conf_statusSize("StatusSize"); static const QLatin1String conf_hourState("HourState"); static const QLatin1String conf_dayState("DayState"); static const QLatin1String conf_weekState("WeekState"); static const QLatin1String conf_monthState("MonthState"); static const QLatin1String conf_billingState("BillingState"); static const QLatin1String conf_yearState("YearState"); enum ToolTipEnums { INTERFACE = 0x00000001, ALIAS = 0x00000002, STATUS = 0x00000004, UPTIME = 0x00000008, IP_ADDRESS = 0x00000010, SCOPE = 0x00000020, HW_ADDRESS = 0x00000040, PTP_ADDRESS = 0x00000080, RX_PACKETS = 0x00000100, TX_PACKETS = 0x00000200, RX_BYTES = 0x00000400, TX_BYTES = 0x00000800, ESSID = 0x00001000, MODE = 0x00002000, FREQUENCY = 0x00004000, BIT_RATE = 0x00008000, ACCESS_POINT = 0x00010000, LINK_QUALITY = 0x00020000, BCAST_ADDRESS = 0x00040000, GATEWAY = 0x00080000, DOWNLOAD_SPEED = 0x00100000, UPLOAD_SPEED = 0x00200000, NICK_NAME = 0x00400000, ENCRYPTION = 0x00800000 }; static const int defaultTip = STATUS | IP_ADDRESS | RX_BYTES | TX_BYTES | ESSID | LINK_QUALITY | DOWNLOAD_SPEED | UPLOAD_SPEED | ENCRYPTION; struct KNemoTheme { QString name; QString comment; QString internalName; }; struct AddrData { int afType; QString broadcastAddress; int scope; QString ipv6Flags; QString label; bool hasPeer; }; struct BackendData { BackendData() : status( KNemoIface::UnknownState ), index( -1 ), interfaceType( KNemoIface::UnknownType ), isWireless( false ), prevRxPackets( 0L ), prevTxPackets( 0L ), rxPackets( 0L ), txPackets( 0L ), prevRxBytes( 0L ), prevTxBytes( 0L ), incomingBytes( 0L ), outgoingBytes( 0L ), rxBytes( 0L ), txBytes( 0L ), isEncrypted( false ) {} int status; int index; KNemoIface::Type interfaceType; bool isWireless; unsigned long prevRxPackets; unsigned long prevTxPackets; unsigned long rxPackets; unsigned long txPackets; unsigned long prevRxBytes; unsigned long prevTxBytes; unsigned long incomingBytes; unsigned long outgoingBytes; QMap addrData; QString hwAddress; QString ip4DefaultGateway; QString ip6DefaultGateway; QString rxString; QString txString; quint64 rxBytes; quint64 txBytes; QString essid; QString mode; QString frequency; QString channel; QString bitRate; QString linkQuality; QString accessPoint; QString prevAccessPoint; QString nickName; bool isEncrypted; }; struct InterfaceCommand { bool runAsRoot; QString command; QString menuText; }; struct GeneralSettings { GeneralSettings() : toolTipContent( defaultTip ), pollInterval( 1.0 ), saveInterval( 60 ), useBitrate( false ), statisticsDir( QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/knemo") ) {} int toolTipContent; double pollInterval; int saveInterval; bool useBitrate; - QUrl statisticsDir; + QDir statisticsDir; }; class StatsRule { public: StatsRule() : periodCount( 1 ), periodUnits( KNemoStats::Month ), logOffpeak( false ), offpeakStartTime( QTime( 23, 0) ), offpeakEndTime( QTime( 7, 0) ), weekendIsOffpeak( false ), weekendDayStart( 5 ), weekendDayEnd( 1 ), weekendTimeStart( QTime( 23, 0) ), weekendTimeEnd( QTime( 7, 0) ) { } bool operator==( StatsRule &r ); bool isValid( KCalendarSystem *cal ); QDate startDate; int periodCount; int periodUnits; bool logOffpeak; QTime offpeakStartTime; QTime offpeakEndTime; bool weekendIsOffpeak; int weekendDayStart; int weekendDayEnd; QTime weekendTimeStart; QTime weekendTimeEnd; }; struct WarnRule { WarnRule() : periodUnits( KNemoStats::Month ), periodCount( 1 ), trafficType( KNemoStats::PeakOffpeak ), trafficDirection( KNemoStats::TrafficIn ), trafficUnits( KNemoStats::UnitG ), threshold( 5.0 ), warnDone( false ) { } bool operator==( WarnRule &r ) { if ( periodUnits == r.periodUnits && periodCount == r.periodCount && trafficType == r.trafficType && trafficDirection == r.trafficDirection && trafficUnits == r.trafficUnits && threshold == r.threshold ) return true; else return false; } int periodUnits; uint periodCount; int trafficType; int trafficDirection; int trafficUnits; double threshold; QString customText; bool warnDone; }; struct InterfaceSettings { InterfaceSettings() : iconTheme( QLatin1String("monitor") ), colorIncoming( 0x1889FF ), colorOutgoing( 0xFF7F08 ), colorDisabled( 0x888786 ), colorUnavailable( 0x888786 ), colorBackground( 0x888786 ), dynamicColor( false ), colorIncomingMax( 0x96FFFF ), colorOutgoingMax( 0xFFC868 ), barScale( false ), inMaxRate( 4 ), outMaxRate( 4 ), iconFont( QFontDatabase::systemFont( QFontDatabase::GeneralFont ) ), numCommands( 0 ), trafficThreshold( 0 ), hideWhenUnavailable( false ), hideWhenDisconnected( false ), activateStatistics( false ), calendarSystem( KLocale::QDateCalendar ) {} QString iconTheme; QColor colorIncoming; QColor colorOutgoing; QColor colorDisabled; QColor colorUnavailable; QColor colorBackground; bool dynamicColor; QColor colorIncomingMax; QColor colorOutgoingMax; bool barScale; unsigned int inMaxRate; unsigned int outMaxRate; QFont iconFont; int numCommands; unsigned int trafficThreshold; bool hideWhenUnavailable; bool hideWhenDisconnected; bool activateStatistics; QList statsRules; QList warnRules; KLocale::CalendarSystem calendarSystem; QString alias; QList commands; }; #ifndef __linux__ enum rt_scope_t { RT_SCOPE_UNIVERSE=0, RT_SCOPE_SITE=200, RT_SCOPE_LINK=253, RT_SCOPE_HOST=254, RT_SCOPE_NOWHERE=255 }; #endif static const double pollIntervals[] = { 0.1, 0.2, 0.25, 0.5, 1.0, 2.0 }; #endif // DATA_H diff --git a/src/kcm/configdialog.cpp b/src/kcm/configdialog.cpp index ab68148..f188ced 100644 --- a/src/kcm/configdialog.cpp +++ b/src/kcm/configdialog.cpp @@ -1,1807 +1,1804 @@ /* This file is part of KNemo Copyright (C) 2004, 2006 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp KNemo is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KNemo 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_configdlg.h" #include "config-knemo.h" #include "configdialog.h" #include "statsconfig.h" #include "warnconfig.h" #include "themeconfig.h" #include "utils.h" #include #include #include #include #ifdef __linux__ #include #include #include #endif K_PLUGIN_FACTORY(KNemoFactory, registerPlugin(QLatin1String("knemo"));) K_EXPORT_PLUGIN(KNemoFactory("kcm_knemo")) Q_DECLARE_METATYPE( KNemoTheme ) Q_DECLARE_METATYPE( StatsRule ) Q_DECLARE_METATYPE( WarnRule ) static bool themesLessThan( const KNemoTheme& s1, const KNemoTheme& s2 ) { if ( s1.name < s2.name ) return true; else return false; } static QString periodText( int c, int u ) { QString units; switch ( u ) { case KNemoStats::Hour: units = i18np( "%1 hour", "%1 hours", c ); break; case KNemoStats::Day: units = i18np( "%1 day", "%1 days", c ); break; case KNemoStats::Week: units = i18np( "%1 week", "%1 weeks", c ); break; case KNemoStats::Month: units = i18np( "%1 month", "%1 months", c ); break; case KNemoStats::BillPeriod: units = i18np( "%1 billing period", "%1 billing periods", c ); break; case KNemoStats::Year: units = i18np( "%1 year", "%1 years", c ); break; default: units = i18n( "Invalid period" ); ;; } return units; } void StatsRuleModel::setCalendar( const KCalendarSystem *cal ) { mCalendar = cal; } QString StatsRuleModel::dateText( const StatsRule &s ) { QString dateStr = mCalendar->formatDate( s.startDate, KLocale::LongDate ); if ( !mCalendar->isValid( s.startDate ) ) dateStr = i18n( "Invalid Date" ); return dateStr; } QList StatsRuleModel::getRules() { QList statsRules; for ( int i = 0; i < rowCount(); ++i ) { statsRules << item( i, 0 )->data( Qt::UserRole ).value(); } return statsRules; } QModelIndex StatsRuleModel::addRule( const StatsRule &s ) { QList items; QStandardItem *item = new QStandardItem( dateText( s ) ); QVariant v; v.setValue( s ); item->setData( v, Qt::UserRole ); item->setData( s.startDate, Qt::UserRole + 1 ); items << item; item = new QStandardItem( periodText( s.periodCount, s.periodUnits ) ); items << item; appendRow( items ); return indexFromItem (items[0] ); } void StatsRuleModel::modifyRule( const QModelIndex &index, const StatsRule &s ) { QVariant v; v.setValue( s ); item( index.row(), 0 )->setData( v, Qt::UserRole ); item( index.row(), 0 )->setData( s.startDate, Qt::UserRole + 1 ); item( index.row(), 0 )->setData( dateText( s ), Qt::DisplayRole ); item( index.row(), 1 )->setData( periodText( s.periodCount, s.periodUnits ), Qt::DisplayRole ); } QString WarnModel::ruleText( const WarnRule &warn ) { QString warnText; quint64 siz = warn.threshold * pow( 1024, warn.trafficUnits ); switch ( warn.trafficDirection ) { case KNemoStats::TrafficIn: if ( warn.trafficType == KNemoStats::Peak ) warnText = i18n( "peak incoming traffic > %1" ).arg( KIO::convertSize( siz ) ); else if ( warn.trafficType == KNemoStats::Offpeak ) warnText = i18n( "off-peak incoming traffic > %1" ).arg( KIO::convertSize( siz ) ); else warnText = i18n( "incoming traffic > %1" ).arg( KIO::convertSize( siz ) ); break; case KNemoStats::TrafficOut: if ( warn.trafficType == KNemoStats::Peak ) warnText = i18n( "peak outgoing traffic > %1" ).arg( KIO::convertSize( siz ) ); else if ( warn.trafficType == KNemoStats::Offpeak ) warnText = i18n( "off-peak outgoing traffic > %1" ).arg( KIO::convertSize( siz ) ); else warnText = i18n( "outgoing traffic > %1" ).arg( KIO::convertSize( siz ) ); break; case KNemoStats::TrafficTotal: if ( warn.trafficType == KNemoStats::Peak ) warnText = i18n( "peak incoming and outgoing traffic > %1" ).arg( KIO::convertSize( siz ) ); else if ( warn.trafficType == KNemoStats::Offpeak ) warnText = i18n( "off-peak incoming and outgoing traffic > %1" ).arg( KIO::convertSize( siz ) ); else warnText = i18n( "incoming and outgoing traffic > %1" ).arg( KIO::convertSize( siz ) ); } return warnText; } QList WarnModel::getRules() { QList warnRules; for ( int i = 0; i < rowCount(); ++i ) { warnRules << item( i, 0 )->data( Qt::UserRole ).value(); } return warnRules; } QModelIndex WarnModel::addWarn( const WarnRule &warn ) { QList items; QStandardItem *item = new QStandardItem( ruleText( warn ) ); QVariant v; v.setValue( warn ); item->setData( v, Qt::UserRole ); items << item; item = new QStandardItem( periodText( warn.periodCount, warn.periodUnits ) ); items << item; appendRow( items ); return indexFromItem( items[0] ); } void WarnModel::modifyWarn( const QModelIndex &index, const WarnRule &warn ) { QVariant v; v.setValue( warn ); item( index.row(), 0 )->setData( v, Qt::UserRole ); item( index.row(), 0 )->setData( ruleText( warn ), Qt::DisplayRole ); item( index.row(), 1 )->setData( periodText( warn.periodCount, warn.periodUnits ), Qt::DisplayRole ); } ConfigDialog::ConfigDialog( QWidget *parent, const QVariantList &args ) : KCModule( parent, args ), mLock( false ), mDlg( new Ui::ConfigDlg() ), mCalendar( 0 ) { mConfig = KSharedConfig::openConfig( QLatin1String("knemorc") ); setupToolTipMap(); QWidget *main = new QWidget( this ); QVBoxLayout* top = new QVBoxLayout( this ); mDlg->setupUi( main ); top->addWidget( main ); statsModel = new StatsRuleModel( this ); QStringList l; l << i18n( "Start Date" ) << i18n( "Period" ); statsModel->setHorizontalHeaderLabels( l ); QSortFilterProxyModel *proxy = new QSortFilterProxyModel( mDlg->statsView ); proxy->setSourceModel( statsModel ); proxy->setSortRole( Qt::UserRole + 1 ); mDlg->statsView->setModel( proxy ); mDlg->statsView->sortByColumn( 0, Qt::AscendingOrder ); warnModel = new WarnModel( this ); l.clear(); l << i18n( "Alert" ) << i18n( "Period" ); warnModel->setHorizontalHeaderLabels( l ); mDlg->warnView->setModel( warnModel ); QList themes = findThemes(); qSort( themes.begin(), themes.end(), themesLessThan ); foreach ( KNemoTheme theme, themes ) mDlg->comboBoxIconTheme->addItem( theme.name, QVariant::fromValue( theme ) ); // We want these hardcoded and at the bottom of the list KNemoTheme systemTheme; systemTheme.name = i18n( "System Theme" ); systemTheme.comment = i18n( "Use the current icon theme's network status icons" ); systemTheme.internalName = SYSTEM_THEME; KNemoTheme textTheme; textTheme.name = i18n( "Text" ); textTheme.comment = i18n( "KNemo theme that shows the upload/download speed as text" ); textTheme.internalName = TEXT_THEME; KNemoTheme netloadTheme; netloadTheme.name = i18n( "Netload" ); netloadTheme.comment = i18n( "KNemo theme that shows the upload/download speed as bar graphs" ); netloadTheme.internalName = NETLOAD_THEME; // Leave this out for now. Looks like none of the KDE icon themes provide // status/network-* icons. //mDlg->comboBoxIconTheme->addItem( systemTheme.name, QVariant::fromValue( systemTheme ) ); mDlg->comboBoxIconTheme->addItem( netloadTheme.name, QVariant::fromValue( netloadTheme ) ); mDlg->comboBoxIconTheme->addItem( textTheme.name, QVariant::fromValue( textTheme ) ); InterfaceSettings s; int index = findIndexFromName( s.iconTheme ); if ( index < 0 ) index = findIndexFromName( TEXT_THEME ); mDlg->comboBoxIconTheme->setCurrentIndex( index ); for ( size_t i = 0; i < sizeof(pollIntervals)/sizeof(double); i++ ) mDlg->comboBoxPoll->addItem( i18n( "%1 sec", pollIntervals[i] ), pollIntervals[i] ); mDlg->pushButtonNew->setIcon( QIcon::fromTheme( QLatin1String("list-add") ) ); mDlg->pushButtonAll->setIcon( QIcon::fromTheme( QLatin1String("document-new") ) ); mDlg->pushButtonDelete->setIcon( QIcon::fromTheme( QLatin1String("list-remove") ) ); mDlg->pushButtonAddCommand->setIcon( QIcon::fromTheme( QLatin1String("list-add") ) ); mDlg->pushButtonRemoveCommand->setIcon( QIcon::fromTheme( QLatin1String("list-remove") ) ); mDlg->pushButtonUp->setIcon( QIcon::fromTheme( QLatin1String("arrow-up") ) ); mDlg->pushButtonDown->setIcon( QIcon::fromTheme( QLatin1String("arrow-down") ) ); mDlg->pushButtonAddToolTip->setIcon( QIcon::fromTheme( QLatin1String("arrow-right") ) ); mDlg->pushButtonRemoveToolTip->setIcon( QIcon::fromTheme( QLatin1String("arrow-left") ) ); mDlg->themeColorBox->setEnabled( false ); //mDlg->listViewCommands->setSorting( -1 ); setButtons( KCModule::Default | KCModule::Apply ); connect( mDlg->checkBoxStartKNemo, SIGNAL( toggled( bool ) ), this, SLOT( checkBoxStartKNemoToggled( bool ) ) ); // Interface connect( mDlg->listBoxInterfaces, SIGNAL( currentRowChanged( int ) ), this, SLOT( interfaceSelected( int ) ) ); connect( mDlg->pushButtonNew, SIGNAL( clicked() ), this, SLOT( buttonNewSelected() ) ); connect( mDlg->pushButtonAll, SIGNAL( clicked() ), this, SLOT( buttonAllSelected() ) ); connect( mDlg->pushButtonDelete, SIGNAL( clicked() ), this, SLOT( buttonDeleteSelected() ) ); connect( mDlg->lineEditAlias, SIGNAL( textChanged( const QString& ) ), this, SLOT( aliasChanged( const QString& ) ) ); // Interface - Icon Appearance connect( mDlg->comboHiding, SIGNAL( activated( int ) ), this, SLOT( comboHidingChanged( int ) ) ); connect( mDlg->comboBoxIconTheme, SIGNAL( activated( int ) ), this, SLOT( iconThemeChanged( int ) ) ); connect( mDlg->colorIncoming, SIGNAL( changed( const QColor& ) ), this, SLOT( colorButtonChanged() ) ); connect( mDlg->colorOutgoing, SIGNAL( changed( const QColor& ) ), this, SLOT( colorButtonChanged() ) ); connect( mDlg->colorDisabled, SIGNAL( changed( const QColor& ) ), this, SLOT( colorButtonChanged() ) ); connect( mDlg->colorUnavailable, SIGNAL( changed( const QColor& ) ), this, SLOT( colorButtonChanged() ) ); connect( mDlg->iconFont, SIGNAL( currentFontChanged( const QFont& ) ), this, SLOT( iconFontChanged( const QFont& ) ) ); connect( mDlg->advancedButton, SIGNAL( clicked() ), this, SLOT( advancedButtonClicked() ) ); // Interface - Statistics connect( mDlg->checkBoxStatistics, SIGNAL( toggled( bool ) ), this, SLOT( checkBoxStatisticsToggled ( bool ) ) ); connect( mDlg->addStats, SIGNAL( clicked() ), this, SLOT( addStatsClicked() ) ); connect( mDlg->modifyStats, SIGNAL( clicked() ), this, SLOT( modifyStatsClicked() ) ); connect( mDlg->removeStats, SIGNAL( clicked() ), this, SLOT( removeStatsClicked() ) ); connect( mDlg->addWarn, SIGNAL( clicked() ), this, SLOT( addWarnClicked() ) ); connect( mDlg->modifyWarn, SIGNAL( clicked() ), this, SLOT( modifyWarnClicked() ) ); connect( mDlg->removeWarn, SIGNAL( clicked() ), this, SLOT( removeWarnClicked() ) ); // Interface - Context Menu connect( mDlg->listViewCommands, SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ), this, SLOT( listViewCommandsSelectionChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ) ); connect( mDlg->listViewCommands, SIGNAL( itemChanged( QTreeWidgetItem*, int ) ), this, SLOT( listViewCommandsChanged( QTreeWidgetItem*, int ) ) ); connect( mDlg->pushButtonAddCommand, SIGNAL( clicked() ), this, SLOT( buttonAddCommandSelected() ) ); connect( mDlg->pushButtonRemoveCommand, SIGNAL( clicked() ), this, SLOT( buttonRemoveCommandSelected() ) ); connect( mDlg->pushButtonUp, SIGNAL( clicked() ), this, SLOT( buttonCommandUpSelected() ) ); connect( mDlg->pushButtonDown, SIGNAL( clicked() ), this, SLOT( buttonCommandDownSelected() ) ); // ToolTip connect( mDlg->pushButtonAddToolTip, SIGNAL( clicked() ), this, SLOT( buttonAddToolTipSelected() ) ); connect( mDlg->pushButtonRemoveToolTip, SIGNAL( clicked() ), this, SLOT( buttonRemoveToolTipSelected() ) ); // General connect( mDlg->pushButtonNotifications, SIGNAL( clicked() ), this, SLOT( buttonNotificationsSelected() ) ); connect( mDlg->comboBoxPoll, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changed() ) ); connect( mDlg->numInputSaveInterval, SIGNAL( valueChanged( int ) ), this, SLOT( changed() ) ); connect( mDlg->useBitrate, SIGNAL( toggled( bool ) ), this, SLOT( changed() ) ); } ConfigDialog::~ConfigDialog() { delete mDlg; } void ConfigDialog::load() { mSettingsMap.clear(); mDlg->listBoxInterfaces->clear(); KConfig *config = mConfig.data(); KConfigGroup generalGroup( config, confg_general ); bool startKNemo = generalGroup.readEntry( conf_autoStart, true ); mDlg->checkBoxStartKNemo->setChecked( startKNemo ); GeneralSettings g; double pollVal = clamp(generalGroup.readEntry( conf_pollInterval, g.pollInterval ), 0.1, 2.0 ); pollVal = validatePoll( pollVal ); int index = mDlg->comboBoxPoll->findData( pollVal ); if ( index >= 0 ) mDlg->comboBoxPoll->setCurrentIndex( index ); mDlg->numInputSaveInterval->setValue( clamp(generalGroup.readEntry( conf_saveInterval, g.saveInterval ), 0, 300 ) ); mDlg->useBitrate->setChecked( generalGroup.readEntry( conf_useBitrate, g.useBitrate ) ); - mDlg->lineEditStatisticsDir->setUrl( generalGroup.readEntry( conf_statisticsDir, g.statisticsDir ) ); mToolTipContent = generalGroup.readEntry( conf_toolTipContent, g.toolTipContent ); QStringList list = generalGroup.readEntry( conf_interfaces, QStringList() ); // Get defaults from the struct InterfaceSettings s; foreach ( QString interface, list ) { QString group( confg_interface ); group += interface; InterfaceSettings* settings = new InterfaceSettings(); if ( config->hasGroup( group ) ) { KConfigGroup interfaceGroup( config, group ); settings->alias = interfaceGroup.readEntry( conf_alias ).trimmed(); settings->hideWhenDisconnected = interfaceGroup.readEntry( conf_hideWhenNotAvail, s.hideWhenDisconnected ); settings->hideWhenUnavailable = interfaceGroup.readEntry( conf_hideWhenNotExist, s.hideWhenUnavailable ); settings->trafficThreshold = clamp(interfaceGroup.readEntry( conf_trafficThreshold, s.trafficThreshold ), 0, 1000 ); settings->iconTheme = interfaceGroup.readEntry( conf_iconTheme, s.iconTheme ); settings->colorIncoming = interfaceGroup.readEntry( conf_colorIncoming, s.colorIncoming ); settings->colorOutgoing = interfaceGroup.readEntry( conf_colorOutgoing, s.colorOutgoing ); KColorScheme scheme(QPalette::Active, KColorScheme::View); settings->colorDisabled = interfaceGroup.readEntry( conf_colorDisabled, scheme.foreground( KColorScheme::InactiveText ).color() ); settings->colorUnavailable = interfaceGroup.readEntry( conf_colorUnavailable, scheme.foreground( KColorScheme::InactiveText ).color() ); settings->colorBackground = scheme.foreground( KColorScheme::InactiveText ).color(); settings->iconFont = interfaceGroup.readEntry( conf_iconFont, s.iconFont ); settings->dynamicColor = interfaceGroup.readEntry( conf_dynamicColor, s.dynamicColor ); settings->colorIncomingMax = interfaceGroup.readEntry( conf_colorIncomingMax, s.colorIncomingMax ); settings->colorOutgoingMax = interfaceGroup.readEntry( conf_colorOutgoingMax, s.colorOutgoingMax ); settings->barScale = interfaceGroup.readEntry( conf_barScale, s.barScale ); settings->inMaxRate = interfaceGroup.readEntry( conf_inMaxRate, s.inMaxRate ); settings->outMaxRate = interfaceGroup.readEntry( conf_outMaxRate, s.outMaxRate ); settings->calendarSystem = static_cast(interfaceGroup.readEntry( conf_calendarSystem, static_cast(KLocale::QDateCalendar) )); settings->activateStatistics = interfaceGroup.readEntry( conf_activateStatistics, s.activateStatistics ); int statsRuleCount = interfaceGroup.readEntry( conf_statsRules, 0 ); for ( int i = 0; i < statsRuleCount; ++i ) { group = QString::fromLatin1( "%1%2 #%3" ).arg( confg_statsRule ).arg( interface ).arg( i ); if ( config->hasGroup( group ) ) { KConfigGroup statsGroup( config, group ); StatsRule stats; stats.startDate = statsGroup.readEntry( conf_statsStartDate, QDate() ); stats.periodUnits = clamp(statsGroup.readEntry( conf_statsPeriodUnits, stats.periodUnits ), KNemoStats::Day, KNemoStats::Year ); stats.periodCount = clamp(statsGroup.readEntry( conf_statsPeriodCount, stats.periodCount ), 1, 1000 ); stats.logOffpeak = statsGroup.readEntry( conf_logOffpeak,stats.logOffpeak ); stats.offpeakStartTime = QTime::fromString( statsGroup.readEntry( conf_offpeakStartTime, stats.offpeakStartTime.toString( Qt::ISODate ) ), Qt::ISODate ); stats.offpeakEndTime = QTime::fromString( statsGroup.readEntry( conf_offpeakEndTime, stats.offpeakEndTime.toString( Qt::ISODate ) ), Qt::ISODate ); stats.weekendIsOffpeak = statsGroup.readEntry( conf_weekendIsOffpeak, stats.weekendIsOffpeak ); stats.weekendDayStart = statsGroup.readEntry( conf_weekendDayStart, stats.weekendDayStart ); stats.weekendDayEnd = statsGroup.readEntry( conf_weekendDayEnd, stats.weekendDayEnd ); stats.weekendTimeStart = QTime::fromString( statsGroup.readEntry( conf_weekendTimeStart, stats.weekendTimeStart.toString( Qt::ISODate ) ), Qt::ISODate ); stats.weekendTimeEnd = QTime::fromString( statsGroup.readEntry( conf_weekendTimeEnd, stats.weekendTimeEnd.toString( Qt::ISODate ) ), Qt::ISODate ); settings->statsRules << stats; } } int warnRuleCount = interfaceGroup.readEntry( conf_warnRules, 0 ); for ( int i = 0; i < warnRuleCount; ++i ) { group = QString::fromLatin1( "%1%2 #%3" ).arg( confg_warnRule ).arg( interface ).arg( i ); if ( config->hasGroup( group ) ) { KConfigGroup warnGroup( config, group ); WarnRule warn; warn.periodUnits = clamp(warnGroup.readEntry( conf_warnPeriodUnits, warn.periodUnits ), KNemoStats::Hour, KNemoStats::Year ); warn.periodCount = clamp(warnGroup.readEntry( conf_warnPeriodCount, warn.periodCount ), 1, 1000 ); warn.trafficType = clamp(warnGroup.readEntry( conf_warnTrafficType, warn.trafficType ), KNemoStats::Peak, KNemoStats::PeakOffpeak ); warn.trafficDirection = clamp(warnGroup.readEntry( conf_warnTrafficDirection, warn.trafficDirection ), KNemoStats::TrafficIn, KNemoStats::TrafficTotal ); warn.trafficUnits = clamp(warnGroup.readEntry( conf_warnTrafficUnits, warn.trafficUnits ), KNemoStats::UnitB, KNemoStats::UnitG ); warn.threshold = clamp(warnGroup.readEntry( conf_warnThreshold, warn.threshold ), 0.0, 9999.0 ); warn.customText = warnGroup.readEntry( conf_warnCustomText, warn.customText ).trimmed(); settings->warnRules << warn; } } int numCommands = interfaceGroup.readEntry( conf_numCommands, s.numCommands ); for ( int i = 0; i < numCommands; i++ ) { QString entry; InterfaceCommand cmd; entry = QString::fromLatin1( "%1%2" ).arg( conf_runAsRoot ).arg( i + 1 ); cmd.runAsRoot = interfaceGroup.readEntry( entry, false ); entry = QString::fromLatin1( "%1%2" ).arg( conf_command ).arg( i + 1 ); cmd.command = interfaceGroup.readEntry( entry ); entry = QString::fromLatin1( "%1%2" ).arg( conf_menuText ).arg( i + 1 ); cmd.menuText = interfaceGroup.readEntry( entry ); settings->commands.append( cmd ); } } mSettingsMap.insert( interface, settings ); mDlg->listBoxInterfaces->addItem( interface ); mDlg->pushButtonDelete->setEnabled( true ); mDlg->ifaceTab->setEnabled( true ); } // These things need to be here so that 'Reset' from the control // center is handled correctly. setupToolTipTab(); // In case the user opened the control center via the context menu // this call to the daemon will deliver the interface the menu // belongs to. This way we can preselect the appropriate entry in the list. QString selectedInterface = QString::null; QDBusMessage reply = QDBusInterface(QLatin1String("org.kde.knemo"), QLatin1String("/knemo"), QLatin1String("org.kde.knemo")).call(QLatin1String("getSelectedInterface")); if ( reply.arguments().count() ) { selectedInterface = reply.arguments().first().toString(); } if ( selectedInterface != QString::null ) { // Try to preselect the interface. int i; for ( i = 0; i < mDlg->listBoxInterfaces->count(); i++ ) { if ( mDlg->listBoxInterfaces->item( i )->text() == selectedInterface ) { // Found it. mDlg->listBoxInterfaces->setCurrentRow( i ); break; } } if ( i == mDlg->listBoxInterfaces->count() ) { // Not found. Select first entry in list. mDlg->listBoxInterfaces->setCurrentRow( 0 ); } } else if ( mDlg->listBoxInterfaces->count() ) { // No interface from KNemo. Select first entry in list. mDlg->listBoxInterfaces->setCurrentRow( 0 ); } } void ConfigDialog::save() { KConfig *config = mConfig.data(); QStringList list; // Remove interfaces from the config that were deleted during this session foreach ( QString delIface, mDeletedIfaces ) { if ( !mSettingsMap.contains( delIface ) ) { config->deleteGroup( confg_interface + delIface ); config->deleteGroup( confg_plotter + delIface ); } } QStringList groupList = config->groupList(); foreach ( QString tempDel, groupList ) { if ( tempDel.contains( confg_statsRule ) || tempDel.contains( confg_warnRule ) ) config->deleteGroup( tempDel ); } foreach ( QString it, mSettingsMap.keys() ) { list.append( it ); InterfaceSettings* settings = mSettingsMap.value( it ); KConfigGroup interfaceGroup( config, confg_interface + it ); // Preserve settings set by the app before delete QPoint plotterPos = interfaceGroup.readEntry( conf_plotterPos, QPoint() ); QSize plotterSize = interfaceGroup.readEntry( conf_plotterSize, QSize() ); QPoint statisticsPos = interfaceGroup.readEntry( conf_statisticsPos, QPoint() ); QSize statisticsSize = interfaceGroup.readEntry( conf_statisticsSize, QSize() ); QPoint statusPos = interfaceGroup.readEntry( conf_statusPos, QPoint() ); QSize statusSize = interfaceGroup.readEntry( conf_statusSize, QSize() ); QByteArray hourState = interfaceGroup.readEntry( conf_hourState, QByteArray() ); QByteArray dayState = interfaceGroup.readEntry( conf_dayState, QByteArray() ); QByteArray weekState = interfaceGroup.readEntry( conf_weekState, QByteArray() ); QByteArray monthState = interfaceGroup.readEntry( conf_monthState, QByteArray() ); QByteArray billingState = interfaceGroup.readEntry( conf_billingState, QByteArray() ); QByteArray yearState = interfaceGroup.readEntry( conf_yearState, QByteArray() ); // Make sure we don't get crufty commands left over interfaceGroup.deleteGroup(); if ( !plotterPos.isNull() ) interfaceGroup.writeEntry( conf_plotterPos, plotterPos ); if ( !plotterSize.isEmpty() ) interfaceGroup.writeEntry( conf_plotterSize, plotterSize ); if ( !statisticsPos.isNull() ) interfaceGroup.writeEntry( conf_statisticsPos, statisticsPos ); if ( !statisticsSize.isEmpty() ) interfaceGroup.writeEntry( conf_statisticsSize, statisticsSize ); if ( !statusPos.isNull() ) interfaceGroup.writeEntry( conf_statusPos, statusPos ); if ( !statusSize.isEmpty() ) interfaceGroup.writeEntry( conf_statusSize, statusSize ); if ( !settings->alias.trimmed().isEmpty() ) interfaceGroup.writeEntry( conf_alias, settings->alias ); if ( !hourState.isNull() ) interfaceGroup.writeEntry( conf_hourState, hourState ); if ( !dayState.isNull() ) interfaceGroup.writeEntry( conf_dayState, dayState ); if ( !weekState.isNull() ) interfaceGroup.writeEntry( conf_weekState, weekState ); if ( !monthState.isNull() ) interfaceGroup.writeEntry( conf_monthState, monthState ); if ( !billingState.isNull() ) interfaceGroup.writeEntry( conf_billingState, billingState ); if ( !yearState.isNull() ) interfaceGroup.writeEntry( conf_yearState, yearState ); interfaceGroup.writeEntry( conf_hideWhenNotAvail, settings->hideWhenDisconnected ); interfaceGroup.writeEntry( conf_hideWhenNotExist, settings->hideWhenUnavailable ); interfaceGroup.writeEntry( conf_trafficThreshold, settings->trafficThreshold ); interfaceGroup.writeEntry( conf_iconTheme, settings->iconTheme ); if ( settings->iconTheme == TEXT_THEME || settings->iconTheme == NETLOAD_THEME ) { interfaceGroup.writeEntry( conf_colorIncoming, settings->colorIncoming ); interfaceGroup.writeEntry( conf_colorOutgoing, settings->colorOutgoing ); interfaceGroup.writeEntry( conf_colorDisabled, settings->colorDisabled ); interfaceGroup.writeEntry( conf_colorUnavailable, settings->colorUnavailable ); interfaceGroup.writeEntry( conf_dynamicColor, settings->dynamicColor ); if ( settings->dynamicColor ) { interfaceGroup.writeEntry( conf_colorIncomingMax, settings->colorIncomingMax ); interfaceGroup.writeEntry( conf_colorOutgoingMax, settings->colorOutgoingMax ); } if ( settings->iconTheme == NETLOAD_THEME ) { interfaceGroup.writeEntry( conf_barScale, settings->barScale ); } if ( settings->iconTheme == TEXT_THEME && settings->iconFont != QFontDatabase::systemFont( QFontDatabase::GeneralFont ) ) { interfaceGroup.writeEntry( conf_iconFont, settings->iconFont ); } if ( settings->dynamicColor || ( settings->iconTheme == NETLOAD_THEME && settings->barScale ) ) { interfaceGroup.writeEntry( conf_inMaxRate, settings->inMaxRate ); interfaceGroup.writeEntry( conf_outMaxRate, settings->outMaxRate ); } } interfaceGroup.writeEntry( conf_activateStatistics, settings->activateStatistics ); interfaceGroup.writeEntry( conf_calendarSystem, static_cast(settings->calendarSystem) ); interfaceGroup.writeEntry( conf_statsRules, settings->statsRules.count() ); for ( int i = 0; i < settings->statsRules.count(); i++ ) { QString group = QString::fromLatin1( "%1%2 #%3" ).arg( confg_statsRule ).arg( it ).arg( i ); KConfigGroup statsGroup( config, group ); statsGroup.writeEntry( conf_statsStartDate, settings->statsRules[i].startDate ); statsGroup.writeEntry( conf_statsPeriodUnits, settings->statsRules[i].periodUnits ); statsGroup.writeEntry( conf_statsPeriodCount, settings->statsRules[i].periodCount ); statsGroup.writeEntry( conf_logOffpeak, settings->statsRules[i].logOffpeak ); if ( settings->statsRules[i].logOffpeak ) { statsGroup.writeEntry( conf_offpeakStartTime, settings->statsRules[i].offpeakStartTime.toString( Qt::ISODate ) ); statsGroup.writeEntry( conf_offpeakEndTime, settings->statsRules[i].offpeakEndTime.toString( Qt::ISODate ) ); statsGroup.writeEntry( conf_weekendIsOffpeak, settings->statsRules[i].weekendIsOffpeak ); if ( settings->statsRules[i].weekendIsOffpeak ) { statsGroup.writeEntry( conf_weekendDayStart, settings->statsRules[i].weekendDayStart ); statsGroup.writeEntry( conf_weekendDayEnd, settings->statsRules[i].weekendDayEnd ); statsGroup.writeEntry( conf_weekendTimeStart, settings->statsRules[i].weekendTimeStart.toString( Qt::ISODate ) ); statsGroup.writeEntry( conf_weekendTimeEnd, settings->statsRules[i].weekendTimeEnd.toString( Qt::ISODate ) ); } } } interfaceGroup.writeEntry( conf_warnRules, settings->warnRules.count() ); for ( int i = 0; i < settings->warnRules.count(); i++ ) { QString group = QString::fromLatin1( "%1%2 #%3" ).arg( confg_warnRule ).arg( it ).arg( i ); KConfigGroup warnGroup( config, group ); if ( settings->statsRules.count() == 0 && settings->warnRules[i].periodUnits == KNemoStats::BillPeriod ) { warnGroup.writeEntry( conf_warnPeriodUnits, static_cast(KNemoStats::Month) ); } else { warnGroup.writeEntry( conf_warnPeriodUnits, settings->warnRules[i].periodUnits ); } warnGroup.writeEntry( conf_warnPeriodCount, settings->warnRules[i].periodCount ); warnGroup.writeEntry( conf_warnTrafficType, settings->warnRules[i].trafficType ); warnGroup.writeEntry( conf_warnTrafficDirection, settings->warnRules[i].trafficDirection ); warnGroup.writeEntry( conf_warnTrafficUnits, settings->warnRules[i].trafficUnits ); warnGroup.writeEntry( conf_warnThreshold, settings->warnRules[i].threshold ); warnGroup.writeEntry( conf_warnCustomText, settings->warnRules[i].customText.trimmed() ); } interfaceGroup.writeEntry( conf_numCommands, settings->commands.size() ); for ( int i = 0; i < settings->commands.size(); i++ ) { QString entry; entry = QString::fromLatin1( "%1%2" ).arg( conf_runAsRoot ).arg( i + 1 ); interfaceGroup.writeEntry( entry, settings->commands[i].runAsRoot ); entry = QString::fromLatin1( "%1%2" ).arg( conf_command ).arg( i + 1 ); interfaceGroup.writeEntry( entry, settings->commands[i].command ); entry = QString::fromLatin1( "%1%2" ).arg( conf_menuText ).arg( i + 1 ); interfaceGroup.writeEntry( entry, settings->commands[i].menuText ); } } KConfigGroup generalGroup( config, confg_general ); generalGroup.writeEntry( conf_firstStart, false ); generalGroup.writeEntry( conf_autoStart, mDlg->checkBoxStartKNemo->isChecked() ); generalGroup.writeEntry( conf_pollInterval, mDlg->comboBoxPoll->itemData( mDlg->comboBoxPoll->currentIndex() ).value() ); generalGroup.writeEntry( conf_saveInterval, mDlg->numInputSaveInterval->value() ); generalGroup.writeEntry( conf_useBitrate, mDlg->useBitrate->isChecked() ); - generalGroup.writeEntry( conf_statisticsDir, mDlg->lineEditStatisticsDir->url().url() ); generalGroup.writeEntry( conf_toolTipContent, mToolTipContent ); generalGroup.writeEntry( conf_interfaces, list ); config->sync(); QDBusMessage reply = QDBusInterface(QLatin1String("org.kde.knemo"), QLatin1String("/knemo"), QLatin1String("org.kde.knemo")).call(QLatin1String("reparseConfiguration")); } void ConfigDialog::defaults() { // Set these values before we check for default interfaces mSettingsMap.clear(); mDlg->listBoxInterfaces->clear(); mDlg->pushButtonDelete->setEnabled( false ); InterfaceSettings emptySettings; updateControls( &emptySettings ); // Default interface void *cache = NULL; #ifdef __linux__ struct nl_sock *rtsock = nl_socket_alloc(); int c = nl_connect(rtsock, NETLINK_ROUTE); if ( c >= 0 ) { rtnl_route_alloc_cache( rtsock, AF_UNSPEC, NL_AUTO_PROVIDE, reinterpret_cast(&cache) ); } #endif QString interface = getDefaultRoute( AF_INET, NULL, cache ); if ( interface.isEmpty() ) interface = getDefaultRoute( AF_INET6, NULL, cache ); #ifdef __linux__ nl_cache_free( static_cast(cache) ); nl_close( rtsock ); nl_socket_free( rtsock ); #endif if ( interface.isEmpty() ) { mDlg->aliasLabel->setEnabled( false ); mDlg->lineEditAlias->setEnabled( false ); mDlg->ifaceTab->setEnabled( false ); mDlg->pixmapError->clear(); mDlg->pixmapDisconnected->clear(); mDlg->pixmapConnected->clear(); mDlg->pixmapIncoming->clear(); mDlg->pixmapOutgoing->clear(); mDlg->pixmapTraffic->clear(); } else { InterfaceSettings* settings = new InterfaceSettings(); KColorScheme scheme(QPalette::Active, KColorScheme::View); settings->colorDisabled = scheme.foreground( KColorScheme::InactiveText ).color(); settings->colorUnavailable = scheme.foreground( KColorScheme::InactiveText ).color(); settings->colorBackground = scheme.foreground( KColorScheme::InactiveText ).color(); settings->iconFont = QFontDatabase::systemFont( QFontDatabase::GeneralFont ); mSettingsMap.insert( interface, settings ); mDlg->listBoxInterfaces->addItem( interface ); mDlg->listBoxInterfaces->setCurrentRow( 0 ); mDlg->pushButtonDelete->setEnabled( true ); mDlg->aliasLabel->setEnabled( true ); mDlg->lineEditAlias->setEnabled( true ); mDlg->ifaceTab->setEnabled( true ); } // Default general settings GeneralSettings g; int index = mDlg->comboBoxPoll->findData( g.pollInterval ); if ( index >= 0 ) mDlg->comboBoxPoll->setCurrentIndex( index ); mDlg->numInputSaveInterval->setValue( g.saveInterval ); mDlg->useBitrate->setChecked( g.useBitrate ); - mDlg->lineEditStatisticsDir->setUrl( g.statisticsDir ); // Default tool tips mToolTipContent = g.toolTipContent; setupToolTipTab(); changed( true ); } void ConfigDialog::checkBoxStartKNemoToggled( bool on ) { if ( on ) { KConfig *config = mConfig.data(); KConfigGroup generalGroup( config, confg_general ); if ( generalGroup.readEntry( conf_firstStart, true ) ) { // Populate the dialog with some default values if the user starts // KNemo for the very first time. defaults(); } } if (!mLock) changed( true ); } /****************************************** * * * Interface tab * * * ******************************************/ InterfaceSettings * ConfigDialog::getItemSettings() { if ( !mDlg->listBoxInterfaces->currentItem() ) return NULL; QListWidgetItem* selected = mDlg->listBoxInterfaces->currentItem(); return mSettingsMap[selected->text()]; } QString ConfigDialog::findNameFromIndex( int index ) { KNemoTheme theme = mDlg->comboBoxIconTheme->itemData( index ).value(); return theme.internalName; } int ConfigDialog::findIndexFromName( const QString& internalName ) { for( int i = 0; i < mDlg->comboBoxIconTheme->count(); i++ ) { KNemoTheme theme = mDlg->comboBoxIconTheme->itemData( i ).value(); if ( theme.internalName == internalName ) return i; } return -1; } void ConfigDialog::updateWarnText( int oldCount ) { // If the billing periods go away, the warn period will change to months // This only changes the text displayed in the model, so it can change // back if a billing period reappears. if ( ! statsModel->rowCount() ) { QList warnRules = warnModel->getRules(); for ( int i = 0; i < warnRules.count(); ++i ) { if ( warnRules[i].periodUnits == KNemoStats::BillPeriod ) { warnModel->item( i, 1 )->setData( periodText( warnRules[i].periodCount, KNemoStats::Month ), Qt::DisplayRole ); } } } else if ( oldCount == 0 ) { QList warnRules = warnModel->getRules(); for ( int i = 0; i < warnRules.count(); ++i ) { if ( warnRules[i].periodUnits == KNemoStats::BillPeriod ) warnModel->item( i, 1 )->setData( periodText( warnRules[i].periodCount, warnRules[i].periodUnits ), Qt::DisplayRole ); } } } void ConfigDialog::updateControls( InterfaceSettings *settings ) { mLock = true; mDlg->lineEditAlias->setText( settings->alias ); int index = findIndexFromName( settings->iconTheme ); if ( index < 0 ) index = findIndexFromName( TEXT_THEME ); mDlg->comboBoxIconTheme->setCurrentIndex( index ); mDlg->colorIncoming->setColor( settings->colorIncoming ); mDlg->colorOutgoing->setColor( settings->colorOutgoing ); mDlg->colorDisabled->setColor( settings->colorDisabled ); mDlg->colorUnavailable->setColor( settings->colorUnavailable ); mDlg->iconFont->setCurrentFont( settings->iconFont ); iconThemeChanged( index ); if ( settings->hideWhenDisconnected ) index = 1; else if ( settings->hideWhenUnavailable ) index = 2; else index = 0; mDlg->comboHiding->setCurrentIndex( index ); comboHidingChanged( index ); mDlg->checkBoxStatistics->setChecked( settings->activateStatistics ); if ( !mCalendar || mCalendar->calendarSystem() != settings->calendarSystem ) mCalendar = KCalendarSystem::create( settings->calendarSystem ); statsModel->removeRows(0, statsModel->rowCount() ); statsModel->setCalendar( mCalendar ); foreach( StatsRule s, settings->statsRules ) { statsModel->addRule( s ); } if ( statsModel->rowCount() ) { QSortFilterProxyModel* proxy = static_cast(mDlg->statsView->model()); QModelIndex index = statsModel->indexFromItem( statsModel->item( 0, 0 ) ); mDlg->statsView->setCurrentIndex( proxy->mapFromSource( index ) ); } mDlg->modifyStats->setEnabled( statsModel->rowCount() ); mDlg->removeStats->setEnabled( statsModel->rowCount() ); warnModel->removeRows(0, warnModel->rowCount() ); foreach( WarnRule warn, settings->warnRules ) { warnModel->addWarn( warn ); } updateWarnText( statsModel->rowCount() ); mDlg->modifyWarn->setEnabled( warnModel->rowCount() ); mDlg->removeWarn->setEnabled( warnModel->rowCount() ); if ( warnModel->rowCount() ) { mDlg->warnView->setCurrentIndex( warnModel->indexFromItem ( warnModel->item( 0, 0 ) ) ); } mDlg->listViewCommands->clear(); QListitems; foreach ( InterfaceCommand command, settings->commands ) { QTreeWidgetItem* item = new QTreeWidgetItem(); enum Qt::CheckState checkState = Qt::Unchecked; if ( command.runAsRoot ) checkState = Qt::Checked; item->setCheckState( 0, checkState ); item->setFlags( item->flags() | Qt::ItemIsEditable ); item->setText( 1, command.menuText ); item->setText( 2, command.command ); items << item; } if ( items.count() > 0 ) { mDlg->listViewCommands->addTopLevelItems( items ); mDlg->listViewCommands->setCurrentItem( items[0] ); mDlg->pushButtonRemoveCommand->setEnabled( true ); setUpDownButtons( items[0] ); } else { mDlg->pushButtonRemoveCommand->setEnabled( false ); setUpDownButtons( NULL ); } mLock = false; } void ConfigDialog::interfaceSelected( int row ) { if ( row < 0 ) return; QString interface = mDlg->listBoxInterfaces->item( row )->text(); InterfaceSettings* settings = mSettingsMap[interface]; mDlg->ifaceTab->setEnabled( true ); mDlg->aliasLabel->setEnabled( true ); mDlg->lineEditAlias->setEnabled( true ); updateControls( settings ); } void ConfigDialog::buttonNewSelected() { bool ok = false; QString ifname = QInputDialog::getText( this, i18n( "Add new interface" ), i18n( "Please enter the name of the interface to be monitored.\nIt should be something like 'eth1', 'wlan2' or 'ppp0'." ), QLineEdit::Normal, QString::null, &ok ); if ( ok ) { QListWidgetItem *item = new QListWidgetItem( ifname ); mDlg->listBoxInterfaces->addItem( item ); InterfaceSettings *settings = new InterfaceSettings(); KColorScheme scheme(QPalette::Active, KColorScheme::View); settings->colorDisabled = scheme.foreground( KColorScheme::InactiveText ).color(); settings->colorUnavailable = scheme.foreground( KColorScheme::InactiveText ).color(); settings->colorBackground = scheme.foreground( KColorScheme::InactiveText ).color(); settings->iconFont = QFontDatabase::systemFont( QFontDatabase::GeneralFont ); mSettingsMap.insert( ifname, settings ); mDlg->listBoxInterfaces->setCurrentRow( mDlg->listBoxInterfaces->row( item ) ); mDlg->pushButtonDelete->setEnabled( true ); changed( true ); } } void ConfigDialog::buttonAllSelected() { QStringList ifaces; #ifdef __linux__ nl_cache * linkCache = NULL; nl_sock *rtsock = nl_socket_alloc(); int c = nl_connect(rtsock, NETLINK_ROUTE); if ( c >= 0 ) { rtnl_link_alloc_cache( rtsock, AF_UNSPEC, &linkCache ); struct rtnl_link * rtlink; for ( rtlink = reinterpret_cast(nl_cache_get_first( linkCache )); rtlink != NULL; rtlink = reinterpret_cast(nl_cache_get_next( reinterpret_cast(rtlink) )) ) { QString ifname( QLatin1String(rtnl_link_get_name( rtlink )) ); ifaces << ifname; } } nl_cache_free( linkCache ); nl_close( rtsock ); nl_socket_free( rtsock ); #else struct ifaddrs *ifaddr; struct ifaddrs *ifa; getifaddrs( &ifaddr ); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { QString ifname( ifa->ifa_name ); ifaces << ifname; } freeifaddrs( ifaddr ); #endif ifaces.removeAll( QLatin1String("lo") ); ifaces.removeAll( QLatin1String("lo0") ); const KColorScheme scheme(QPalette::Active, KColorScheme::View); foreach ( QString ifname, ifaces ) { if ( mSettingsMap.contains( ifname ) ) continue; InterfaceSettings* settings = new InterfaceSettings(); settings->colorDisabled = scheme.foreground( KColorScheme::InactiveText ).color(); settings->colorUnavailable = scheme.foreground( KColorScheme::InactiveText ).color(); settings->colorBackground = scheme.foreground( KColorScheme::InactiveText ).color(); settings->iconFont = QFontDatabase::systemFont( QFontDatabase::GeneralFont ); mSettingsMap.insert( ifname, settings ); mDlg->listBoxInterfaces->addItem( ifname ); } if ( mDlg->listBoxInterfaces->count() > 0 ) { mDlg->listBoxInterfaces->setCurrentRow( 0 ); mDlg->pushButtonDelete->setEnabled( true ); mDlg->ifaceTab->setEnabled( true ); QString iface = mDlg->listBoxInterfaces->item( 0 )->text(); } changed( true ); } void ConfigDialog::buttonDeleteSelected() { if ( !mDlg->listBoxInterfaces->currentItem() ) return; QListWidgetItem* selected = mDlg->listBoxInterfaces->currentItem(); // To prevent bloat when we save if ( !mDeletedIfaces.contains( selected->text() ) ) mDeletedIfaces << selected->text(); mSettingsMap.remove( selected->text() ); QListWidgetItem *taken = mDlg->listBoxInterfaces->takeItem( mDlg->listBoxInterfaces->row( selected ) ); delete taken; if ( mDlg->listBoxInterfaces->count() < 1 ) { InterfaceSettings emptySettings; updateControls( &emptySettings ); mDlg->pushButtonDelete->setEnabled( false ); mDlg->aliasLabel->setEnabled( false ); mDlg->lineEditAlias->setEnabled( false ); mDlg->ifaceTab->setEnabled( false ); mDlg->pixmapError->clear(); mDlg->pixmapDisconnected->clear(); mDlg->pixmapConnected->clear(); mDlg->pixmapIncoming->clear(); mDlg->pixmapOutgoing->clear(); mDlg->pixmapTraffic->clear(); } changed( true ); } void ConfigDialog::aliasChanged( const QString& text ) { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; settings->alias = text; if (!mLock) changed( true ); } /****************************************** * * * Interface tab - Icon Appearance * * * ******************************************/ QPixmap ConfigDialog::textIcon( QString incomingText, QString outgoingText, int status ) { QPixmap sampleIcon( 22, 22 ); sampleIcon.fill( Qt::transparent ); QRect topRect( 0, 0, 22, 11 ); QRect bottomRect( 0, 11, 22, 11 ); QPainter p( &sampleIcon ); p.setBrush( Qt::NoBrush ); p.setOpacity( 1.0 ); QFont rxFont = setIconFont( incomingText, mDlg->iconFont->currentFont(), 22 ); QFont txFont = setIconFont( outgoingText, mDlg->iconFont->currentFont(), 22 ); if ( rxFont.pointSizeF() > txFont.pointSizeF() ) rxFont.setPointSizeF( txFont.pointSizeF() ); p.setFont( rxFont ); if ( status >= KNemoIface::Connected ) p.setPen( mDlg->colorIncoming->color() ); else if ( status == KNemoIface::Available ) p.setPen( mDlg->colorDisabled->color() ); else p.setPen( mDlg->colorUnavailable->color() ); p.drawText( topRect, Qt::AlignCenter | Qt::AlignRight, incomingText ); p.setFont( rxFont ); if ( status >= KNemoIface::Connected ) p.setPen( mDlg->colorOutgoing->color() ); p.drawText( bottomRect, Qt::AlignCenter | Qt::AlignRight, outgoingText ); return sampleIcon; } QPixmap ConfigDialog::barIcon( int status ) { int barIncoming = 0; int barOutgoing = 0; QPixmap barIcon( 22, 22 ); barIcon.fill( Qt::transparent ); QPainter p( &barIcon ); QLinearGradient inGrad( 12, 0, 19, 0 ); QLinearGradient topInGrad( 12, 0, 19, 0 ); QLinearGradient outGrad( 3, 0, 10, 0 ); QLinearGradient topOutGrad( 3, 0, 10, 0 ); QColor topColor = getItemSettings()->colorBackground; QColor topColorD = getItemSettings()->colorBackground.darker(); topColor.setAlpha( 128 ); topColorD.setAlpha( 128 ); topInGrad.setColorAt(0, topColorD); topInGrad.setColorAt(1, topColor ); topOutGrad.setColorAt(0, topColorD); topOutGrad.setColorAt(1, topColor ); if ( status & KNemoIface::Connected ) { inGrad.setColorAt(0, mDlg->colorIncoming->color() ); inGrad.setColorAt(1, mDlg->colorIncoming->color().darker() ); outGrad.setColorAt(0, mDlg->colorOutgoing->color() ); outGrad.setColorAt(1, mDlg->colorOutgoing->color().darker() ); } else if ( status & KNemoIface::Available ) { inGrad.setColorAt(0, mDlg->colorDisabled->color()); inGrad.setColorAt(1, mDlg->colorDisabled->color().darker() ); outGrad.setColorAt(0, mDlg->colorDisabled->color() ); outGrad.setColorAt(1, mDlg->colorDisabled->color().darker() ); } else { inGrad.setColorAt(0, mDlg->colorUnavailable->color() ); inGrad.setColorAt(1, mDlg->colorUnavailable->color().darker() ); outGrad.setColorAt(0, mDlg->colorUnavailable->color() ); outGrad.setColorAt(1, mDlg->colorUnavailable->color().darker() ); } if ( status & KNemoIface::Available || status & KNemoIface::Unavailable ) { barIncoming = 22; barOutgoing = 22; } if ( status & KNemoIface::RxTraffic ) barIncoming = 17; if ( status & KNemoIface::TxTraffic ) barOutgoing = 17; int top = 22 - barOutgoing; QRect topLeftRect( 3, 0, 7, top ); QRect leftRect( 3, top, 7, 22 ); top = 22 - barIncoming; QRect topRightRect( 12, 0, 7, top ); QRect rightRect( 12, top, 7, 22 ); QBrush brush( inGrad ); p.setBrush( brush ); p.fillRect( rightRect, inGrad ); brush = QBrush( topInGrad ); p.fillRect( topRightRect, topInGrad ); brush = QBrush( outGrad ); p.fillRect( leftRect, outGrad ); brush = QBrush( topOutGrad ); p.fillRect( topLeftRect, topOutGrad ); return barIcon; } void ConfigDialog::comboHidingChanged( int val ) { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; switch ( val ) { case 0: settings->hideWhenDisconnected = false; settings->hideWhenUnavailable = false; break; case 1: settings->hideWhenDisconnected = true; settings->hideWhenUnavailable = true; break; case 2: settings->hideWhenDisconnected = false; settings->hideWhenUnavailable = true; break; } if (!mLock) changed( true ); } void ConfigDialog::iconThemeChanged( int set ) { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; KNemoTheme curTheme = mDlg->comboBoxIconTheme->itemData( mDlg->comboBoxIconTheme->currentIndex() ).value(); if ( curTheme.internalName != TEXT_THEME ) { mDlg->iconFontLabel->setEnabled( false ); mDlg->iconFont->setEnabled( false ); } if ( curTheme.internalName == TEXT_THEME || curTheme.internalName == NETLOAD_THEME ) { if ( curTheme.internalName == TEXT_THEME ) { QString f1 = QStringLiteral("0.0K"); QString f2 = QStringLiteral("123K"); QString f3 = QStringLiteral("12K"); settings->iconTheme = TEXT_THEME; mDlg->pixmapError->setPixmap( textIcon( f1, f1, KNemoIface::Unavailable ) ); mDlg->pixmapDisconnected->setPixmap( textIcon( f1, f1, KNemoIface::Available ) ); mDlg->pixmapConnected->setPixmap( textIcon( f1, f1, KNemoIface::Connected ) ); mDlg->pixmapIncoming->setPixmap( textIcon( f2, f1, KNemoIface::Connected ) ); mDlg->pixmapOutgoing->setPixmap( textIcon( f1, f3, KNemoIface::Connected ) ); mDlg->pixmapTraffic->setPixmap( textIcon( f2, f3, KNemoIface::Connected ) ); mDlg->iconFontLabel->setEnabled( true ); mDlg->iconFont->setEnabled( true ); } else { settings->iconTheme = NETLOAD_THEME; mDlg->pixmapError->setPixmap( barIcon( KNemoIface::Unavailable ) ); mDlg->pixmapDisconnected->setPixmap( barIcon( KNemoIface::Available ) ); mDlg->pixmapConnected->setPixmap( barIcon( KNemoIface::Connected ) ); mDlg->pixmapIncoming->setPixmap( barIcon( KNemoIface::Connected | KNemoIface::RxTraffic ) ); mDlg->pixmapOutgoing->setPixmap( barIcon( KNemoIface::Connected | KNemoIface::TxTraffic ) ); mDlg->pixmapTraffic->setPixmap( barIcon( KNemoIface::Connected | KNemoIface::RxTraffic | KNemoIface::TxTraffic ) ); } mDlg->themeColorBox->setEnabled( true ); } else { settings->iconTheme = findNameFromIndex( set ); QString iconName; if ( settings->iconTheme == SYSTEM_THEME ) iconName = QLatin1String("network-"); else iconName = QLatin1String("knemo-") + settings->iconTheme + QLatin1Char('-'); mDlg->pixmapError->setPixmap( QIcon::fromTheme( iconName + ICON_ERROR ).pixmap( 22 ) ); mDlg->pixmapDisconnected->setPixmap( QIcon::fromTheme( iconName + ICON_OFFLINE ).pixmap( 22 ) ); mDlg->pixmapConnected->setPixmap( QIcon::fromTheme( iconName + ICON_IDLE ).pixmap( 22 ) ); mDlg->pixmapIncoming->setPixmap( QIcon::fromTheme( iconName + ICON_RX ).pixmap( 22 ) ); mDlg->pixmapOutgoing->setPixmap( QIcon::fromTheme( iconName + ICON_TX ).pixmap( 22 ) ); mDlg->pixmapTraffic->setPixmap( QIcon::fromTheme( iconName + ICON_RX_TX ).pixmap( 22 ) ); mDlg->themeColorBox->setEnabled( false ); } if (!mLock) changed( true ); } void ConfigDialog::colorButtonChanged() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; if ( mDlg->colorIncoming->color().isValid() ) settings->colorIncoming = mDlg->colorIncoming->color(); if ( mDlg->colorOutgoing->color().isValid() ) settings->colorOutgoing = mDlg->colorOutgoing->color(); if ( mDlg->colorDisabled->color().isValid() ) settings->colorDisabled = mDlg->colorDisabled->color(); if ( mDlg->colorUnavailable->color().isValid() ) settings->colorUnavailable = mDlg->colorUnavailable->color(); KNemoTheme curTheme = mDlg->comboBoxIconTheme->itemData( mDlg->comboBoxIconTheme->currentIndex() ).value(); if ( curTheme.internalName == TEXT_THEME || curTheme.internalName == NETLOAD_THEME ) iconThemeChanged( mDlg->comboBoxIconTheme->currentIndex() ); if ( !mLock) changed( true ); } void ConfigDialog::iconFontChanged( const QFont &font ) { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; if ( font != settings->iconFont ) { settings->iconFont = font; iconThemeChanged( mDlg->comboBoxIconTheme->currentIndex() ); } if ( !mLock ) changed( true ); } void ConfigDialog::advancedButtonClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; ThemeConfig dlg( *settings ); if ( dlg.exec() ) { InterfaceSettings s = dlg.settings(); settings->trafficThreshold = s.trafficThreshold; settings->dynamicColor = s.dynamicColor; settings->colorIncomingMax = s.colorIncomingMax; settings->colorOutgoingMax = s.colorOutgoingMax; settings->barScale = s.barScale; settings->inMaxRate = s.inMaxRate; settings->outMaxRate = s.outMaxRate; changed( true ); } } void ConfigDialog::addStatsClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; StatsRule rule; int oldRuleCount = statsModel->rowCount(); StatsConfig dlg( settings, mCalendar, rule, true ); if ( dlg.exec() ) { rule = dlg.settings(); QSortFilterProxyModel* proxy = static_cast(mDlg->statsView->model()); QModelIndex index = statsModel->addRule( rule ); mDlg->statsView->setCurrentIndex( proxy->mapFromSource( index ) ); settings->statsRules = statsModel->getRules(); mDlg->modifyStats->setEnabled( true ); mDlg->removeStats->setEnabled( true ); updateWarnText( oldRuleCount ); changed( true ); } } void ConfigDialog::modifyStatsClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings || mDlg->statsView->model()->rowCount() < 1 ) return; QModelIndex index = mDlg->statsView->selectionModel()->currentIndex(); if ( !index.isValid() ) return; QSortFilterProxyModel* proxy = static_cast(mDlg->statsView->model()); index = proxy->mapToSource( index ); StatsRule s = statsModel->item( index.row(), 0 )->data( Qt::UserRole ).value(); StatsConfig dlg( settings, mCalendar, s, false ); if ( dlg.exec() ) { s = dlg.settings(); statsModel->modifyRule( index, s ); settings->statsRules = statsModel->getRules(); changed( true ); } } void ConfigDialog::removeStatsClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings || mDlg->statsView->model()->rowCount() < 1 ) return; QModelIndex index = mDlg->statsView->selectionModel()->currentIndex(); if ( !index.isValid() ) return; QSortFilterProxyModel* proxy = static_cast(mDlg->statsView->model()); index = proxy->mapToSource( index ); statsModel->removeRow( index.row() ); settings->statsRules = statsModel->getRules(); mDlg->modifyStats->setEnabled( statsModel->rowCount() ); mDlg->removeStats->setEnabled( statsModel->rowCount() ); updateWarnText( statsModel->rowCount() ); changed( true ); } void ConfigDialog::addWarnClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; WarnRule warn; WarnConfig dlg( settings, warn, true ); if ( dlg.exec() ) { warn = dlg.settings(); QModelIndex index = warnModel->addWarn( warn ); mDlg->warnView->setCurrentIndex( index ); settings->warnRules = warnModel->getRules(); changed( true ); mDlg->modifyWarn->setEnabled( true ); mDlg->removeWarn->setEnabled( true ); } } void ConfigDialog::modifyWarnClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings || mDlg->warnView->model()->rowCount() < 1 ) return; const QModelIndex index = mDlg->warnView->selectionModel()->currentIndex(); if ( !index.isValid() ) return; WarnRule warn = mDlg->warnView->model()->data( index.sibling( index.row(), 0 ), Qt::UserRole ).value(); WarnConfig dlg( settings, warn, false ); if ( dlg.exec() ) { warn = dlg.settings(); warnModel->modifyWarn( index, warn ); settings->warnRules = warnModel->getRules(); changed( true ); } } void ConfigDialog::removeWarnClicked() { InterfaceSettings* settings = getItemSettings(); if ( !settings || mDlg->warnView->model()->rowCount() < 1 ) return; const QModelIndex index = mDlg->warnView->selectionModel()->currentIndex(); if ( !index.isValid() ) return; warnModel->removeRow( index.row() ); settings->warnRules = warnModel->getRules(); mDlg->modifyWarn->setEnabled( warnModel->rowCount() ); mDlg->removeWarn->setEnabled( warnModel->rowCount() ); changed( true ); } /****************************************** * * * Interface tab - Statistics * * * ******************************************/ void ConfigDialog::checkBoxStatisticsToggled( bool on ) { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; settings->activateStatistics = on; if (!mLock) changed( true ); } /****************************************** * * * Interface tab - Context Menu * * * ******************************************/ void ConfigDialog::buttonAddCommandSelected() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; InterfaceCommand cmd; cmd.runAsRoot = false; cmd.menuText = QString(); cmd.command = QString(); settings->commands.append( cmd ); QTreeWidgetItem* item = new QTreeWidgetItem(); item->setCheckState( 0, Qt::Unchecked ); item->setFlags( item->flags() | Qt::ItemIsEditable ); mDlg->listViewCommands->addTopLevelItem( item ); mDlg->listViewCommands->setCurrentItem( item ); if (!mLock) changed( true ); } void ConfigDialog::buttonRemoveCommandSelected() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; if ( !mDlg->listViewCommands->currentItem() ) return; QTreeWidgetItem *item = mDlg->listViewCommands->currentItem(); int index = mDlg->listViewCommands->indexOfTopLevelItem( item ); mDlg->listViewCommands->takeTopLevelItem( index ); delete item; QList cmds; QTreeWidgetItemIterator i( mDlg->listViewCommands ); while ( QTreeWidgetItem * item = *i ) { InterfaceCommand cmd; cmd.runAsRoot = item->checkState( 0 ); cmd.menuText = item->text( 1 ); cmd.command = item->text( 2 ); cmds.append( cmd ); ++i; } settings->commands = cmds; if (!mLock) changed( true ); } void ConfigDialog::setUpDownButtons( QTreeWidgetItem* item ) { if ( !item ) { mDlg->pushButtonUp->setEnabled( false ); mDlg->pushButtonDown->setEnabled( false ); return; } if (mDlg->listViewCommands->indexOfTopLevelItem( item ) == 0 ) mDlg->pushButtonUp->setEnabled( false ); else mDlg->pushButtonUp->setEnabled( true ); if (mDlg->listViewCommands->indexOfTopLevelItem( item ) == mDlg->listViewCommands->topLevelItemCount() - 1 ) mDlg->pushButtonDown->setEnabled( false ); else mDlg->pushButtonDown->setEnabled( true ); } void ConfigDialog::buttonCommandUpSelected() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; if ( !mDlg->listViewCommands->currentItem() ) return; QTreeWidgetItem* item = mDlg->listViewCommands->currentItem(); int index = mDlg->listViewCommands->indexOfTopLevelItem( item ); if ( index == 0 ) return; mDlg->listViewCommands->takeTopLevelItem( index ); mDlg->listViewCommands->insertTopLevelItem( index - 1, item ); mDlg->listViewCommands->setCurrentItem( item ); setUpDownButtons( item ); QList cmds; QTreeWidgetItemIterator i( mDlg->listViewCommands ); while ( QTreeWidgetItem * item = *i ) { InterfaceCommand cmd; cmd.runAsRoot = item->checkState( 0 ); cmd.menuText = item->text( 1 ); cmd.command = item->text( 2 ); cmds.append( cmd ); ++i; } settings->commands = cmds; if (!mLock) changed( true ); } void ConfigDialog::buttonCommandDownSelected() { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; if ( !mDlg->listViewCommands->currentItem() ) return; QTreeWidgetItem* item = mDlg->listViewCommands->currentItem(); int index = mDlg->listViewCommands->indexOfTopLevelItem( item ); if ( index == mDlg->listViewCommands->topLevelItemCount() - 1 ) return; mDlg->listViewCommands->takeTopLevelItem( index ); mDlg->listViewCommands->insertTopLevelItem( index + 1, item ); mDlg->listViewCommands->setCurrentItem( item ); setUpDownButtons( item ); QList cmds; QTreeWidgetItemIterator i( mDlg->listViewCommands ); while ( QTreeWidgetItem * item = *i ) { InterfaceCommand cmd; cmd.runAsRoot = item->checkState( 0 ); cmd.menuText = item->text( 1 ); cmd.command = item->text( 2 ); cmds.append( cmd ); ++i; } settings->commands = cmds; if (!mLock) changed( true ); } void ConfigDialog::listViewCommandsSelectionChanged( QTreeWidgetItem* item, QTreeWidgetItem* ) { mDlg->pushButtonRemoveCommand->setEnabled( item != NULL ); setUpDownButtons( item ); } void ConfigDialog::listViewCommandsChanged( QTreeWidgetItem* item, int column ) { InterfaceSettings* settings = getItemSettings(); if ( !settings ) return; int row = mDlg->listViewCommands->indexOfTopLevelItem( item ); InterfaceCommand& cmd = settings->commands[row]; switch ( column ) { case 0: cmd.runAsRoot = item->checkState( 0 ); break; case 1: cmd.menuText = item->text( 1 ); break; case 2: cmd.command = item->text( 2 ); } if (!mLock) changed( true ); } /****************************************** * * * ToolTip tab * * * ******************************************/ void ConfigDialog::setupToolTipMap() { // Cannot make this data static as the i18n macro doesn't seem // to work when called to early i.e. before setting the catalogue. mToolTips.insert( INTERFACE, i18n( "Interface" ) ); mToolTips.insert( STATUS, i18n( "Status" ) ); mToolTips.insert( UPTIME, i18n( "Connection Time" ) ); mToolTips.insert( IP_ADDRESS, i18n( "IP Address" ) ); mToolTips.insert( SCOPE, i18n( "Scope & Flags" ) ); mToolTips.insert( HW_ADDRESS, i18n( "MAC Address" ) ); mToolTips.insert( BCAST_ADDRESS, i18n( "Broadcast Address" ) ); mToolTips.insert( GATEWAY, i18n( "Default Gateway" ) ); mToolTips.insert( PTP_ADDRESS, i18n( "PtP Address" ) ); mToolTips.insert( RX_PACKETS, i18n( "Packets Received" ) ); mToolTips.insert( TX_PACKETS, i18n( "Packets Sent" ) ); mToolTips.insert( RX_BYTES, i18n( "Bytes Received" ) ); mToolTips.insert( TX_BYTES, i18n( "Bytes Sent" ) ); mToolTips.insert( DOWNLOAD_SPEED, i18n( "Download Speed" ) ); mToolTips.insert( UPLOAD_SPEED, i18n( "Upload Speed" ) ); mToolTips.insert( ESSID, i18n( "ESSID" ) ); mToolTips.insert( MODE, i18n( "Mode" ) ); mToolTips.insert( FREQUENCY, i18n( "Frequency" ) ); mToolTips.insert( BIT_RATE, i18n( "Bit Rate" ) ); mToolTips.insert( ACCESS_POINT, i18n( "Access Point" ) ); mToolTips.insert( LINK_QUALITY, i18n( "Link Quality" ) ); #ifndef __linux__ mToolTips.insert( NICK_NAME, i18n( "Nickname" ) ); #endif mToolTips.insert( ENCRYPTION, i18n( "Encryption" ) ); } void ConfigDialog::setupToolTipTab() { mDlg->listBoxDisplay->clear(); mDlg->listBoxAvailable->clear(); foreach ( QString tip, mToolTips ) { if ( mToolTipContent & mToolTips.key( tip ) ) mDlg->listBoxDisplay->addItem( tip ); else mDlg->listBoxAvailable->addItem( tip ); } if ( mDlg->listBoxDisplay->count() > 0 ) mDlg->listBoxDisplay->item( 0 )->setSelected( true ); if ( mDlg->listBoxAvailable->count() > 0 ) mDlg->listBoxAvailable->item( 0 )->setSelected( true ); mDlg->pushButtonRemoveToolTip->setEnabled( (mDlg->listBoxDisplay->count() > 0) ); mDlg->pushButtonAddToolTip->setEnabled( (mDlg->listBoxAvailable->count() > 0) ); } void ConfigDialog::moveTips( QListWidget *from, QListWidget* to ) { QList selectedItems = from->selectedItems(); foreach ( QListWidgetItem *selected, selectedItems ) { quint32 key = mToolTips.key( selected->text() ); int newIndex = -1; int count = to->count(); for ( int i = 0; i < count; i++ ) { QListWidgetItem *item = to->item( i ); if ( mToolTips.key( item->text() ) > key ) { newIndex = i; break; } } if ( newIndex < 0 ) newIndex = count; selected->setSelected( false ); from->takeItem( from->row( selected ) ); to->insertItem( newIndex, selected ); mDlg->pushButtonAddToolTip->setEnabled( (mDlg->listBoxAvailable->count() > 0) ); mDlg->pushButtonRemoveToolTip->setEnabled( (mDlg->listBoxDisplay->count() > 0) ); changed( true ); } mToolTipContent = 0; for ( int i = 0; i < mDlg->listBoxDisplay->count(); i++ ) mToolTipContent += mToolTips.key( mDlg->listBoxDisplay->item( i )->text() ); } void ConfigDialog::buttonAddToolTipSelected() { // Support extended selection if ( mDlg->listBoxAvailable->count() == 0 ) return; moveTips( mDlg->listBoxAvailable, mDlg->listBoxDisplay ); } void ConfigDialog::buttonRemoveToolTipSelected() { // Support extended selection if ( mDlg->listBoxDisplay->count() == 0 ) return; moveTips( mDlg->listBoxDisplay, mDlg->listBoxAvailable ); } /****************************************** * * * General tab * * * ******************************************/ void ConfigDialog::buttonNotificationsSelected() { KNotifyConfigWidget::configure( this, QLatin1String("knemo") ); } #include "configdialog.moc" diff --git a/src/kcm/configdlg.ui b/src/kcm/configdlg.ui index 55edc51..398af6f 100644 --- a/src/kcm/configdlg.ui +++ b/src/kcm/configdlg.ui @@ -1,1098 +1,1074 @@ ConfigDlg 0 0 0 0 Start KNemo automatically when you login 0 Interfaces This lists the interfaces that you wish to monitor. Please use the names understood by <i>ifconfig</i> ('eth0', 'wlan0', 'ppp0', etc.), or click "Add all interfaces" below to include all of the interfaces currently found on your system. true Add a new interface Add all interfaces false Delete the selected interface Qt::Vertical 0 0 false Alias: false false You can enter an alias for the interface. KNemo will use it to differentiate interfaces when it displays tooltips, dialogs, etc. false 0 0 0 Icon Appearance Icon hiding: Do not hide Hide when disconnected Hide when unavailable Icon theme: false Unavailable false Disconnected false Connected false Incoming traffic false Outgoing traffic false Incoming and outgoing traffic false Theme Settings Incoming traffic: Outgoing traffic: Disconnected: Unavailable: false Icon Font: Qt::Horizontal QSizePolicy::Expanding 0 0 Advanced... Qt::Vertical 0 0 Statistics Activate statistics false Custom Billing Periods Log traffic statistics according to customized rules. When a custom billing period ends, it will automatically start a new billing period with the same rules. false false Add a new entry Add... Modify... Remove the selected entry Remove Qt::Vertical QSizePolicy::Expanding 0 0 false Traffic Notifications When interface traffic exceeds the limit set by a rule, KNemo will emit a notification. The notification will appear once per period. false false Add a new entry Add... Modify... Remove the selected entry Remove Qt::Vertical QSizePolicy::Expanding 0 0 Qt::Vertical 0 0 Context Menu In this area you can add the custom entries for your context menu: <ol><li>push the <b>Add</b> button to add a new entry in the list;</li><li>edit the entry by double clicking in the <b>Menu text</b> and <b>Command</b> columns.</li></ol>If you need to execute the command as root user check the corresponding <b>Root</b> check box. false false 3 Root Menu text Command Add a new entry Remove the selected entry Qt::Vertical QSizePolicy::Expanding 0 0 Move the selected entry up Move the selected entry down ToolTip 0 0 Available: false QAbstractItemView::ExtendedSelection Qt::Vertical QSizePolicy::Expanding 0 0 Qt::Horizontal QSizePolicy::Fixed 5 20 Add the selected entry to the tray icon's tooltip Remove the selected entry from the tray icon's tooltip Qt::Horizontal QSizePolicy::Fixed 5 20 Qt::Vertical QSizePolicy::Expanding 0 0 0 0 Active: false QAbstractItemView::ExtendedSelection Wireless specific information will only appear in the tooltips of wireless devices true General Notifications Configure Notifications... Update interval Update interface information every false Set how often KNemo polls interfaces for information. A lower value will speed up reaction to changes, but it will also increase CPU load. Qt::Horizontal QSizePolicy::Expanding 0 0 Report traffic rate in bit/s Statistics Autosave interval: false Save interface statistics every <i>n</i> seconds. If 0, KNemo will only save statistics when it closes. At shutdown sec 0 300 60 Qt::Horizontal QSizePolicy::Expanding 0 0 - - - - Statistics directory: - - - false - - - - - - - KNemo will log interface statistics in this directory. - - - Qt::Vertical QSizePolicy::Expanding 0 0 KColorButton QPushButton
kcolorbutton.h
- - KUrlRequester - QFrame -
kurlrequester.h
- 1 -
checkBoxStartKNemo tabWidgetConfiguration listBoxInterfaces pushButtonNew pushButtonAll pushButtonDelete lineEditAlias ifaceTab comboHiding comboBoxIconTheme colorIncoming colorOutgoing colorDisabled colorUnavailable iconFont advancedButton checkBoxStatistics statsView addStats modifyStats removeStats warnView addWarn modifyWarn removeWarn listViewCommands pushButtonAddCommand pushButtonRemoveCommand pushButtonUp pushButtonDown listBoxAvailable pushButtonAddToolTip pushButtonRemoveToolTip listBoxDisplay pushButtonNotifications comboBoxPoll useBitrate numInputSaveInterval - lineEditStatisticsDir checkBoxStatistics toggled(bool) groupBox setEnabled(bool) 429 148 496 437 checkBoxStatistics toggled(bool) groupBox_2 setEnabled(bool) 431 146 426 162
diff --git a/src/knemod/interfacestatistics.cpp b/src/knemod/interfacestatistics.cpp index d041331..d9bb3a3 100644 --- a/src/knemod/interfacestatistics.cpp +++ b/src/knemod/interfacestatistics.cpp @@ -1,1122 +1,1118 @@ /* This file is part of KNemo Copyright (C) 2005, 2006 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp KNemo is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KNemo 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include "global.h" #include "interface.h" #include "interfacestatistics.h" #include "statisticsmodel.h" #include "syncstats/statsfactory.h" #include "storage/sqlstorage.h" #include "storage/xmlstorage.h" static bool statsLessThan( const StatsRule& s1, const StatsRule& s2 ) { if ( s1.startDate < s2.startDate ) return true; else return false; } InterfaceStatistics::InterfaceStatistics( Interface* interface ) : QObject(), mInterface( interface ), mSaveTimer( new QTimer() ), mWarnTimer( new QTimer() ), mEntryTimer( new QTimer() ), mTrafficChanged( false ) { StatisticsModel * s = new StatisticsModel( KNemoStats::Hour, this ); mModels.insert( KNemoStats::Hour, s ); s = new StatisticsModel( KNemoStats::Day, this ); mModels.insert( KNemoStats::Day, s ); s = new StatisticsModel( KNemoStats::Week, this ); mModels.insert( KNemoStats::Week, s ); s = new StatisticsModel( KNemoStats::Month, this ); mModels.insert( KNemoStats::Month, s ); s = new StatisticsModel( KNemoStats::Year, this ); mModels.insert( KNemoStats::Year, s ); s = new StatisticsModel( KNemoStats::BillPeriod, this ); mModels.insert( KNemoStats::BillPeriod, s ); s = new StatisticsModel( KNemoStats::HourArchive, this ); mModels.insert( KNemoStats::HourArchive, s ); foreach ( StatisticsModel *s, mModels ) { mStorageData.saveFromId.insert( s->periodType(), 0 ); } connect( mSaveTimer, SIGNAL( timeout() ), this, SLOT( saveStatistics() ) ); connect( mWarnTimer, SIGNAL( timeout() ), this, SLOT( checkWarnings() ) ); connect( mEntryTimer, SIGNAL( timeout() ), this, SLOT( checkValidEntry() ) ); - QUrl dir( generalSettings->statisticsDir ); sql = new SqlStorage( mInterface->ifaceName() ); loadStats(); syncWithExternal( mStorageData.lastSaved ); configChanged(); } InterfaceStatistics::~InterfaceStatistics() { mSaveTimer->stop(); mWarnTimer->stop(); mEntryTimer->stop(); delete mSaveTimer; delete mWarnTimer; delete mEntryTimer; saveStatistics(); delete sql; QSqlDatabase::removeDatabase( mInterface->ifaceName() ); } void InterfaceStatistics::saveStatistics( bool fullSave ) { sql->saveStats( &mStorageData, &mModels, &mStatsRules, fullSave ); } bool InterfaceStatistics::loadStats() { - QUrl dir( generalSettings->statisticsDir ); - if ( !dir.isLocalFile() ) - return 0; bool loaded = false; if ( sql->dbExists() ) { loaded = sql->loadStats( &mStorageData, &mModels, &mStatsRules ); qSort( mStatsRules.begin(), mStatsRules.end(), statsLessThan ); } else { XmlStorage xml; loaded = xml.loadStats( mInterface->ifaceName(), &mStorageData, &mModels ); sql->createDb(); if ( loaded ) { hoursToArchive( QDateTime::currentDateTime() ); checkRebuild( mStorageData.calendar->calendarSystem(), true ); } } if ( !mStorageData.calendar ) { mStorageData.calendar = KCalendarSystem::create( mInterface->settings().calendarSystem ); foreach( StatisticsModel * s, mModels ) { s->setCalendar( mStorageData.calendar ); } } return loaded; } /********************************** * Stats Entry Generators * **********************************/ void InterfaceStatistics::resetWarnings( int modelType ) { for ( int i = 0; i < mInterface->settings().warnRules.count(); ++i ) { if ( modelType == mInterface->settings().warnRules[i].periodUnits ) mInterface->settings().warnRules[i].warnDone = false; } } void InterfaceStatistics::hoursToArchive( const QDateTime &dateTime ) { bool removedRow = false; StatisticsModel* hours = mModels.value( KNemoStats::Hour ); StatisticsModel* hourArchives = mModels.value( KNemoStats::HourArchive ); // Only 24 hours while ( hours->rowCount() ) { if ( hours->dateTime( 0 ) <= dateTime.addDays( -1 ) ) { QList row = hours->takeRow( 0 ); hourArchives->appendRow( row ); hourArchives->setId( mStorageData.nextHourId ); mStorageData.nextHourId++; removedRow = true; } else break; } if ( removedRow ) { for ( int i = 0; i < hours->rowCount(); ++i ) { hours->setId( i, i ); } mStorageData.saveFromId.insert( hours->periodType(), 0 ); mStorageData.saveFromId.insert( hourArchives->periodType(), hourArchives->id( 0 ) ); } } void InterfaceStatistics::genNewHour( const QDateTime &dateTime ) { hoursToArchive( dateTime ); StatisticsModel* hours = mModels.value( KNemoStats::Hour ); if ( hours->dateTime() == dateTime ) return; int ruleIndex = ruleForDate( dateTime.date() ); hours->createEntry( dateTime ); if ( ruleIndex >= 0 && isOffpeak( mStatsRules[ruleIndex], dateTime ) ) { hours->addTrafficType( KNemoStats::OffpeakTraffic ); } resetWarnings( hours->periodType() ); } bool InterfaceStatistics::genNewCalendarType( const QDate &date, const KNemoStats::PeriodUnits stype ) { if ( stype < KNemoStats::Day || stype > KNemoStats::Year ) return false; StatisticsModel * model = mModels.value( stype ); if ( model->rowCount() && model->date().addDays( model->days() ) > date ) return false; QDate newDate; int dayOf; int weekStartDay = mStorageData.calendar->weekStartDay(); switch ( stype ) { case KNemoStats::Day: newDate = date; break; case KNemoStats::Week: dayOf = mStorageData.calendar->dayOfWeek( date ); if ( dayOf >= weekStartDay ) newDate = date.addDays( weekStartDay - dayOf ); else newDate = date.addDays( weekStartDay - mStorageData.calendar->daysInWeek( date ) - dayOf ); break; case KNemoStats::Month: dayOf = mStorageData.calendar->day( date ); newDate = date.addDays( 1 - dayOf ); break; case KNemoStats::Year: dayOf = mStorageData.calendar->dayOfYear( date ); newDate = date.addDays( 1 - dayOf ); break; default: return false; } mModels.value( stype )->createEntry( QDateTime( newDate, QTime() ) ); resetWarnings( stype ); return true; } // Return true if at least one daily statistic entry is in a span of days bool InterfaceStatistics::daysInSpan( const QDate& date, int days ) { StatisticsModel *model = mModels.value( KNemoStats::Day ); if ( !model->rowCount() ) return false; QDate nextRuleStart = date.addDays( days ); for ( int i = model->rowCount() - 1; i >= 0; --i ) { // No others will be valid after this; stop early if ( model->date( i ) < date ) return false; if ( model->date( i ) < nextRuleStart && model->date( i ) >= date ) return true; } return false; } QDate InterfaceStatistics::nextBillPeriodStart( const StatsRule &rules, const QDate &date ) { QDate nextDate; QDate refDay; int modelType = rules.periodUnits; switch ( modelType ) { case KNemoStats::Day: nextDate = date.addDays( rules.periodCount ); break; case KNemoStats::Week: nextDate = date; for ( int i = 0; i < rules.periodCount; ++i ) nextDate = nextDate.addDays( mStorageData.calendar->daysInWeek( nextDate ) ); break; default:// KNemoStats::Month: nextDate = mStorageData.calendar->addMonths( date, rules.periodCount ); // Example: one month starting Jan 31 = Jan 31 -> Mar 1 // This seems the most common way to handle late start dates if ( mStorageData.calendar->day( nextDate ) < mStorageData.calendar->day( date ) ) nextDate = nextDate.addDays( 1 ); break; } return nextDate; } void InterfaceStatistics::genNewBillPeriod( const QDate &date ) { int ruleIndex = ruleForDate( date ); if ( ruleIndex < 0 ) return; StatisticsModel * billing = mModels.value( KNemoStats::BillPeriod ); QDate nextRuleStart; if ( mStatsRules.count() > ruleIndex+1 ) nextRuleStart = mStatsRules.at( ruleIndex+1 ).startDate; // Harder to find whether we should skip generating a new billing entry if ( nextRuleStart.isValid() && billing->rowCount() && billing->date().addDays( billing->days() ) >= nextRuleStart ) return; int days; // Given a calendar day and a billing period start date, find a // billing period that the day belongs in. QDate newDate; QDate nextStartDate; if ( !billing->rowCount() || billing->date() < mStatsRules.at( ruleIndex ).startDate ) { nextStartDate = mStatsRules.at( ruleIndex ).startDate; } else { nextStartDate = billing->date(); } do { newDate = nextStartDate; nextStartDate = nextBillPeriodStart( mStatsRules.at( ruleIndex ), newDate ); days = newDate.daysTo( nextStartDate ); } while ( nextStartDate <= date || !daysInSpan( newDate, days ) ); // Truncate a billing period if necessary if ( nextRuleStart.isValid() && nextRuleStart < nextStartDate ) days = newDate.daysTo( nextRuleStart ); if ( billing->rowCount() && newDate == billing->date() ) return; billing->createEntry( QDateTime( newDate, QTime() ), billing->rowCount(), days ); resetWarnings( KNemoStats::BillPeriod ); } // END STATS ENTRY GENERATORS void InterfaceStatistics::configChanged() { mSaveTimer->stop(); mWarnTimer->stop(); KLocale::CalendarSystem origCalendarSystem = KLocale::QDateCalendar; if ( mStorageData.calendar ) origCalendarSystem = mStorageData.calendar->calendarSystem(); if ( mInterface->settings().calendarSystem != origCalendarSystem ) { mStorageData.calendar = KCalendarSystem::create( mInterface->settings().calendarSystem ); foreach( StatisticsModel * s, mModels ) { s->setCalendar( mStorageData.calendar ); } if ( mStorageData.calendar ) { StatisticsModel *hours = mModels.value( KNemoStats::Hour ); StatisticsModel *days = mModels.value( KNemoStats::Day ); for ( int i = 0; i < days->rowCount(); ++i ) { days->updateDateText( i ); } for ( int i = 0; i < hours->rowCount(); ++i ) { hours->updateDateText( i ); } } } checkRebuild( origCalendarSystem ); if ( generalSettings->saveInterval > 0 ) { mSaveTimer->setInterval( generalSettings->saveInterval * 1000 ); mSaveTimer->start(); } foreach ( StatisticsModel * s, mModels ) { resetWarnings( s->periodType() ); } checkValidEntry(); mWarnTimer->setInterval( 2000 ); mWarnTimer->start(); } int InterfaceStatistics::ruleForDate( const QDate &date ) { for( int i = mStatsRules.count() - 1; i >= 0; --i ) { if ( date >= mStatsRules[i].startDate ) return i; } return -1; } void InterfaceStatistics::syncWithExternal( uint updated ) { ExternalStats *v = StatsFactory::stats( mInterface, mStorageData.calendar ); if ( !v ) return; v->importIfaceStats(); const StatisticsModel *syncDays = v->days(); const StatisticsModel *syncHours = v->hours(); StatisticsModel *days = mModels.value( KNemoStats::Day ); StatisticsModel *hours = mModels.value( KNemoStats::Hour ); QDateTime curDateTime = QDateTime( QDate::currentDate(), QTime( QDateTime::currentDateTime().time().hour(), 0 ) ); for ( int i = 0; i < syncHours->rowCount(); ++i ) { QDateTime syncDateTime = syncHours->dateTime( i ); if ( hours->rowCount() && hours->dateTime() > syncDateTime ) continue; if ( !hours->rowCount() || hours->dateTime() < syncDateTime ) genNewHour( syncDateTime ); foreach ( KNemoStats::TrafficType t, hours->trafficTypes() ) { hours->addRxBytes( syncHours->rxBytes( i ), t ); hours->addTxBytes( syncHours->txBytes( i ), t ); } } for ( int i = 0; i < syncDays->rowCount(); ++i ) { QDate syncDate = syncDays->date( i ); if ( days->rowCount() && days->date() > syncDate ) continue; if ( !days->rowCount() || days->date() < syncDate ) { genNewCalendarType( syncDate, KNemoStats::Day ); genNewCalendarType( syncDate, KNemoStats::Week ); genNewCalendarType( syncDate, KNemoStats::Month ); genNewCalendarType( syncDate, KNemoStats::Year ); genNewBillPeriod( syncDate ); } foreach( StatisticsModel * s, mModels ) { if ( s->periodType() == KNemoStats::Hour || s->periodType() == KNemoStats::HourArchive ) continue; s->addRxBytes( v->addBytes( s->rxBytes(), syncDays->rxBytes( i ) ) ); s->addTxBytes( v->addBytes( s->txBytes(), syncDays->txBytes( i ) ) ); for ( int j = hours->rowCount() - 1; j >= 0; --j ) { if ( hours->date( j ) == syncDate ) { foreach( KNemoStats::TrafficType t, hours->trafficTypes( j ) ) { if ( t == KNemoStats::AllTraffic ) continue; s->addRxBytes( hours->rxBytes( j, t ), t ); s->addTxBytes( hours->txBytes( j, t ), t ); } } else if ( hours->date( j ) < syncDate ) break; } } } StatsPair lag = v->addLagged( updated, days ); if ( lag.rxBytes > 0 || lag.txBytes > 0 ) { if ( lag.rxBytes || lag.txBytes ) { genNewHour( curDateTime ); genNewCalendarType( curDateTime.date(), KNemoStats::Day ); genNewCalendarType( curDateTime.date(), KNemoStats::Week ); genNewCalendarType( curDateTime.date(), KNemoStats::Month ); genNewCalendarType( curDateTime.date(), KNemoStats::Year ); genNewBillPeriod( curDateTime.date() ); foreach ( StatisticsModel * s, mModels ) { if ( s->periodType() == KNemoStats::HourArchive ) continue; foreach ( KNemoStats::TrafficType t, hours->trafficTypes() ) { s->addRxBytes( lag.rxBytes, t ); s->addTxBytes( lag.txBytes, t ); } } } } delete v; } bool InterfaceStatistics::isOffpeak( const StatsRule &rules, const QDateTime &curDT ) { if ( !rules.logOffpeak ) return false; bool isOffpeak = false; QTime curHour = QTime( curDT.time().hour(), 0 ); // This block just tests weekly hours if ( rules.offpeakStartTime < rules.offpeakEndTime && curHour >= rules.offpeakStartTime && curHour < rules.offpeakEndTime ) { isOffpeak = true; } else if ( rules.offpeakStartTime > rules.offpeakEndTime && ( curHour >= rules.offpeakStartTime || curHour < rules.offpeakEndTime ) ) { isOffpeak = true; } if ( rules.weekendIsOffpeak ) { int dow = mStorageData.calendar->dayOfWeek( curDT.date() ); if ( rules.weekendDayStart <= rules.weekendDayEnd && rules.weekendDayStart <= dow ) { QDateTime dayBegin = curDT.addDays( dow - rules.weekendDayStart ); dayBegin = QDateTime( dayBegin.date(), rules.weekendTimeStart ); QDateTime end = curDT.addDays( rules.weekendDayEnd - dow ); end = QDateTime( end.date(), rules.weekendTimeEnd ); if ( dayBegin <= curDT && curDT < end ) isOffpeak = true; } else if ( rules.weekendDayStart > rules.weekendDayEnd && ( dow >= rules.weekendDayStart || dow <= rules.weekendDayEnd ) ) { QDateTime dayBegin = curDT.addDays( rules.weekendDayStart - dow ); dayBegin = QDateTime( dayBegin.date(), rules.weekendTimeStart ); QDateTime end = curDT.addDays( mStorageData.calendar->daysInWeek( curDT.date() ) - dow + rules.weekendDayEnd ); end = QDateTime( end.date(), rules.weekendTimeEnd ); if ( dayBegin <= curDT && curDT < end ) isOffpeak = true; } } return isOffpeak; } /************************************** * Rebuilding Statistics * **************************************/ int InterfaceStatistics::rebuildHours( StatisticsModel *s, const StatsRule &rules, const QDate &start, const QDate &nextRuleStart ) { if ( !s->rowCount() ) return 0; int i = s->rowCount(); while ( i > 0 && s->date( i - 1 ) >= start ) { i--; if ( nextRuleStart.isValid() && s->date( i ) >= nextRuleStart ) continue; s->resetTrafficTypes( i ); if ( isOffpeak( rules, s->dateTime( i ) ) ) { s->setTraffic( i, s->rxBytes( i ), s->txBytes( i ), KNemoStats::OffpeakTraffic ); s->addTrafficType( KNemoStats::OffpeakTraffic, i ); } } if ( mStorageData.saveFromId.value( s->periodType() ) > s->id( i ) ) { mStorageData.saveFromId.insert( s->periodType(), s->id( i ) ); } return i; } int InterfaceStatistics::rebuildDay( int dayIndex, int hourIndex, StatisticsModel *hours ) { QMap > dayTraffic; StatisticsModel *days = mModels.value( KNemoStats::Day ); while ( hourIndex >= 0 && hours->date( hourIndex ) > days->date( dayIndex ).addDays( 1 ) ) { --hourIndex; } while ( hourIndex >= 0 && hours->date( hourIndex ) == days->date( dayIndex ) ) { foreach ( KNemoStats::TrafficType t, hours->trafficTypes( hourIndex ) ) { if ( t == KNemoStats::AllTraffic ) continue; quint64 rx = hours->rxBytes( hourIndex, t ) + dayTraffic.value( t ).first; quint64 tx = hours->txBytes( hourIndex, t ) + dayTraffic.value( t ).second; dayTraffic.insert( t, QPair( rx, tx ) ); } --hourIndex; } foreach (KNemoStats::TrafficType t, dayTraffic.keys() ) { days->setTraffic( dayIndex, dayTraffic.value( t ).first, dayTraffic.value( t ).second, t ); days->addTrafficType( t, dayIndex ); } return hourIndex; } // A rebuild of hours and days never changes the number of entries // We just change what bytes count as off-peak void InterfaceStatistics::rebuildBaseUnits( const StatsRule &rules, const QDate &start, const QDate &nextRuleStart ) { int hIndex = 0; int haIndex = 0; StatisticsModel *hours = mModels.value( KNemoStats::Hour ); StatisticsModel *hourArchives = mModels.value( KNemoStats::HourArchive ); StatisticsModel *days = mModels.value( KNemoStats::Day ); sql->loadHourArchives( hourArchives, start, nextRuleStart ); if ( hourArchives->rowCount() ) mStorageData.saveFromId.insert( hourArchives->periodType(), hourArchives->id( 0 ) ); rebuildHours( hourArchives, rules, start, nextRuleStart ); rebuildHours( hours, rules, start, nextRuleStart ); if ( hours->rowCount() ) hIndex = hours->rowCount() - 1; if ( hourArchives->rowCount() ) haIndex = hourArchives->rowCount() - 1; if ( !days->rowCount() ) return; int dayIndex = days->rowCount(); while ( dayIndex > 0 && days->date( dayIndex - 1 ) >= start ) { dayIndex--; if ( nextRuleStart.isValid() && days->date( dayIndex ) >= nextRuleStart ) continue; days->resetTrafficTypes( dayIndex ); if ( rules.logOffpeak ) { haIndex = rebuildDay( dayIndex, haIndex, hourArchives ); hIndex = rebuildDay( dayIndex, hIndex, hours ); } } if ( mStorageData.saveFromId.value( days->periodType() ) > days->id( dayIndex ) ) { mStorageData.saveFromId.insert( days->periodType(), days->id( dayIndex ) ); } } /** * Given a model with statistics of a certain unit (year, month, week, etc.) * and a requested rebuild date, how far back to we actually need to go * to accuratly rebuild statistics from the daily stats. */ QDate InterfaceStatistics::prepareRebuild( StatisticsModel* statistics, const QDate &startDate ) { QDate newStartDate = startDate; if ( statistics->periodType() <= KNemoStats::Day || statistics->periodType() > KNemoStats::Year ) return newStartDate; for ( int i = 0; i < statistics->rowCount(); ++i ) { int days = statistics->days( i ); QDate nextPeriodStart = statistics->date( i ).addDays( days ); if ( statistics->periodType() == KNemoStats::BillPeriod ) { // Have to check if a billing period's truncation changed int ruleIndex = ruleForDate( statistics->date( i ) ); if ( ruleIndex < 0 ) break; QDate nextFullPeriodStart = nextBillPeriodStart( mStatsRules.at( ruleIndex ), statistics->date( i ) ); if ( nextFullPeriodStart > nextPeriodStart ) { if ( mStatsRules.count() == ruleIndex+1 || mStatsRules.at( ruleIndex + 1 ).startDate != nextPeriodStart ) { // Truncation changed // This will make sure the entry gets rebuilt nextPeriodStart = nextFullPeriodStart; } } } if ( nextPeriodStart > startDate ) { if ( statistics->date( i ) < startDate ) { newStartDate = statistics->date( i ); } if ( statistics->rowCount() && mStorageData.saveFromId.value( statistics->periodType() ) > statistics->id( i ) ) { mStorageData.saveFromId.insert( statistics->periodType(), statistics->id( i ) ); } statistics->removeRows( i, statistics->rowCount() - i ); break; } } return newStartDate; } void InterfaceStatistics::amendStats( int i, const StatisticsModel *source, StatisticsModel* dest ) { foreach ( KNemoStats::TrafficType t, source->trafficTypes( i ) ) { dest->addRxBytes( source->rxBytes( i, t ), t ); dest->addTxBytes( source->txBytes( i, t ), t ); dest->addTrafficType( t ); } } void InterfaceStatistics::rebuildCalendarPeriods( const QDate &requestedStart, bool weekOnly ) { QDate weekStart; QDate monthStart; QDate walkbackDate; QList s; weekStart = prepareRebuild( mModels.value( KNemoStats::Week), requestedStart ); s.append( weekStart ); if ( !weekOnly ) { monthStart = prepareRebuild( mModels.value( KNemoStats::Month), requestedStart ); s.append( monthStart ); } // Now find how far back we'll need to go qSort( s ); walkbackDate = s.first(); StatisticsModel *days = mModels.value( KNemoStats::Day ); for ( int i = 0; i < days->rowCount(); ++i ) { QDate day = days->date( i ); if ( day < walkbackDate ) continue; if ( day >= weekStart ) { genNewCalendarType( day, KNemoStats::Week ); amendStats( i, mModels.value( KNemoStats::Day ), mModels.value( KNemoStats::Week ) ); } if ( !weekOnly && day >= monthStart ) { genNewCalendarType( day, KNemoStats::Month ); amendStats( i, mModels.value( KNemoStats::Day ), mModels.value( KNemoStats::Month ) ); } } if ( weekOnly ) return; // Build years from months...save time QDate yearStart = prepareRebuild( mModels.value( KNemoStats::Year ), requestedStart ); StatisticsModel *months = mModels.value( KNemoStats::Month ); for ( int i = 0; i < months->rowCount(); ++i ) { QDate day = months->date( i ); if ( day < yearStart ) continue; genNewCalendarType( day, KNemoStats::Year ); amendStats( i, mModels.value( KNemoStats::Month ), mModels.value( KNemoStats::Year ) ); } } void InterfaceStatistics::rebuildBillPeriods( const QDate &requestedStart ) { QDate walkbackDate; StatisticsModel *days = mModels.value( KNemoStats::Day ); StatisticsModel *billPeriods = mModels.value( KNemoStats::BillPeriod ); if ( billPeriods->rowCount() ) walkbackDate = prepareRebuild( mModels.value( KNemoStats::BillPeriod), requestedStart ); else walkbackDate = days->date( 0 ); for ( int i = 0; i < days->rowCount(); ++i ) { QDate day = days->date( i ); if ( day >= walkbackDate ) { genNewBillPeriod( day ); amendStats( i, mModels.value( KNemoStats::Day ), mModels.value( KNemoStats::BillPeriod ) ); } } } void InterfaceStatistics::prependStatsRule( QList &rules ) { qSort( rules.begin(), rules.end(), statsLessThan ); StatisticsModel * days = mModels.value( KNemoStats::Day ); if ( rules.count() == 0 || ( days->rowCount() > 0 && rules[0].startDate > days->date( 0 ) ) ) { QDate date; if ( days->rowCount() ) date = days->date( 0 ); else date = QDate::currentDate(); StatsRule s; s.startDate = date.addDays( 1 - mStorageData.calendar->day( date ) ); rules.prepend( s ); } } void InterfaceStatistics::checkRebuild( const KLocale::CalendarSystem oldCalendar, bool force ) { QList newRules = mInterface->settings().statsRules; bool forceWeek = false; if ( oldCalendar != mInterface->settings().calendarSystem ) { StatisticsModel *hours = mModels.value( KNemoStats::Hour ); StatisticsModel *days = mModels.value( KNemoStats::Day ); for ( int i = 0; i < days->rowCount(); ++i ) { days->updateDateText( i ); } for ( int i = 0; i < hours->rowCount(); ++i ) { hours->updateDateText( i ); } force = true; } if ( mModels.value( KNemoStats::Week )->rowCount() ) { QDate testDate = mModels.value( KNemoStats::Week )->date( 0 ); if ( mStorageData.calendar->dayOfWeek( testDate ) != mStorageData.calendar->weekStartDay() ) forceWeek = true; } bool doBilling = newRules.count(); int oldRuleCount = mStatsRules.count(); QDate bpBeginDate; if ( !doBilling ) { mModels.value( KNemoStats::BillPeriod )->clearRows(); mStorageData.saveFromId.insert( KNemoStats::BillPeriod, 0 ); } // This is just a dummy for calculation prependStatsRule( newRules ); prependStatsRule( mStatsRules ); if ( !oldRuleCount && mStatsRules[0] == newRules[0] && newRules.count() > mStatsRules.count() ) bpBeginDate = mModels.value( KNemoStats::Day )->date( 0 ); int j = 0; QDate recalcPos; for ( int i = 0; i < newRules.count(); ++i ) { bool rulesMatch = ( newRules[i] == mStatsRules[j] ); QDate nextRuleStart; if ( !rulesMatch ) { if ( newRules.count() > i + 1 ) nextRuleStart = newRules[i+1].startDate; if ( !recalcPos.isValid() ) recalcPos = newRules[i].startDate; rebuildBaseUnits( newRules[i], newRules[i].startDate, nextRuleStart ); } else { // rules match, now scan forward to see if we need to extend new rule if ( newRules.count() > i + 1 ) { int first = -1; int k; // Here we want to skip over any intermediary old rules that will // get taken care of when we recalculate this section. for ( k = 0; k < mStatsRules.count(); ++k ) { if ( mStatsRules[k].startDate > newRules[i].startDate && mStatsRules[k].startDate < newRules[i+1].startDate ) { if ( first < 0 ) first = k; j = k; if ( !recalcPos.isValid() ) recalcPos = mStatsRules[j].startDate; } } if ( first >= 0 ) { rebuildBaseUnits( newRules[i], mStatsRules[first].startDate, newRules[i+1].startDate ); } } // We're out of new rules but there's more old ones // so rebuild from next old rule's date using final new rule. else if ( mStatsRules.count() > j + 1 ) { if ( !recalcPos.isValid() ) recalcPos = mStatsRules[j+1].startDate; rebuildBaseUnits( newRules[i], recalcPos, nextRuleStart ); } if ( mStatsRules.count() > j + 1 ) ++j; } } /* now do the rest */ mStatsRules = newRules; if ( force ) recalcPos = mModels.value( KNemoStats::Day )->date( 0 ); if ( recalcPos.isValid() ) { rebuildCalendarPeriods( recalcPos ); if ( doBilling ) { rebuildBillPeriods( recalcPos ); } } else if ( forceWeek ) { rebuildCalendarPeriods( mModels.value( KNemoStats::Day )->date( 0 ), true ); } mStatsRules = mInterface->settings().statsRules; if ( mStatsRules.count() ) prependStatsRule( mStatsRules ); if ( recalcPos.isValid() ) { saveStatistics( true ); } mTrafficChanged = true; emit currentEntryChanged(); } // END REBUILDING STATISTICS void InterfaceStatistics::checkValidEntry() { mEntryTimer->stop(); QDateTime curDateTime = QDateTime::currentDateTime(); QDate curDate = curDateTime.date(); StatisticsModel *days = mModels.value( KNemoStats::Day ); StatisticsModel *hours = mModels.value( KNemoStats::Hour ); if ( !hours->rowCount() || hours->dateTime().addSecs( 3600 ) <= curDateTime ) { genNewHour( QDateTime( curDate, QTime( curDateTime.time().hour(), 0 ) ) ); } if ( !days->rowCount() || days->date() < curDate ) { genNewCalendarType( curDate, KNemoStats::Day ); genNewCalendarType( curDate, KNemoStats::Week ); genNewCalendarType( curDate, KNemoStats::Month ); genNewCalendarType( curDate, KNemoStats::Year ); genNewBillPeriod( curDate ); // The fancy short date may need updating for ( int i = 0; i < hours->rowCount(); ++i ) hours->updateDateText( i ); } foreach ( StatisticsModel * s, mModels ) { if ( s->periodType() == KNemoStats::HourArchive || s->periodType() == KNemoStats::Hour ) continue; foreach ( KNemoStats::TrafficType t, hours->trafficTypes() ) { s->addTrafficType( t ); } } QDateTime ndt = curDateTime.addSecs( 3600 - curDateTime.time().minute()*60 - curDateTime.time().second() ); int secs = curDateTime.secsTo( ndt ); mEntryTimer->setInterval( secs * 1000 ); mEntryTimer->start(); } void InterfaceStatistics::checkWarnings() { if ( !mTrafficChanged ) return; mTrafficChanged = false; QList warn = mInterface->settings().warnRules; for ( int wi=0; wi < warn.count(); ++wi ) { if ( warn[wi].warnDone || !warn[wi].threshold > 0.0 ) continue; quint64 total = 0; StatisticsModel *model = 0; model = mModels.value( warn[wi].periodUnits ); if ( !model ) return; int lowerIndex = model->rowCount() - warn[wi].periodCount; for ( int i = model->rowCount() - 1; i >= 0; --i ) { if ( i >= lowerIndex ) { switch ( warn[wi].trafficDirection ) { case KNemoStats::TrafficIn: if ( warn[wi].trafficType == KNemoStats::PeakOffpeak ) total += model->rxBytes( i ); else if ( warn[wi].trafficType == KNemoStats::Offpeak ) total += model->rxBytes( i, KNemoStats::OffpeakTraffic ); else total += model->rxBytes( i ) - model->rxBytes( i, KNemoStats::OffpeakTraffic ); break; case KNemoStats::TrafficOut: if ( warn[wi].trafficType == KNemoStats::PeakOffpeak ) total += model->txBytes( i ); else if ( warn[wi].trafficType == KNemoStats::Offpeak ) total += model->txBytes( i, KNemoStats::OffpeakTraffic ); else total += model->txBytes( i ) - model->txBytes( i, KNemoStats::OffpeakTraffic ); break; default: if ( warn[wi].trafficType == KNemoStats::PeakOffpeak ) total += model->totalBytes( i ); else if ( warn[wi].trafficType == KNemoStats::Offpeak ) total += model->totalBytes( i, KNemoStats::OffpeakTraffic ); else total += model->totalBytes( i ) - model->totalBytes( i, KNemoStats::OffpeakTraffic ); } } else break; } int warnMult = pow( 1024, warn[wi].trafficUnits ); quint64 thresholdBytes = warn[wi].threshold * warnMult; if ( total > thresholdBytes ) { emit warnTraffic( warn[wi].customText, thresholdBytes, total ); mInterface->settings().warnRules[wi].warnDone = true; } } } /****************************** * Public Interface * ******************************/ void InterfaceStatistics::clearStatistics() { foreach( StatisticsModel * s, mModels ) s->clearRows(); mStorageData.nextHourId = 0; foreach ( StatisticsModel *s, mModels ) { mStorageData.saveFromId.insert( s->periodType(), 0 ); } sql->clearStats( &mStorageData ); checkValidEntry(); mTrafficChanged = true; emit currentEntryChanged(); } void InterfaceStatistics::addRxBytes( unsigned long bytes ) { if ( bytes == 0 ) return; foreach( StatisticsModel * s, mModels ) { if ( s->periodType() == KNemoStats::HourArchive ) continue; foreach ( KNemoStats::TrafficType t, mModels.value( KNemoStats::Hour )->trafficTypes() ) { s->addRxBytes( bytes, t ); } } mTrafficChanged = true; emit currentEntryChanged(); } void InterfaceStatistics::addTxBytes( unsigned long bytes ) { if ( bytes == 0 ) return; foreach( StatisticsModel * s, mModels ) { if ( s->periodType() == KNemoStats::HourArchive ) continue; foreach ( KNemoStats::TrafficType t, mModels.value( KNemoStats::Hour )->trafficTypes() ) { s->addTxBytes( bytes, t ); } } mTrafficChanged = true; emit currentEntryChanged(); } #include "moc_interfacestatistics.cpp" diff --git a/src/knemod/knemodaemon.cpp b/src/knemod/knemodaemon.cpp index b45920b..ecbfcf1 100644 --- a/src/knemod/knemodaemon.cpp +++ b/src/knemod/knemodaemon.cpp @@ -1,215 +1,215 @@ /* This file is part of KNemo Copyright (C) 2004, 2006 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp KNemo is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KNemo 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include "global.h" #include "knemodaemon.h" #include "interface.h" #include "backends/backendfactory.h" #include "utils.h" QString KNemoDaemon::sSelectedInterface = QString::null; BackendBase *backend = NULL; GeneralSettings *generalSettings = NULL; KNemoDaemon::KNemoDaemon() : QObject(), mConfig( KSharedConfig::openConfig() ), mHaveInterfaces( false ) { generalSettings = new GeneralSettings(); backend = BackendFactory::backend(); QDBusConnection::sessionBus().registerObject(QLatin1String("/knemo"), this, QDBusConnection::ExportScriptableSlots); mPollTimer = new QTimer(); connect( mPollTimer, SIGNAL( timeout() ), this, SLOT( updateInterfaces() ) ); KActionCollection* ac = new KActionCollection( this ); QAction* action = new QAction( i18n( "Toggle Traffic Plotters" ), this ); ac->addAction( QLatin1String("toggleTrafficPlotters"), action ); connect( action, SIGNAL( triggered() ), SLOT( togglePlotters() ) ); KGlobalAccel::setGlobalShortcut( action, QKeySequence() ); readConfig(); } KNemoDaemon::~KNemoDaemon() { mPollTimer->stop(); delete mPollTimer; foreach ( QString key, mInterfaceHash.keys() ) { Interface *interface = mInterfaceHash.take( key ); delete interface; } delete generalSettings; } void KNemoDaemon::readConfig() { mPollTimer->stop(); KConfig *config = mConfig.data(); // For when reparseConfiguration() is called config->reparseConfiguration(); // General GeneralSettings g; KConfigGroup generalGroup( config, confg_general ); generalSettings->pollInterval = clamp(generalGroup.readEntry( conf_pollInterval, g.pollInterval ), 0.1, 2.0 ); generalSettings->pollInterval = validatePoll( generalSettings->pollInterval ); generalSettings->useBitrate = generalGroup.readEntry( conf_useBitrate, g.useBitrate ); generalSettings->saveInterval = clamp(generalGroup.readEntry( conf_saveInterval, g.saveInterval ), 0, 300 ); - generalSettings->statisticsDir = generalGroup.readEntry( conf_statisticsDir, g.statisticsDir ); + generalSettings->statisticsDir = g.statisticsDir; generalSettings->toolTipContent = generalGroup.readEntry( conf_toolTipContent, g.toolTipContent ); // If we already have an Interfaces key--even if its empty--then we // shouldn't try to set up a default interface if ( generalGroup.hasKey( conf_interfaces ) ) mHaveInterfaces = true; QStringList interfaceList = generalGroup.readEntry( conf_interfaces, QStringList() ); // Remove interfaces that are no longer monitored foreach ( QString key, mInterfaceHash.keys() ) { if ( !interfaceList.contains( key ) ) { Interface *interface = mInterfaceHash.take( key ); delete interface; backend->removeIface( key ); // If knemo is running while config removes an interface to monitor, // it will keep the interface and plotter groups. Delete them here. KConfigGroup interfaceGroup( config, QString( confg_interface + key ) ); KConfigGroup plotterGroup( config, QString( confg_plotter + key ) ); interfaceGroup.deleteGroup(); plotterGroup.deleteGroup(); config->sync(); } } if ( !mHaveInterfaces ) { QString ifaceName = backend->defaultRouteIface( AF_INET ); if ( ifaceName.isEmpty() ) ifaceName = backend->defaultRouteIface( AF_INET6 ); if ( !ifaceName.isEmpty() ) { interfaceList << ifaceName; mHaveInterfaces = true; } } // Add/update those that do need to be monitored QStringList newIfaces; foreach ( QString key, interfaceList ) { if ( !mInterfaceHash.contains( key ) ) { const BackendData * data = backend->addIface( key ); Interface *iface = new Interface( key, data ); mInterfaceHash.insert( key, iface ); newIfaces << key; } } // Now (re)config interfaces, but new interfaces need extra work so // they don't show bogus icon traffic states on startup. updateInterfaces(); foreach( QString key, interfaceList ) { Interface *iface = mInterfaceHash.value( key ); iface->configChanged(); if ( newIfaces.contains( key ) ) { backend->updatePackets( key ); iface->processUpdate(); connect( backend, SIGNAL( updateComplete() ), iface, SLOT( processUpdate() ) ); } } bool statsActivated = false; foreach ( Interface *iface, mInterfaceHash ) { if ( iface->settings().activateStatistics ) statsActivated = true; } if ( statsActivated ) { QStringList drivers = QSqlDatabase::drivers(); if ( !drivers.contains( QLatin1String("QSQLITE") ) ) { KMessageBox::sorry( 0, i18n( "The Qt4 SQLite database plugin is not available.\n" "Please install it to store traffic statistics." ) ); } } mPollTimer->start( generalSettings->pollInterval * 1000 ); } void KNemoDaemon::reparseConfiguration() { readConfig(); } QString KNemoDaemon::getSelectedInterface() { // Reset the variable to avoid preselecting an interface when // the user opens the control center module from the control // center afterwards. QString tmp = sSelectedInterface; sSelectedInterface = QString::null; return tmp; } void KNemoDaemon::updateInterfaces() { backend->update(); } void KNemoDaemon::togglePlotters() { bool showPlotters = false; foreach ( QString key, mInterfaceHash.keys() ) { // If only some of the plotters are visible, show them all if ( !mInterfaceHash.value( key )->plotterVisible() ) showPlotters = true; } foreach ( QString key, mInterfaceHash.keys() ) { mInterfaceHash.value( key )->toggleSignalPlotter( showPlotters ); } } #include "moc_knemodaemon.cpp" diff --git a/src/knemod/storage/sqlstorage.cpp b/src/knemod/storage/sqlstorage.cpp index 9f68a54..57804d3 100644 --- a/src/knemod/storage/sqlstorage.cpp +++ b/src/knemod/storage/sqlstorage.cpp @@ -1,573 +1,575 @@ /* This file is part of KNemo Copyright (C) 2010 John Stamp KNemo is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KNemo 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "global.h" #include "statisticsmodel.h" #include "sqlstorage.h" #include "commonstorage.h" #include #include #include #include #include #include static const QString time_format( QLatin1String("hh:mm:ss") ); static const int current_db_version = 2; SqlStorage::SqlStorage( QString ifaceName ) : mValidDbVer( true ) , mIfaceName( ifaceName ) { - QUrl dir( generalSettings->statisticsDir ); - mDbPath = QString::fromLatin1( "%1%2%3.db" ).arg( dir.path() ).arg( statistics_prefix ).arg( mIfaceName ); + if ( !generalSettings->statisticsDir.exists() ) + QDir().mkpath( generalSettings->statisticsDir.absolutePath() ); + + mDbPath = generalSettings->statisticsDir.absoluteFilePath( statistics_prefix + mIfaceName + QLatin1String(".db") ); QStringList drivers = QSqlDatabase::drivers(); if ( drivers.contains( QLatin1String("QSQLITE") ) ) db = QSqlDatabase::addDatabase( QLatin1String("QSQLITE"), mIfaceName ); mTypeMap.insert( KNemoStats::AllTraffic, QLatin1String("") ); mTypeMap.insert( KNemoStats::OffpeakTraffic, QLatin1String("_offpeak") ); if ( dbExists() && open() ) { // KNemo 0.7.4 didn't create tables on a new db. This lets us fix it // without forcing the user to intervene. if ( db.tables().isEmpty() ) createDb(); else migrateDb(); } } SqlStorage::~SqlStorage() { db.close(); } bool SqlStorage::dbExists() { QFile dbfile( mDbPath ); return dbfile.exists(); } bool SqlStorage::createDb() { bool ok = false; if ( !open() ) return ok; QSqlDatabase::database( mIfaceName ).transaction(); QSqlQuery qry( db ); QString qryStr = QLatin1String("CREATE TABLE IF NOT EXISTS general (id INTEGER PRIMARY KEY, version INTEGER,") + QLatin1String(" last_saved BIGINT, calendar TEXT, next_hour_id INTEGER );"); qry.exec( qryStr ); qryStr = QLatin1String("CREATE TABLE IF NOT EXISTS stats_rules (id INTEGER PRIMARY KEY, start_date DATETIME,") + QLatin1String(" period_units INTEGER, period_count INTEGER );"); qry.exec( qryStr ); qryStr = QLatin1String("CREATE TABLE IF NOT EXISTS stats_rules_offpeak (id INTEGER PRIMARY KEY,") + QLatin1String(" offpeak_start_time TEXT, offpeak_end_time TEXT,") + QLatin1String(" weekend_is_offpeak BOOLEAN, weekend_start_time TEXT, weekend_end_time TEXT,") + QLatin1String(" weekend_start_day INTEGER, weekend_end_day INTEGER );"); qry.exec( qryStr ); for ( int i = KNemoStats::Hour; i <= KNemoStats::HourArchive; ++i ) { foreach ( KNemoStats::TrafficType j, mTypeMap.keys() ) { QString dateTimeStr; qryStr = QLatin1String("CREATE TABLE IF NOT EXISTS %1s%2 (id INTEGER PRIMARY KEY,%3") + QLatin1String(" rx BIGINT, tx BIGINT );"); if ( j == KNemoStats::AllTraffic ) { dateTimeStr = QLatin1String(" datetime DATETIME,"); if ( i == KNemoStats::BillPeriod ) dateTimeStr += QLatin1String(" days INTEGER,"); } qryStr = qryStr.arg( periods.at( i ) ).arg( mTypeMap.value( j ) ).arg( dateTimeStr ); qry.exec( qryStr ); } } ok = QSqlDatabase::database( mIfaceName ).commit(); db.close(); return ok; } bool SqlStorage::loadHourArchives( StatisticsModel *hourArchive, const QDate &startDate, const QDate &nextStartDate ) { bool ok = false; if ( !open() ) return ok; QDateTime startDateTime = QDateTime( startDate, QTime() ); QDateTime nextStartDateTime = QDateTime( nextStartDate, QTime() ); QSqlDatabase::database( mIfaceName ).transaction(); QSqlQuery qry( db ); QString searchCol; QString startVal; QString endVal; foreach ( KNemoStats::TrafficType trafficType, mTypeMap.keys() ) { if ( trafficType == KNemoStats::AllTraffic ) { searchCol = QLatin1String("datetime"); startVal = startDateTime.toString( Qt::ISODate ); endVal = nextStartDateTime.toString( Qt::ISODate ); } else { searchCol = QLatin1String("id"); startVal = QString::number( hourArchive->id( 0 ) ); endVal = QString::number( hourArchive->id()+1 ); } QString qryStr = QLatin1String("SELECT * FROM %1s%2 WHERE %3 >= '%4'"); if ( nextStartDate.isValid() ) { qryStr += QLatin1String(" AND datetime < '%5'"); qryStr = qryStr.arg( periods.at( KNemoStats::HourArchive ) ) .arg( mTypeMap.value( trafficType ) ) .arg( searchCol ) .arg( startVal ) .arg( endVal ); } else { qryStr = qryStr.arg( periods.at( KNemoStats::HourArchive ) ) .arg( mTypeMap.value( trafficType ) ) .arg( searchCol ) .arg( startVal ); } qryStr += QLatin1String(" ORDER BY id;"); qry.exec( qryStr ); int cId = qry.record().indexOf( QLatin1String("id") ); int cRx = qry.record().indexOf( QLatin1String("rx") ); int cTx = qry.record().indexOf( QLatin1String("tx") ); int cDt = 0; if ( trafficType == KNemoStats::AllTraffic ) cDt = qry.record().indexOf( QLatin1String("datetime") ); while ( qry.next() ) { int id = qry.value( cId ).toInt(); if ( trafficType == KNemoStats::AllTraffic ) { hourArchive->createEntry( QDateTime::fromString( qry.value( cDt ).toString(), Qt::ISODate ), id ); } hourArchive->setTraffic( hourArchive->indexOfId( id ), qry.value( cRx ).toULongLong(), qry.value( cTx ).toULongLong(), trafficType ); hourArchive->addTrafficType( trafficType, hourArchive->indexOfId( id ) ); } } ok = QSqlDatabase::database( mIfaceName ).commit(); db.close(); return ok; } bool SqlStorage::migrateDb() { bool ok = false; if ( !open() ) return ok; QSqlDatabase::database( mIfaceName ).transaction(); QSqlQuery qry( db ); qry.exec( QLatin1String("SELECT * FROM general;") ); if ( qry.next() ) { int dbVersion = qry.value( qry.record().indexOf( QLatin1String("version") ) ).toInt(); if ( dbVersion > current_db_version ) { mValidDbVer = false; QSqlDatabase::database( mIfaceName ).commit(); db.close(); KMessageBox::error( NULL, i18n( "The statistics database for interface \"%1\" is incompatible with this version of KNemo.\n\nPlease upgrade to a more recent KNemo release.", mIfaceName ) ); return false; } if ( dbVersion < 2 ) { int lastSaved = qry.value( qry.record().indexOf( QLatin1String("last_saved") ) ).toInt(); int nextHourId = qry.value( qry.record().indexOf( QLatin1String("next_hour_id") ) ).toInt(); QString qryStr = QLatin1String("REPLACE INTO general (id, version, last_saved, calendar, next_hour_id )") + QLatin1String(" VALUES (?, ?, ?, ?, ? );"); qry.prepare( qryStr ); qry.addBindValue( 1 ); qry.addBindValue( current_db_version ); qry.addBindValue( lastSaved ); // If still using calendar names, use the default calendar qry.addBindValue( QVariant( KLocale::QDateCalendar ).toString() ); qry.addBindValue( nextHourId ); qry.exec(); } } ok = QSqlDatabase::database( mIfaceName ).commit(); db.close(); return ok; } bool SqlStorage::loadStats( StorageData *sd, QHash *models, QList *rules ) { bool ok = false; if ( !open() ) return ok; QSqlDatabase::database( mIfaceName ).transaction(); QSqlQuery qry( db ); QDateTime curDateTime = QDateTime::currentDateTime(); KLocale::CalendarSystem calSystem = KLocale::QDateCalendar; qry.exec( QLatin1String("SELECT * FROM general;") ); if ( qry.next() ) { int cLastSaved = qry.record().indexOf( QLatin1String("last_saved") ); int cCalendarSystem = qry.record().indexOf( QLatin1String("calendar") ); int cNextHourId = qry.record().indexOf( QLatin1String("next_hour_id") ); sd->lastSaved = qry.value( cLastSaved ).toUInt(); calSystem = static_cast(qry.value( cCalendarSystem ).toInt()); sd->nextHourId = qry.value( cNextHourId ).toInt(); } sd->calendar = KCalendarSystem::create( calSystem ); if ( models ) { foreach( StatisticsModel * s, *models ) s->setCalendar( sd->calendar ); foreach ( StatisticsModel * s, *models ) { if ( s->periodType() == KNemoStats::HourArchive ) continue; foreach ( KNemoStats::TrafficType trafficType, mTypeMap.keys() ) { qry.exec( QString::fromLatin1( "SELECT * FROM %1s%2 ORDER BY id;" ) .arg( periods.at( s->periodType() ) ) .arg( mTypeMap.value( trafficType ) ) ); int cId = qry.record().indexOf( QLatin1String("id") ); int cRx = qry.record().indexOf( QLatin1String("rx") ); int cTx = qry.record().indexOf( QLatin1String("tx") ); int cDt = 0; int cDays = 0; if ( trafficType == KNemoStats::AllTraffic ) { cDt = qry.record().indexOf( QLatin1String("datetime") ); if ( s->periodType() == KNemoStats::BillPeriod ) { cDays = qry.record().indexOf( QLatin1String("days") ); } } while ( qry.next() ) { int id = qry.value( cId ).toInt(); if ( trafficType == KNemoStats::AllTraffic ) { int days = -1; if ( s->periodType() == KNemoStats::BillPeriod ) { days = qry.value( cDays ).toInt(); } s->createEntry( QDateTime::fromString( qry.value( cDt ).toString(), Qt::ISODate ), id, days ); } s->setTraffic( id, qry.value( cRx ).toULongLong(), qry.value( cTx ).toULongLong(), trafficType ); s->addTrafficType( trafficType, id ); } if ( trafficType == KNemoStats::AllTraffic && s->rowCount() ) { sd->saveFromId.insert( s->periodType(), s->id() ); } } } } if ( rules ) { qry.exec( QLatin1String("SELECT * FROM stats_rules ORDER BY id;") ); int cDt = qry.record().indexOf( QLatin1String("start_date") ); int cType = qry.record().indexOf( QLatin1String("period_units") ); int cUnits = qry.record().indexOf( QLatin1String("period_count") ); while ( qry.next() ) { StatsRule entry; entry.startDate = QDate::fromString( qry.value( cDt ).toString(), Qt::ISODate ); entry.periodUnits = qry.value( cType ).toInt(); entry.periodCount = qry.value( cUnits ).toInt(); *rules << entry; } qry.exec( QLatin1String("SELECT * FROM stats_rules_offpeak ORDER BY id;") ); int cId = qry.record().indexOf( QLatin1String("id") ); int cOpStartTime = qry.record().indexOf( QLatin1String("offpeak_start_time") ); int cOpEndTime = qry.record().indexOf( QLatin1String("offpeak_end_time") ); int cWeekendIsOffpeak = qry.record().indexOf( QLatin1String("weekend_is_offpeak") ); int cWStartTime = qry.record().indexOf( QLatin1String("weekend_start_time") ); int cWEndTime = qry.record().indexOf( QLatin1String("weekend_end_time") ); int cWStartDay = qry.record().indexOf( QLatin1String("weekend_start_day") ); int cWEndDay = qry.record().indexOf( QLatin1String("weekend_end_day") ); while ( qry.next() ) { int id = qry.value( cId ).toInt(); if ( id < rules->count() ) { (*rules)[ id ].logOffpeak = true; (*rules)[ id ].offpeakStartTime = QTime::fromString( qry.value( cOpStartTime ).toString(), time_format ); (*rules)[ id ].offpeakEndTime = QTime::fromString( qry.value( cOpEndTime ).toString(), time_format ); (*rules)[ id ].weekendIsOffpeak = qry.value( cWeekendIsOffpeak ).toBool(); (*rules)[ id ].weekendDayStart = qry.value( cWStartDay ).toInt(); (*rules)[ id ].weekendDayEnd = qry.value( cWEndDay ).toInt(); (*rules)[ id ].weekendTimeStart = QTime::fromString( qry.value( cWStartTime ).toString(), time_format ); (*rules)[ id ].weekendTimeEnd = QTime::fromString( qry.value( cWEndTime ).toString(), time_format ); } } } ok = QSqlDatabase::database( mIfaceName ).commit(); qry.exec( QLatin1String("VACUUM;") ); db.close(); return ok; } bool SqlStorage::saveStats( StorageData *sd, QHash *models, QList *rules, bool fullSave ) { bool ok = false; if ( !open() ) return ok; QSqlDatabase::database( mIfaceName ).transaction(); save( sd, models, rules, fullSave ); ok = QSqlDatabase::database( mIfaceName ).commit(); if ( fullSave ) { QSqlQuery qry( db ); qry.exec( QLatin1String("VACUUM;") ); } db.close(); return ok; } bool SqlStorage::clearStats( StorageData *sd ) { bool ok = false; if ( !open() ) return ok; QSqlDatabase::database( mIfaceName ).transaction(); QSqlQuery qry( db ); foreach ( QString period, periods ) { foreach ( KNemoStats::TrafficType i, mTypeMap.keys() ) { if ( i == KNemoStats::AllTraffic && ( period == periods.at( KNemoStats::Hour ) || period == periods.at( KNemoStats::HourArchive ) ) ) continue; qry.exec( QString::fromLatin1( "DELETE FROM %1s%2;" ).arg( period ).arg( mTypeMap.value( i ) ) ); } } save( sd ); ok = QSqlDatabase::database( mIfaceName ).commit(); qry.exec( QLatin1String("VACUUM;") ); db.close(); return ok; } bool SqlStorage::open() { if ( !mValidDbVer ) return false; if ( !db.isValid() ) return false; if ( db.isOpen() ) return true; db.setDatabaseName( mDbPath ); return db.open(); } void SqlStorage::save( StorageData *sd, QHash *models, QList *rules, bool fullSave ) { QSqlQuery qry( db ); QString qryStr = QLatin1String("REPLACE INTO general (id, version, last_saved, calendar, next_hour_id )") + QLatin1String(" VALUES (?, ?, ?, ?, ? );"); qry.prepare( qryStr ); qry.addBindValue( 1 ); qry.addBindValue( current_db_version ); qry.addBindValue( QDateTime::currentDateTime().toTime_t() ); qry.addBindValue( QVariant( sd->calendar->calendarSystem() ).toString() ); qry.addBindValue( sd->nextHourId ); qry.exec(); if ( models ) { foreach ( StatisticsModel * s, *models ) { foreach ( KNemoStats::TrafficType trafficType, mTypeMap.keys() ) { /* Always do deletes for: hour* Even on a full save, don't delete anything from: days hour_archives hour_archives_* if the model is empty */ if ( s->periodType() == KNemoStats::Hour || ( fullSave && !( ( trafficType == KNemoStats::AllTraffic && ( s->periodType() == KNemoStats::Day || s->periodType() == KNemoStats::HourArchive ) ) || ( s->periodType() == KNemoStats::HourArchive && !s->rowCount() ) ) ) ) { int deleteFrom = sd->saveFromId.value( s->periodType() ); qryStr = QString::fromLatin1( "DELETE FROM %1s%2 WHERE id >= '%3';" ) .arg( periods.at( s->periodType() ) ) .arg( mTypeMap.value( trafficType ) ) .arg( deleteFrom ); qry.exec( qryStr ); } if ( !s->rowCount() ) { continue; } QString dateTimeStr; QString dateTimeStr2; if ( trafficType == KNemoStats::AllTraffic ) { dateTimeStr = QLatin1String(" datetime,"); dateTimeStr2 = QLatin1String(" ?,"); if ( s->periodType() == KNemoStats::BillPeriod ) { dateTimeStr += QLatin1String(" days,"); dateTimeStr2 += QLatin1String(" ?,"); } } qryStr = QLatin1String("REPLACE INTO %1s%2 (id,%3 rx, tx )") + QLatin1String(" VALUES (?,%4 ?, ? );"); qryStr = qryStr .arg( periods.at( s->periodType() ) ) .arg( mTypeMap.value( trafficType ) ) .arg( dateTimeStr ) .arg( dateTimeStr2 ); qry.prepare( qryStr ); int j = sd->saveFromId.value( s->periodType() ); for ( j = s->indexOfId( j ); j < s->rowCount(); ++j ) { if ( s->trafficTypes( j ).contains( trafficType ) ) { qry.addBindValue( s->id( j ) ); if ( trafficType == KNemoStats::AllTraffic ) { qry.addBindValue( s->dateTime( j ).toString( Qt::ISODate ) ); if ( s->periodType() == KNemoStats::BillPeriod ) { qry.addBindValue( s->days( j ) ); } } qry.addBindValue( s->rxBytes( j, trafficType ) ); qry.addBindValue( s->txBytes( j, trafficType ) ); qry.exec(); } } } if ( s->rowCount() ) { sd->saveFromId.insert( s->periodType(), s->id() ); if ( s->periodType() == KNemoStats::HourArchive ) s->clearRows(); } } } if ( fullSave && rules ) { qryStr = QString::fromLatin1( "DELETE FROM stats_rules WHERE id >= '%1';" ).arg( rules->count() ); qry.exec( qryStr ); qryStr = QString::fromLatin1( "DELETE FROM stats_rules_offpeak WHERE id >= '%1';" ).arg( rules->count() ); qry.exec( qryStr ); if ( rules->count() ) { qryStr = QLatin1String("REPLACE INTO stats_rules (id, start_date, period_units, period_count )") + QLatin1String(" VALUES( ?, ?, ?, ? );"); qry.prepare( qryStr ); for ( int i = 0; i < rules->count(); ++i ) { qry.addBindValue( i ); qry.addBindValue( rules->at(i).startDate.toString( Qt::ISODate ) ); qry.addBindValue( rules->at(i).periodUnits ); qry.addBindValue( rules->at(i).periodCount ); qry.exec(); } qryStr = QLatin1String("REPLACE INTO stats_rules_offpeak (id,") + QLatin1String(" offpeak_start_time, offpeak_end_time, weekend_is_offpeak,") + QLatin1String(" weekend_start_time, weekend_end_time, weekend_start_day, weekend_end_day )") + QLatin1String(" VALUES( ?, ?, ?, ?, ?, ?, ?, ? );"); qry.prepare( qryStr ); for ( int i = 0; i < rules->count(); ++i ) { QVariant startTime = QVariant::String; QVariant stopTime = QVariant::String; QVariant weekendIsOffpeak = QVariant::Bool; QVariant wStartTime = QVariant::String; QVariant wEndTime = QVariant::String; QVariant wStartDay = QVariant::Int; QVariant wEndDay = QVariant::Int; if ( !rules->at(i).logOffpeak ) continue; startTime = rules->at(i).offpeakStartTime.toString( time_format ); stopTime = rules->at(i).offpeakEndTime.toString( time_format ); weekendIsOffpeak = rules->at(i).weekendIsOffpeak; if ( rules->at(i).weekendIsOffpeak ) { wStartTime = rules->at(i).weekendTimeStart.toString( time_format ); wEndTime = rules->at(i).weekendTimeEnd.toString( time_format ); wStartDay = rules->at(i).weekendDayStart; wEndDay = rules->at(i).weekendDayEnd; } qry.addBindValue( i ); qry.addBindValue( startTime ); qry.addBindValue( stopTime ); qry.addBindValue( weekendIsOffpeak ); qry.addBindValue( wStartTime ); qry.addBindValue( wEndTime ); qry.addBindValue( wStartDay ); qry.addBindValue( wEndDay ); qry.exec(); } } } } diff --git a/src/knemod/storage/xmlstorage.cpp b/src/knemod/storage/xmlstorage.cpp index b96a6be..4b807ee 100644 --- a/src/knemod/storage/xmlstorage.cpp +++ b/src/knemod/storage/xmlstorage.cpp @@ -1,117 +1,116 @@ /* This file is part of KNemo Copyright (C) 2010 John Stamp KNemo is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. KNemo 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "global.h" #include "statisticsmodel.h" #include "xmlstorage.h" #include "commonstorage.h" #include #include #include // xml storage static const QLatin1String doc_name("statistics"); static const QLatin1String attrib_calendar("calendar"); static const QLatin1String attrib_updated("lastUpdated"); static const QLatin1String attrib_rx("rxBytes"); static const QLatin1String attrib_tx("txBytes"); XmlStorage::XmlStorage() { } void XmlStorage::loadGroup( StorageData *sd, const QDomElement& parentItem, StatisticsModel* statistics ) { QDomNode n = parentItem.namedItem( periods.at( statistics->periodType() ) + QLatin1Char('s') ); if ( !n.isNull() ) { QDomNode node = n.firstChild(); while ( !node.isNull() ) { QDomElement element = node.toElement(); if ( !element.isNull() ) { QDate date; QTime time; int year = element.attribute( periods.at( KNemoStats::Year ) ).toInt(); int month = element.attribute( periods.at( KNemoStats::Month ), QLatin1String("1") ).toInt(); int day = element.attribute( periods.at( KNemoStats::Day ), QLatin1String("1") ).toInt(); sd->calendar->setDate( date, year, month, day ); if ( date.isValid() ) { switch ( statistics->periodType() ) { case KNemoStats::Hour: time = QTime( element.attribute( periods.at( KNemoStats::Hour ) ).toInt(), 0 ); break; default: ;; } int entryIndex = statistics->createEntry( QDateTime( date, time ) ); statistics->setTraffic( entryIndex, element.attribute( attrib_rx ).toULongLong(), element.attribute( attrib_tx ).toULongLong() ); } } node = node.nextSibling(); } statistics->sort( 0 ); // Make sure the ids are in order after a sort for ( int i = 0; i < statistics->rowCount(); ++i ) { statistics->setId( i, i ); } } } bool XmlStorage::loadStats( QString name, StorageData *sd, QHash *models ) { - QUrl dir( generalSettings->statisticsDir ); QDomDocument doc( doc_name ); - QFile file( dir.path() + statistics_prefix + name ); + QFile file( generalSettings->statisticsDir.absoluteFilePath( statistics_prefix + name ) ); if ( !file.open( QIODevice::ReadOnly ) ) return false; if ( !doc.setContent( &file ) ) { file.close(); return false; } file.close(); QDomElement root = doc.documentElement(); // If unknown, empty, or still using calendar names, use the default calendar sd->calendar = KCalendarSystem::create( KLocale::QDateCalendar ); foreach( StatisticsModel * s, *models ) { s->setCalendar( sd->calendar ); loadGroup( sd, root, s ); } sd->lastSaved = root.attribute( attrib_updated ).toUInt(); return true; }