diff --git a/src/kcm/configdialog.cpp b/src/kcm/configdialog.cpp index 9b80765..c2028f8 100644 --- a/src/kcm/configdialog.cpp +++ b/src/kcm/configdialog.cpp @@ -1,1811 +1,1812 @@ /* 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 "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("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( "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( "list-add" ) ); mDlg->pushButtonAll->setIcon( QIcon::fromTheme( "document-new" ) ); mDlg->pushButtonDelete->setIcon( QIcon::fromTheme( "list-remove" ) ); mDlg->pushButtonAddCommand->setIcon( QIcon::fromTheme( "list-add" ) ); mDlg->pushButtonRemoveCommand->setIcon( QIcon::fromTheme( "list-remove" ) ); mDlg->pushButtonUp->setIcon( QIcon::fromTheme( "arrow-up" ) ); mDlg->pushButtonDown->setIcon( QIcon::fromTheme( "arrow-down" ) ); mDlg->pushButtonAddToolTip->setIcon( QIcon::fromTheme( "arrow-right" ) ); mDlg->pushButtonRemoveToolTip->setIcon( QIcon::fromTheme( "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 ); if ( interfaceGroup.hasKey( conf_calendar ) ) { QString oldSetting = interfaceGroup.readEntry( conf_calendar ); - settings->calendarSystem = KCalendarSystem::calendarSystem( oldSetting ); + // FIXME + //settings->calendarSystem = KCalendarSystem::calendarSystem( oldSetting ); interfaceGroup.writeEntry( conf_calendarSystem, static_cast(settings->calendarSystem) ); interfaceGroup.deleteEntry( conf_calendar ); config->sync(); } else 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( "%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( "%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( "%1%2" ).arg( conf_runAsRoot ).arg( i + 1 ); cmd.runAsRoot = interfaceGroup.readEntry( entry, false ); entry = QString( "%1%2" ).arg( conf_command ).arg( i + 1 ); cmd.command = interfaceGroup.readEntry( entry ); entry = QString( "%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("org.kde.knemo", "/knemo", "org.kde.knemo").call("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( "%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( "%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( "%1%2" ).arg( conf_runAsRoot ).arg( i + 1 ); interfaceGroup.writeEntry( entry, settings->commands[i].runAsRoot ); entry = QString( "%1%2" ).arg( conf_command ).arg( i + 1 ); interfaceGroup.writeEntry( entry, settings->commands[i].command ); entry = QString( "%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("org.kde.knemo", "/knemo", "org.kde.knemo").call("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( 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( "lo" ); ifaces.removeAll( "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 ) { settings->iconTheme = TEXT_THEME; mDlg->pixmapError->setPixmap( textIcon( "0.0K", "0.0K", KNemoIface::Unavailable ) ); mDlg->pixmapDisconnected->setPixmap( textIcon( "0.0K", "0.0K", KNemoIface::Available ) ); mDlg->pixmapConnected->setPixmap( textIcon( "0.0K", "0.0K", KNemoIface::Connected ) ); mDlg->pixmapIncoming->setPixmap( textIcon( "123K", "0.0K", KNemoIface::Connected ) ); mDlg->pixmapOutgoing->setPixmap( textIcon( "0.0K", "12K", KNemoIface::Connected ) ); mDlg->pixmapTraffic->setPixmap( textIcon( "123K", "12K", 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 = "network-"; else iconName = "knemo-" + settings->iconTheme + "-"; 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, "knemo" ); } #include "configdialog.moc" diff --git a/src/knemod/interface.cpp b/src/knemod/interface.cpp index 06046f5..0700c68 100644 --- a/src/knemod/interface.cpp +++ b/src/knemod/interface.cpp @@ -1,478 +1,479 @@ /* 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 "backends/backendbase.h" #include "global.h" #include "utils.h" #include "interface.h" #include "interfaceplotterdialog.h" #include "interfacestatistics.h" #include "interfacestatusdialog.h" #include "interfacestatisticsdialog.h" Interface::Interface( const QString &ifname, const BackendData* data ) : QObject(), mIfaceState( KNemoIface::UnknownState ), mPreviousIfaceState( KNemoIface::UnknownState ), mIfaceName( ifname ), mRealSec( 0.0 ), mUptime( 0 ), mUptimeString( "00:00:00" ), mRxRate( 0 ), mTxRate( 0 ), mIcon( this ), mIfaceStatistics( 0 ), mStatusDialog( 0 ), mStatisticsDialog( 0 ), mPlotterDialog( 0 ), mBackendData( data ) { mPlotterDialog = new InterfacePlotterDialog( mIfaceName ); connect( &mIcon, SIGNAL( statisticsSelected() ), this, SLOT( showStatisticsDialog() ) ); } Interface::~Interface() { delete mStatusDialog; delete mPlotterDialog; delete mStatisticsDialog; delete mIfaceStatistics; } void Interface::configChanged() { KSharedConfigPtr config = KGlobal::config(); QString group( confg_interface ); group += mIfaceName; KConfigGroup interfaceGroup( config, group ); InterfaceSettings s; mSettings.alias = interfaceGroup.readEntry( conf_alias ).trimmed(); mSettings.iconTheme = interfaceGroup.readEntry( conf_iconTheme, s.iconTheme ); QStringList themeNames; QList themes = findThemes(); // Let's check that it's available foreach( KNemoTheme theme, themes ) themeNames << theme.internalName; themeNames << NETLOAD_THEME; if ( !themeNames.contains( mSettings.iconTheme ) ) mSettings.iconTheme = TEXT_THEME; mSettings.colorIncoming = interfaceGroup.readEntry( conf_colorIncoming, s.colorIncoming ); mSettings.colorOutgoing = interfaceGroup.readEntry( conf_colorOutgoing, s.colorOutgoing ); KColorScheme scheme(QPalette::Active, KColorScheme::View); mSettings.colorDisabled = interfaceGroup.readEntry( conf_colorDisabled, scheme.foreground( KColorScheme::InactiveText ).color() ); mSettings.colorUnavailable = interfaceGroup.readEntry( conf_colorUnavailable, scheme.foreground( KColorScheme::InactiveText ).color() ); mSettings.colorBackground = scheme.foreground( KColorScheme::InactiveText ).color(); mSettings.iconFont = interfaceGroup.readEntry( conf_iconFont, s.iconFont ); mSettings.dynamicColor = interfaceGroup.readEntry( conf_dynamicColor, s.dynamicColor ); mSettings.colorIncomingMax = interfaceGroup.readEntry( conf_colorIncomingMax, s.colorIncomingMax ); mSettings.colorOutgoingMax = interfaceGroup.readEntry( conf_colorOutgoingMax, s.colorOutgoingMax ); mSettings.barScale = interfaceGroup.readEntry( conf_barScale, s.barScale ); mSettings.inMaxRate = interfaceGroup.readEntry( conf_inMaxRate, s.inMaxRate )*1024; mSettings.outMaxRate = interfaceGroup.readEntry( conf_outMaxRate, s.outMaxRate )*1024; mSettings.hideWhenDisconnected = interfaceGroup.readEntry( conf_hideWhenNotAvail, s.hideWhenDisconnected ); mSettings.hideWhenUnavailable = interfaceGroup.readEntry( conf_hideWhenNotExist, s.hideWhenUnavailable ); mSettings.activateStatistics = interfaceGroup.readEntry( conf_activateStatistics, s.activateStatistics ); mSettings.trafficThreshold = clamp(interfaceGroup.readEntry( conf_trafficThreshold, s.trafficThreshold ), 0, 1000 ); mSettings.warnRules.clear(); int warnRuleCount = interfaceGroup.readEntry( conf_warnRules, 0 ); for ( int i = 0; i < warnRuleCount; ++i ) { group = QString( "%1%2 #%3" ).arg( confg_warnRule ).arg( mIfaceName ).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.periodUnits ), 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(); mSettings.warnRules << warn; } } if ( interfaceGroup.hasKey( conf_calendar ) ) { QString oldSetting = interfaceGroup.readEntry( conf_calendar ); - mSettings.calendarSystem = KCalendarSystem::calendarSystem( oldSetting ); + // FIXME + //mSettings.calendarSystem = KCalendarSystem::calendarSystem( oldSetting ); interfaceGroup.writeEntry( conf_calendarSystem, static_cast(mSettings.calendarSystem) ); interfaceGroup.deleteEntry( conf_calendar ); config->sync(); } else mSettings.calendarSystem = static_cast(interfaceGroup.readEntry( conf_calendarSystem, static_cast(KLocale::QDateCalendar) )); mSettings.statsRules.clear(); int statsRuleCount = interfaceGroup.readEntry( conf_statsRules, 0 ); KCalendarSystem *testCal = KCalendarSystem::create( mSettings.calendarSystem ); for ( int i = 0; i < statsRuleCount; ++i ) { group = QString( "%1%2 #%3" ).arg( confg_statsRule ).arg( mIfaceName ).arg( i ); if ( config->hasGroup( group ) ) { KConfigGroup statsGroup( config, group ); StatsRule rule; rule.startDate = statsGroup.readEntry( conf_statsStartDate, QDate() ); rule.periodUnits = clamp(statsGroup.readEntry( conf_statsPeriodUnits, rule.periodUnits ), KNemoStats::Day, KNemoStats::Year ); rule.periodCount = clamp(statsGroup.readEntry( conf_statsPeriodCount, rule.periodCount ), 1, 1000 ); rule.logOffpeak = statsGroup.readEntry( conf_logOffpeak,rule.logOffpeak ); rule.offpeakStartTime = QTime::fromString( statsGroup.readEntry( conf_offpeakStartTime, rule.offpeakStartTime.toString( Qt::ISODate ) ), Qt::ISODate ); rule.offpeakEndTime = QTime::fromString( statsGroup.readEntry( conf_offpeakEndTime, rule.offpeakEndTime.toString( Qt::ISODate ) ), Qt::ISODate ); rule.weekendIsOffpeak = statsGroup.readEntry( conf_weekendIsOffpeak, rule.weekendIsOffpeak ); rule.weekendDayStart = clamp(statsGroup.readEntry( conf_weekendDayStart, rule.weekendDayStart ), 1, testCal->daysInWeek( QDate::currentDate() ) ); rule.weekendDayEnd = clamp(statsGroup.readEntry( conf_weekendDayEnd, rule.weekendDayEnd ), 1, testCal->daysInWeek( QDate::currentDate() ) ); rule.weekendTimeStart = QTime::fromString( statsGroup.readEntry( conf_weekendTimeStart, rule.weekendTimeStart.toString( Qt::ISODate ) ), Qt::ISODate ); rule.weekendTimeEnd = QTime::fromString( statsGroup.readEntry( conf_weekendTimeEnd, rule.weekendTimeEnd.toString( Qt::ISODate ) ), Qt::ISODate ); if ( rule.isValid( testCal ) ) { mSettings.statsRules << rule; } } } mSettings.commands.clear(); int numCommands = interfaceGroup.readEntry( conf_numCommands, s.numCommands ); for ( int i = 0; i < numCommands; i++ ) { QString entry; InterfaceCommand cmd; entry = QString( "%1%2" ).arg( conf_runAsRoot ).arg( i + 1 ); cmd.runAsRoot = interfaceGroup.readEntry( entry, false ); entry = QString( "%1%2" ).arg( conf_command ).arg( i + 1 ); cmd.command = interfaceGroup.readEntry( entry ); entry = QString( "%1%2" ).arg( conf_menuText ).arg( i + 1 ); cmd.menuText = interfaceGroup.readEntry( entry ); mSettings.commands.append( cmd ); } // This prevents needless regeneration of icon when first shown in tray if ( mIfaceState == KNemoIface::UnknownState ) { mIfaceState = mBackendData->status; mPreviousIfaceState = mIfaceState; } mIcon.configChanged(); if ( mIfaceStatistics ) { mIfaceStatistics->configChanged(); if ( !mSettings.activateStatistics ) stopStatistics(); } else if ( mSettings.activateStatistics ) { startStatistics(); } if ( mStatusDialog ) mStatusDialog->configChanged(); if ( mStatisticsDialog != 0 ) mStatisticsDialog->configChanged(); if ( mPlotterDialog ) mPlotterDialog->useBitrate( generalSettings->useBitrate ); } void Interface::processUpdate() { mPreviousIfaceState = mIfaceState; unsigned int trafficThreshold = mSettings.trafficThreshold; mIfaceState = mBackendData->status; int units = 1; if ( generalSettings->useBitrate ) units = 8; mRxRate = mBackendData->incomingBytes * units / generalSettings->pollInterval; mTxRate = mBackendData->outgoingBytes * units / generalSettings->pollInterval; mRxRateStr = formattedRate( mRxRate, generalSettings->useBitrate ); mTxRateStr = formattedRate( mTxRate, generalSettings->useBitrate ); QString title = mSettings.alias; if ( title.isEmpty() ) title = mIfaceName; if ( mIfaceState & KNemoIface::Connected ) { // the interface is connected, look for traffic if ( ( mBackendData->rxPackets - mBackendData->prevRxPackets ) > trafficThreshold ) mIfaceState |= KNemoIface::RxTraffic; if ( ( mBackendData->txPackets - mBackendData->prevTxPackets ) > trafficThreshold ) mIfaceState |= KNemoIface::TxTraffic; if ( mIfaceStatistics ) { // We only check once an hour if we need to create a new stats entry. // However, the timer will be out of sync if we're resuming from suspend, // so we just check if we need to readjust when an interface becomes connected. if ( mPreviousIfaceState < KNemoIface::Connected ) mIfaceStatistics->checkValidEntry(); mIfaceStatistics->addRxBytes( mBackendData->incomingBytes ); mIfaceStatistics->addTxBytes( mBackendData->outgoingBytes ); } updateTime(); if ( mPreviousIfaceState < KNemoIface::Connected ) { QString connectedStr; if ( mBackendData->isWireless ) connectedStr = i18n( "%1 is connected to %2", title, mBackendData->essid ); else connectedStr = i18n( "%1 is connected", title ); if ( mPreviousIfaceState != KNemoIface::UnknownState ) KNotification::event( "connected", connectedStr ); } } else if ( mIfaceState & KNemoIface::Available ) { if ( mPreviousIfaceState & KNemoIface::Connected ) { KNotification::event( "disconnected", i18n( "%1 has disconnected", title ) ); if ( mBackendData->interfaceType == KNemoIface::PPP ) backend->clearTraffic( mIfaceName ); resetUptime(); } else if ( mPreviousIfaceState < KNemoIface::Available ) { if ( mPreviousIfaceState != KNemoIface::UnknownState ) KNotification::event( "available", i18n( "%1 is available", title ) ); } } else if ( mIfaceState == KNemoIface::Unavailable && mPreviousIfaceState > KNemoIface::Unavailable ) { KNotification::event( "unavailable", i18n( "%1 is unavailable", title ) ); backend->clearTraffic( mIfaceName ); resetUptime(); } if ( mPreviousIfaceState != mIfaceState ) mIcon.updateTrayStatus(); if ( mPlotterDialog ) mPlotterDialog->updatePlotter( mRxRate, mTxRate ); mIcon.updateToolTip(); if ( mStatusDialog ) mStatusDialog->updateDialog(); } void Interface::resetUptime() { mUptime = 0; mRealSec = 0.0; mUptimeString = "00:00:00"; mRxRate = 0; mTxRate = 0; mRxRateStr = formattedRate( mRxRate, generalSettings->useBitrate ); mTxRateStr = formattedRate( mTxRate, generalSettings->useBitrate ); } void Interface::showStatusDialog( bool fromContextMenu ) { // Toggle the status dialog. // First click will show the status dialog, second will hide it. if ( mStatusDialog == 0L ) { mStatusDialog = new InterfaceStatusDialog( this ); if ( mIfaceStatistics != 0 ) { connect( mIfaceStatistics, SIGNAL( currentEntryChanged() ), mStatusDialog, SLOT( statisticsChanged() ) ); mStatusDialog->statisticsChanged(); } } activateOrHide( mStatusDialog, fromContextMenu ); } void Interface::showSignalPlotter( bool fromContextMenu ) { // Toggle the signal plotter. activateOrHide( mPlotterDialog, fromContextMenu ); } void Interface::showStatisticsDialog() { if ( mStatisticsDialog == 0 ) { mStatisticsDialog = new InterfaceStatisticsDialog( this ); if ( mIfaceStatistics == 0 ) { // should never happen but you never know... startStatistics(); } connect( mStatisticsDialog, SIGNAL( clearStatistics() ), mIfaceStatistics, SLOT( clearStatistics() ) ); } mStatisticsDialog->show(); } void Interface::updateTime() { mRealSec += generalSettings->pollInterval; if ( mRealSec < 1.0 ) return; mUptime += trunc( mRealSec ); mRealSec -= trunc( mRealSec ); time_t updays = mUptime / 86400; mUptimeString = i18np("1 day, ","%1 days, ",updays); mUptime -= 86400 * updays; // we only want the seconds of today int hrs = mUptime / 3600; int mins = ( mUptime - hrs * 3600 ) / 60; int secs = mUptime - hrs * 3600 - mins * 60; QString time; time.sprintf( "%02d:%02d:%02d", hrs, mins, secs ); mUptimeString += time; } void Interface::startStatistics() { mIfaceStatistics = new InterfaceStatistics( this ); connect( mIfaceStatistics, SIGNAL( warnTraffic( QString, quint64, quint64 ) ), this, SLOT( warnTraffic( QString, quint64, quint64 ) ) ); if ( mStatusDialog != 0 ) { connect( mIfaceStatistics, SIGNAL( currentEntryChanged() ), mStatusDialog, SLOT( statisticsChanged() ) ); mStatusDialog->statisticsChanged(); } } void Interface::stopStatistics() { // this will close an open statistics dialog delete mStatisticsDialog; mStatisticsDialog = 0; delete mIfaceStatistics; mIfaceStatistics = 0; } void Interface::warnTraffic( QString warnText, quint64 threshold, quint64 current ) { if ( !warnText.isEmpty() ) { warnText = warnText.replace( QRegExp("%i"), mIfaceName ); warnText = warnText.replace( QRegExp("%a"), mSettings.alias ); warnText = warnText.replace( QRegExp("%t"), KIO::convertSize( threshold ) ); warnText = warnText.replace( QRegExp("%c"), KIO::convertSize( threshold ) ); } else { warnText = i18n( "" "
%1:Exceeded traffic limit of %2\n" "(currently %3)
", mIfaceName, KIO::convertSize( threshold ), KIO::convertSize( current ) ); } KNotification::event( "exceededTraffic", warnText ); } void Interface::toggleSignalPlotter( bool show ) { if ( !mPlotterDialog ) return; if ( show ) mPlotterDialog->show(); else mPlotterDialog->hide(); } bool Interface::plotterVisible() { if ( !mPlotterDialog || !mPlotterDialog->isVisible() ) return false; return true; } // taken from ksystemtray.cpp void Interface::activateOrHide( QWidget* widget, bool onlyActivate ) { if ( !widget ) return; KWindowInfo info1 = KWindowSystem::windowInfo( widget->winId(), NET::XAWMState | NET::WMState ); // mapped = visible (but possibly obscured) bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized(); // - not mapped -> show, raise, focus // - mapped // - obscured -> raise, focus // - not obscured -> hide if( !mapped ) { KWindowSystem::setOnDesktop( widget->winId(), KWindowSystem::currentDesktop() ); widget->show(); widget->raise(); } else { QListIterator< WId > it (KWindowSystem::stackingOrder()); it.toBack(); while( it.hasPrevious() ) { WId id = it.previous(); if( id == widget->winId() ) break; KWindowInfo info2 = KWindowSystem::windowInfo( id, NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType ); if( info2.mappingState() != NET::Visible ) continue; // not visible on current desktop -> ignore if( !info2.geometry().intersects( widget->geometry())) continue; // not obscuring the window -> ignore if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove )) continue; // obscured by window kept above -> ignore NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask ); if( type == NET::Dock || type == NET::TopMenu ) continue; // obscured by dock or topmenu -> ignore widget->raise(); KWindowSystem::activateWindow( widget->winId()); return; } if ( !onlyActivate ) { widget->hide(); } } } #include "interface.moc" diff --git a/src/knemod/storage/sqlstorage.cpp b/src/knemod/storage/sqlstorage.cpp index ecf0f06..b666886 100644 --- a/src/knemod/storage/sqlstorage.cpp +++ b/src/knemod/storage/sqlstorage.cpp @@ -1,571 +1,572 @@ /* 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 static const QString time_format( "hh:mm:ss" ); static const int current_db_version = 2; SqlStorage::SqlStorage( QString ifaceName ) : mValidDbVer( true ) , mIfaceName( ifaceName ) { QUrl dir( generalSettings->statisticsDir ); mDbPath = QString( "%1%2%3.db" ).arg( dir.path() ).arg( statistics_prefix ).arg( mIfaceName ); QStringList drivers = QSqlDatabase::drivers(); if ( drivers.contains( "QSQLITE" ) ) db = QSqlDatabase::addDatabase( "QSQLITE", mIfaceName ); mTypeMap.insert( KNemoStats::AllTraffic, "" ); mTypeMap.insert( KNemoStats::OffpeakTraffic, "_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 = "CREATE TABLE IF NOT EXISTS general (id INTEGER PRIMARY KEY, version INTEGER," " last_saved BIGINT, calendar TEXT, next_hour_id INTEGER );"; qry.exec( qryStr ); qryStr = "CREATE TABLE IF NOT EXISTS stats_rules (id INTEGER PRIMARY KEY, start_date DATETIME," " period_units INTEGER, period_count INTEGER );"; qry.exec( qryStr ); qryStr = "CREATE TABLE IF NOT EXISTS stats_rules_offpeak (id INTEGER PRIMARY KEY," " offpeak_start_time TEXT, offpeak_end_time TEXT," " weekend_is_offpeak BOOLEAN, weekend_start_time TEXT, weekend_end_time TEXT," " 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 = "CREATE TABLE IF NOT EXISTS %1s%2 (id INTEGER PRIMARY KEY,%3" " rx BIGINT, tx BIGINT );"; if ( j == KNemoStats::AllTraffic ) { dateTimeStr = " datetime DATETIME,"; if ( i == KNemoStats::BillPeriod ) dateTimeStr += " 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 = "datetime"; startVal = startDateTime.toString( Qt::ISODate ); endVal = nextStartDateTime.toString( Qt::ISODate ); } else { searchCol = "id"; startVal = QString::number( hourArchive->id( 0 ) ); endVal = QString::number( hourArchive->id()+1 ); } QString qryStr = "SELECT * FROM %1s%2 WHERE %3 >= '%4'"; if ( nextStartDate.isValid() ) { qryStr += " 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 += " ORDER BY id;"; qry.exec( qryStr ); int cId = qry.record().indexOf( "id" ); int cRx = qry.record().indexOf( "rx" ); int cTx = qry.record().indexOf( "tx" ); int cDt = 0; if ( trafficType == KNemoStats::AllTraffic ) cDt = qry.record().indexOf( "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( "SELECT * FROM general;" ); if ( qry.next() ) { int dbVersion = qry.value( qry.record().indexOf( "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( "last_saved" ) ).toInt(); QString calendarType = qry.value( qry.record().indexOf( "calendar" ) ).toString(); int nextHourId = qry.value( qry.record().indexOf( "next_hour_id" ) ).toInt(); QString qryStr = "REPLACE INTO general (id, version, last_saved, calendar, next_hour_id )" " VALUES (?, ?, ?, ?, ? );"; qry.prepare( qryStr ); qry.addBindValue( 1 ); qry.addBindValue( current_db_version ); qry.addBindValue( lastSaved ); - qry.addBindValue( QVariant( KCalendarSystem::calendarSystem( calendarType ) ).toString() ); + // FIXME + //qry.addBindValue( QVariant( KCalendarSystem::calendarSystem( calendarType ) ).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( "SELECT * FROM general;" ); if ( qry.next() ) { int cLastSaved = qry.record().indexOf( "last_saved" ); int cCalendarSystem = qry.record().indexOf( "calendar" ); int cNextHourId = qry.record().indexOf( "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( "SELECT * FROM %1s%2 ORDER BY id;" ) .arg( periods.at( s->periodType() ) ) .arg( mTypeMap.value( trafficType ) ) ); int cId = qry.record().indexOf( "id" ); int cRx = qry.record().indexOf( "rx" ); int cTx = qry.record().indexOf( "tx" ); int cDt = 0; int cDays = 0; if ( trafficType == KNemoStats::AllTraffic ) { cDt = qry.record().indexOf( "datetime" ); if ( s->periodType() == KNemoStats::BillPeriod ) { cDays = qry.record().indexOf( "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( "SELECT * FROM stats_rules ORDER BY id;" ); int cDt = qry.record().indexOf( "start_date" ); int cType = qry.record().indexOf( "period_units" ); int cUnits = qry.record().indexOf( "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( "SELECT * FROM stats_rules_offpeak ORDER BY id;" ); int cId = qry.record().indexOf( "id" ); int cOpStartTime = qry.record().indexOf( "offpeak_start_time" ); int cOpEndTime = qry.record().indexOf( "offpeak_end_time" ); int cWeekendIsOffpeak = qry.record().indexOf( "weekend_is_offpeak" ); int cWStartTime = qry.record().indexOf( "weekend_start_time" ); int cWEndTime = qry.record().indexOf( "weekend_end_time" ); int cWStartDay = qry.record().indexOf( "weekend_start_day" ); int cWEndDay = qry.record().indexOf( "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( "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( "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( "DELETE FROM %1s%2;" ).arg( period ).arg( mTypeMap.value( i ) ) ); } } save( sd ); ok = QSqlDatabase::database( mIfaceName ).commit(); qry.exec( "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 = "REPLACE INTO general (id, version, last_saved, calendar, next_hour_id )" " 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( "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 = " datetime,"; dateTimeStr2 = " ?,"; if ( s->periodType() == KNemoStats::BillPeriod ) { dateTimeStr += " days,"; dateTimeStr2 += " ?,"; } } qryStr = "REPLACE INTO %1s%2 (id,%3 rx, tx )" " 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( "DELETE FROM stats_rules WHERE id >= '%1';" ).arg( rules->count() ); qry.exec( qryStr ); qryStr = QString( "DELETE FROM stats_rules_offpeak WHERE id >= '%1';" ).arg( rules->count() ); qry.exec( qryStr ); if ( rules->count() ) { qryStr = "REPLACE INTO stats_rules (id, start_date, period_units, period_count )" " 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 = "REPLACE INTO stats_rules_offpeak (id," " offpeak_start_time, offpeak_end_time, weekend_is_offpeak," " weekend_start_time, weekend_end_time, weekend_start_day, weekend_end_day )" " 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 21ac2cd..3212324 100644 --- a/src/knemod/storage/xmlstorage.cpp +++ b/src/knemod/storage/xmlstorage.cpp @@ -1,117 +1,118 @@ /* 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 char doc_name[] = "statistics"; static const char attrib_calendar[] = "calendar"; static const char attrib_updated[] = "lastUpdated"; static const char attrib_rx[] = "rxBytes"; static const char attrib_tx[] = "txBytes"; XmlStorage::XmlStorage() { } void XmlStorage::loadGroup( StorageData *sd, const QDomElement& parentItem, StatisticsModel* statistics ) { QDomNode n = parentItem.namedItem( periods.at( statistics->periodType() ) + "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 ), "1" ).toInt(); int day = element.attribute( periods.at( KNemoStats::Day ), "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 ); if ( !file.open( QIODevice::ReadOnly ) ) return false; if ( !doc.setContent( &file ) ) { file.close(); return false; } file.close(); QDomElement root = doc.documentElement(); // If unknown or empty calendar it will default to gregorian - sd->calendar = KCalendarSystem::create( KCalendarSystem::calendarSystem( root.attribute( attrib_calendar ) ) ); + // FIXME + //sd->calendar = KCalendarSystem::create( KCalendarSystem::calendarSystem( root.attribute( attrib_calendar ) ) ); foreach( StatisticsModel * s, *models ) { s->setCalendar( sd->calendar ); loadGroup( sd, root, s ); } sd->lastSaved = root.attribute( attrib_updated ).toUInt(); return true; }