kcmpureftpdstat.cpp
00001 /***************************************************************************
00002 kcmpureftpdstat.cpp - PureFTPd Statistics
00003 -------------------
00004 begin : Thu Jan 2 2002
00005 copyright : (C) 2002,2003 by Claudiu Costin
00006 email : claudiuc@kde.org
00007 ***************************************************************************/
00008
00009 /***************************************************************************
00010 * *
00011 * This program is free software; you can redistribute it and/or modify *
00012 * it under the terms of the GNU General Public License as published by *
00013 * the Free Software Foundation; either version 2 of the License, or *
00014 * (at your option) any later version. *
00015 * *
00016 ***************************************************************************/
00017
00018
00019 #include <qclipboard.h>
00020 #include <qwhatsthis.h>
00021 #include <qcstring.h>
00022 #include <qstringlist.h>
00023 #include <qfile.h>
00024 #include <qfileinfo.h>
00025 #include <qtextstream.h>
00026 #include <qdom.h>
00027 #include <qregexp.h>
00028 #include <qlayout.h>
00029 #include <qbuttongroup.h>
00030
00031 #include <klocale.h>
00032 #include <kcursor.h>
00033 #include <kseparator.h>
00034 #include <kstddirs.h>
00035 #include <kmessagebox.h>
00036 #include <kfiledialog.h>
00037 #include <kiconloader.h>
00038 #include <kapplication.h>
00039
00040 #include "kcmpureftpdstat.moc"
00041
00042 KPureftpdStat::KPureftpdStat(QWidget *parent, const char *name)
00043 : KCModule(parent, name), infoProcess(0), logProcess(0) {
00044
00045 pureftpwhoExe=QString::null;
00046 logMaxNumLines=0;
00047 reachedMaxNumLines=false;
00048 deliberatedKill=false;
00049 isProcessingInfo=false;
00050 mFound=false;
00051
00052 config = new KConfig("kcmpureftpdstatrc",false,false);
00053 infoTimer = new QTimer(this);
00054 connect(infoTimer,SIGNAL(timeout()),this,SLOT(startInfoProcess()));
00055
00056 initView();
00057
00058
00059 // ensure changed() when user modify settings
00060 connect(rbInfoDefault,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00061 connect(rbInfoCustom,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00062 connect(rbLogFile,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00063 connect(rbLogCustom,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00064 connect(pureftpwhoDefault,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00065 connect(pureftpwhoPath,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00066 connect(logFileName,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00067 connect(infoCommand,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00068 connect(logCommand,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00069 connect(updateInterval,SIGNAL(valueChanged(int)),this,SLOT(configChanged(int)));
00070 connect(historyLines,SIGNAL(valueChanged(int)),this,SLOT(configChanged(int)));
00071
00072 load();
00073
00074 displayInfoMessage(InfoInit);
00075 displayLogMessage(LogInit);
00076
00077 logProcess = new KShellProcess;
00078 connect(logProcess,SIGNAL(receivedStdout(KProcess *,char*, int)),this,SLOT(slotLogProcessRecvStdout(KProcess *,char*, int)));
00079 connect(logProcess,SIGNAL(receivedStderr(KProcess *,char*, int)),this,SLOT(slotLogProcessRecvStderr(KProcess *,char*, int)));
00080 connect(logProcess,SIGNAL(processExited(KProcess *)),this,SLOT(slotLogProcessExited(KProcess *)));
00081
00082 infoProcess = new KShellProcess;
00083 connect(infoProcess,SIGNAL(receivedStdout(KProcess *,char *, int)),this,SLOT(slotInfoProcessRecvStdout(KProcess *, char*, int)));
00084 connect(infoProcess,SIGNAL(receivedStderr(KProcess *,char *, int)),this,SLOT(slotInfoProcessRecvStderr(KProcess *, char*, int)));
00085 connect(infoProcess,SIGNAL(processExited(KProcess *)),this,SLOT(slotInfoProcessExited(KProcess *)));
00086 }
00087
00088
00089 KPureftpdStat::~KPureftpdStat() {
00090 if (infoTimer->isActive()) {
00091 infoTimer->stop();
00092 }
00093 if (infoProcess->isRunning()) {
00094 stopInfoProcess();
00095 }
00096 if (logProcess->isRunning()) {
00097 stopLogProcess();
00098 }
00099 }
00100
00101 void KPureftpdStat::initView() {
00102
00103 QVBoxLayout *vbmain = new QVBoxLayout(this,0,0);
00104 tab = new QTabWidget(this);
00105 vbmain->addWidget(tab);
00106
00107 // "Information" tab
00108 tabInfo = new QWidget(this);
00109 tab->addTab(tabInfo,i18n("Information"));
00110 QWhatsThis::add(tabInfo, i18n(
00111 "<qml>Informations about current connections to your "
00112 "<b>pure-ftpd</b> FTP server</qml>"
00113 ));
00114 QVBoxLayout *vbox1 = new QVBoxLayout(tabInfo,5,5);
00115 QGroupBox *grpConn = new QGroupBox(i18n("FTP Connections"),tabInfo);
00116 QVBoxLayout *vbox11 = new QVBoxLayout(grpConn,5,5);
00117 vbox11->addSpacing(grpConn->fontMetrics().height());
00118 connList = new KListView(grpConn);
00119
00120 connList->addColumn(i18n("Username"),-1);
00121 connList->addColumn(i18n("State"),-1);
00122 connList->addColumn(i18n("Time"),-1);
00123 connList->addColumn(i18n("Percentage"),-1);
00124 connList->addColumn(i18n("File"),-1);
00125 connList->setMaximumHeight(10*connList->fontMetrics().height());
00126 connList->setAllColumnsShowFocus(true);
00127 connList->setShowSortIndicator(true);
00128 connList->setColumnAlignment(2,Qt::AlignRight);
00129 connList->setColumnAlignment(3,Qt::AlignRight);
00130 vbox11->addWidget(connList);
00131
00132 QGroupBox *grpConnInfo = new QGroupBox(i18n("Extended Informations"),tabInfo);
00133 QVBoxLayout *vbox12 = new QVBoxLayout(grpConnInfo,5,5);
00134 vbox12->addSpacing(grpConnInfo->fontMetrics().height());
00135 txtExtInfo = new QTextView(grpConnInfo);
00136 vbox12->addWidget(txtExtInfo);
00137
00138 infoUpdate = new KPushButton(i18n("Continuos &Update"),tabInfo);
00139 infoUpdate->setToggleButton(true);
00140
00141 grpInfoMessage = new QGroupBox(i18n(" Message "),tabInfo);
00142 grpInfoMessage->setMinimumHeight(8*grpInfoMessage->fontMetrics().height());
00143 QGridLayout *gbox13 = new QGridLayout(grpInfoMessage,2,2,5);
00144 mesgInfoIcon = new QLabel(grpInfoMessage);
00145 mesgInfoIcon->setMargin(10);
00146 mesgInfoText = new QLabel(grpInfoMessage);
00147 mesgInfoText->setAlignment(Qt::AlignLeft | Qt::AlignTop);
00148
00149 gbox13->addRowSpacing(0,grpInfoMessage->fontMetrics().height());
00150 gbox13->setColStretch(1,10);
00151 gbox13->setRowStretch(1,10);
00152 gbox13->addWidget(mesgInfoIcon,1,0,Qt::AlignCenter);
00153 gbox13->addWidget(mesgInfoText,1,1);
00154
00155 vbox1->addWidget(grpConn);
00156 vbox1->addSpacing(5);
00157 vbox1->addWidget(grpConnInfo);
00158 vbox1->addSpacing(5);
00159 vbox1->addWidget(infoUpdate,0,Qt::AlignRight);
00160 vbox1->addSpacing(5);
00161 vbox1->addWidget(grpInfoMessage);
00162 vbox1->addStretch();
00163
00164 connect(infoUpdate,SIGNAL(clicked()),this,SLOT(slotInfoProcessToggleUpdate()));
00165 connect(connList,SIGNAL(clicked(QListViewItem*)),this,SLOT(slotShowExtendedInfo(QListViewItem*)));
00166
00167
00168 // "Log" tab
00169 tabLog = new QWidget(this);
00170 tab->addTab(tabLog,i18n("Log"));
00171 QWhatsThis::add(tabLog, i18n(
00172 "<qml>Show <b>pure-ftpd</b> server log file activity "
00173 "in real time. Also you can search in log view "
00174 "for some special keywords using usual search "
00175 "options.</qml>"
00176 ));
00177 QVBoxLayout *vbox2 = new QVBoxLayout(tabLog,5,5);
00178 QLabel *txtLogOutput = new QLabel(i18n("Log Output:"),tabLog);
00179 logOutput = new QMultiLineEdit(tabLog);
00180 logOutput->setReadOnly(true);
00181 logOutput->setMinimumHeight(15*logOutput->fontMetrics().height());
00182 logOutput->setFont(KGlobalSettings::fixedFont());
00183 logOutput->setWordWrap(QTextEdit::NoWrap);
00184 KCursor::setAutoHideCursor(logOutput,true);
00185
00186 logUpdate = new KPushButton(i18n("Continuos &Update"),tabLog);
00187 logUpdate->setToggleButton(true);
00188 logSave = new KPushButton(i18n("&Save..."),tabLog);
00189 logCopy = new KPushButton(i18n("&Copy to Clipboard"),tabLog);
00190 logClear = new KPushButton(i18n("Cl&ear"),tabLog);
00191
00192 QHBoxLayout *hbox21 = new QHBoxLayout();
00193 hbox21->addWidget(logSave);
00194 hbox21->addSpacing(5);
00195 hbox21->addWidget(logCopy);
00196 hbox21->addSpacing(5);
00197 hbox21->addWidget(logClear);
00198 hbox21->addStretch();
00199 hbox21->addWidget(logUpdate);
00200
00201
00202 KSeparator *sep = new KSeparator(KSeparator::HLine,tabLog);
00203
00204 caseSensitive = new QCheckBox(i18n("Case &sensitive"),tabLog);
00205 wholeWords = new QCheckBox(i18n("&Whole words only"),tabLog);
00206 findBackwards = new QCheckBox(i18n("Find &backwards"),tabLog);
00207 logSearch = new KPushButton(i18n("&Search"),tabLog);
00208 logResetSearch = new KPushButton(i18n("&Reset Search"),tabLog);
00209 QLabel *txtSearch = new QLabel(i18n("Sea&rch for:"),tabLog);
00210 editSearch = new KLineEdit(tabLog);
00211 txtSearch->setBuddy(editSearch);
00212
00213 QGridLayout *gbox22 = new QGridLayout();
00214 gbox22->addWidget(txtSearch,1,1,Qt::AlignRight);
00215 gbox22->addWidget(editSearch,1,2);
00216 gbox22->addWidget(logSearch,1,3,Qt::AlignLeft);
00217 gbox22->addWidget(logResetSearch,2,3,Qt::AlignLeft);
00218 gbox22->addMultiCellWidget(caseSensitive,2,2,1,2);
00219 gbox22->addWidget(logResetSearch,2,3,Qt::AlignRight);
00220 gbox22->addMultiCellWidget(wholeWords,3,3,1,2);
00221 gbox22->addMultiCellWidget(findBackwards,4,4,1,2);
00222
00223 grpLogMessage = new QGroupBox(i18n(" Message "),tabLog);
00224 grpLogMessage->setMinimumHeight(8*grpLogMessage->fontMetrics().height());
00225 QGridLayout *gbox23 = new QGridLayout(grpLogMessage,2,2,5);
00226 mesgLogIcon = new QLabel(grpLogMessage);
00227 mesgLogIcon->setMargin(10);
00228 mesgLogText = new QLabel(grpLogMessage);
00229 mesgLogText->setAlignment(Qt::AlignLeft | Qt::AlignTop);
00230
00231 gbox23->addRowSpacing(0,grpLogMessage->fontMetrics().height());
00232 gbox23->setColStretch(1,10);
00233 gbox23->setRowStretch(1,10);
00234 gbox23->addWidget(mesgLogIcon,1,0,Qt::AlignCenter);
00235 gbox23->addWidget(mesgLogText,1,1);
00236
00237
00238 vbox2->addWidget(txtLogOutput);
00239 vbox2->addWidget(logOutput);
00240 vbox2->addSpacing(5);
00241 vbox2->addLayout(hbox21);
00242 vbox2->addSpacing(5);
00243 vbox2->addWidget(grpLogMessage);
00244 vbox2->addSpacing(5);
00245 vbox2->addWidget(sep);
00246 vbox2->addSpacing(5);
00247 vbox2->addLayout(gbox22);
00248 vbox2->addStretch();
00249
00250 connect(logUpdate,SIGNAL(toggled(bool)),this,SLOT(slotLogProcessToggleUpdate(bool)));
00251 connect(logSave,SIGNAL(clicked()),this,SLOT(slotLogSave()));
00252 connect(logCopy,SIGNAL(clicked()),this,SLOT(slotLogCopy()));
00253 connect(logClear,SIGNAL(clicked()),this,SLOT(slotLogClear()));
00254 connect(logSearch,SIGNAL(clicked()),this,SLOT(slotLogSearch()));
00255 connect(logResetSearch,SIGNAL(clicked()),this,SLOT(slotLogResetSearch()));
00256
00257
00258
00259 // "Configuration" tab
00260 tabConfig = new QWidget(this);
00261 tab->addTab(tabConfig,i18n("Configuration"));
00262 QWhatsThis::add(tabConfig, i18n(
00263 "<qml>Here you can configure parameteres for "
00264 "Pureftpd Statistics KDE module. You may want to "
00265 "modify default values if you have unsual configuration "
00266 "or your machine is powerfull enough.</qml>"
00267 ));
00268 QVBoxLayout *vbox3 = new QVBoxLayout(tabConfig,5,5);
00269 QButtonGroup *grpInfoConf = new QButtonGroup(i18n(" FTP Sessions Display Settings "),tabConfig);
00270 QGridLayout *gbox31 = new QGridLayout(grpInfoConf,7,3,5);
00271
00272 QLabel *txtUpdateInterval = new QLabel(i18n("&Update interval:"),grpInfoConf);
00273 updateInterval = new KIntNumInput(grpInfoConf);
00274 updateInterval->setRange(1,10000,1,false);
00275 updateInterval->setSuffix(i18n("seconds"," sec"));
00276 txtUpdateInterval->setBuddy(updateInterval);
00277 QLabel *txtInfoChoose = new QLabel(i18n("Choose information source:"),grpInfoConf);
00278 rbInfoDefault = new QRadioButton(i18n("Run pure-ftp&who"),grpInfoConf);
00279 pureftpwhoDefault = new QCheckBox(i18n("Use s&etting from \"PureFTPd Configuration\" module"), grpInfoConf);
00280 txtPureftpwhoPath = new QLabel(i18n("Pure-ftpwho Path:"),grpInfoConf);
00281 pureftpwhoPath = new KURLRequester("",grpInfoConf);
00282 txtPureftpwhoPath->setBuddy(pureftpwhoPath);
00283 #if KDE_VERSION > 300
00284 pureftpwhoPath->setMode(KFile::File);
00285 #endif
00286 rbInfoCustom = new QRadioButton(i18n("&Run custom command"),grpInfoConf);
00287 txtInfoCommand = new QLabel(i18n("Command Line:"),grpInfoConf);
00288 infoCommand = new KLineEdit(grpInfoConf);
00289 txtInfoCommand->setBuddy(infoCommand);
00290
00291 gbox31->addRowSpacing(0,grpInfoConf->fontMetrics().height());
00292 gbox31->addColSpacing(0,20);
00293 gbox31->addMultiCellWidget(txtUpdateInterval,1,1,0,1,Qt::AlignLeft);
00294 gbox31->addWidget(updateInterval,1,2,Qt::AlignLeft);
00295 gbox31->addMultiCellWidget(txtInfoChoose,2,2,0,2);
00296 gbox31->addMultiCellWidget(rbInfoDefault,3,3,0,2);
00297 gbox31->addMultiCellWidget(pureftpwhoDefault,4,4,1,2);
00298 gbox31->addWidget(txtPureftpwhoPath,5,1);
00299 gbox31->addWidget(pureftpwhoPath,5,2);
00300 gbox31->addMultiCellWidget(rbInfoCustom,6,6,0,2);
00301 gbox31->addWidget(txtInfoCommand,7,1);
00302 gbox31->addWidget(infoCommand,7,2);
00303
00304 QButtonGroup *grpLogConf = new QButtonGroup(i18n(" Log Display Settings "),tabConfig);
00305 QGridLayout *gbox32 = new QGridLayout(grpLogConf,7,3,5);
00306
00307 QLabel *txtHistoryLines = new QLabel(i18n("&Number of &history lines:"),grpLogConf);
00308 historyLines = new KIntNumInput(grpLogConf);
00309 historyLines->setRange(1,30000,1,false);
00310 txtHistoryLines->setBuddy(historyLines);
00311 QLabel *txtLogChoose = new QLabel(i18n("Choose logging method:"),grpLogConf);
00312 rbLogFile = new QRadioButton(i18n("D&isplay log file"),grpLogConf);
00313 txtLogFileName = new QLabel(i18n("Log Filename:"),grpLogConf);
00314 logFileName = new KURLRequester("",grpLogConf);
00315 #if KDE_VERSION > 300
00316 logFileName->setMode(KFile::File);
00317 #endif
00318 txtLogFileName->setBuddy(logFileName);
00319 rbLogCustom = new QRadioButton(i18n("Run cu&stom command"),grpLogConf);
00320 txtLogCommand = new QLabel(i18n("Log Command:"),grpLogConf);
00321 logCommand = new KLineEdit(grpLogConf);
00322 txtLogCommand->setBuddy(logCommand);
00323
00324 gbox32->addRowSpacing(0,grpLogConf->fontMetrics().height());
00325 gbox32->addColSpacing(0,20);
00326 gbox32->addMultiCellWidget(txtHistoryLines,1,1,0,1);
00327 gbox32->addWidget(historyLines,1,2,Qt::AlignLeft);
00328 gbox32->addMultiCellWidget(txtLogChoose,2,2,0,2);
00329 gbox32->addMultiCellWidget(rbLogFile,3,3,0,2);
00330 gbox32->addWidget(txtLogFileName,4,1);
00331 gbox32->addWidget(logFileName,4,2);
00332 gbox32->addMultiCellWidget(rbLogCustom,5,5,0,2);
00333 gbox32->addWidget(txtLogCommand,6,1);
00334 gbox32->addWidget(logCommand,6,2);
00335
00336 rbInfoDefault->setChecked(true);
00337 pureftpwhoDefault->setChecked(true);
00338 txtPureftpwhoPath->setEnabled(false);
00339 pureftpwhoPath->setEnabled(false);
00340 txtInfoCommand->setEnabled(false);
00341 infoCommand->setEnabled(false);
00342 rbLogFile->setChecked(true);
00343 txtLogCommand->setEnabled(false);
00344 logCommand->setEnabled(false);
00345
00346 vbox3->addWidget(grpInfoConf);
00347 vbox3->addSpacing(5);
00348 vbox3->addWidget(grpLogConf);
00349 vbox3->addStretch();
00350
00351 connect(updateInterval,SIGNAL(valueChanged(int)),this,SLOT(slotChangedInterval(int)));
00352 connect(rbInfoDefault,SIGNAL(toggled(bool)),this,SLOT(slotInfoConfDefault(bool)));
00353 connect(rbLogFile,SIGNAL(toggled(bool)),this,SLOT(slotLogConfDefault(bool)));
00354 connect(pureftpwhoDefault,SIGNAL(toggled(bool)),this,SLOT(slotInfoConfUseDefault(bool)));
00355 }
00356
00357
00358 void KPureftpdStat::displayInfoMessage(InfoMessage t) {
00359 switch (t) {
00360 case InfoInit:
00361 mesgInfoIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00362 "messagebox_info",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00363 break;
00364 case InfoExecCommandKill:
00365 case InfoExecRunning:
00366 case InfoWarning:
00367 mesgInfoIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00368 "messagebox_warning",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00369 break;
00370 case InfoExecCommandError:
00371 mesgInfoIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00372 "messagebox_critical",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00373 break;
00374 case InfoClear:
00375 default:
00376 mesgInfoIcon->setPixmap(QPixmap());
00377 }
00378
00379 switch (t) {
00380 case InfoClear:
00381 mesgInfoText->setText("");
00382 break;
00383 case InfoInit:
00384 mesgInfoText->setText(i18n(
00385 "<qml>Press <b>Continuos Update</b> button to view "
00386 "FTP connections to your PureFTPd server. Depress the "
00387 "button to freeze view on current state.</qml>"
00388 ));
00389 break;
00390 case InfoWarning:
00391 break;
00392 case InfoExecRunning:
00393 mesgInfoText->setText(i18n(
00394 "<qml>The process for FTP connection displaying "
00395 "have been locked, timed out or took to long to process. Please "
00396 "try to increase the update interval or ask your system administrator "
00397 "to investigate the issue.</qml>"
00398 ));
00399 break;
00400 case InfoExecCommandError:
00401 mesgInfoText->setText(i18n(
00402 "<qml>There was an error executing FTP info grabbing command. "
00403 "Check if this error is temporary or permanent, then "
00404 "contact your system administrator.</qml>"
00405 ));
00406 break;
00407 case InfoExecCommandKill:
00408 mesgInfoText->setText(i18n(
00409 "<qml>The info grabbing process has been forced to stop "
00410 "because there's more time needed for FTP sessions processing "
00411 "than time interval between updates.</qml>"
00412 ));
00413 break;
00414 default:
00415 kdWarning() << __FUNCTION__ << "(): unknown message display type t=" << t << endl;
00416 }
00417 }
00418
00419 void KPureftpdStat::displayLogMessage(LogMessage t) {
00420 switch (t) {
00421 case LogInit:
00422 case LogFull:
00423 mesgLogIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00424 "messagebox_info",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00425 break;
00426 case LogWriteError:
00427 case LogExecTerminated:
00428 mesgLogIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00429 "messagebox_warning",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00430 break;
00431 case LogExecTailError:
00432 case LogExecCommandError:
00433 mesgLogIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00434 "messagebox_critical",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00435 break;
00436 case LogClear:
00437 default:
00438 mesgLogIcon->setPixmap(QPixmap());
00439 }
00440
00441 switch (t) {
00442 case LogClear:
00443 mesgLogText->setText("");
00444 break;
00445 case LogInit:
00446 mesgLogText->setText(i18n(
00447 "<qml>Press <b>Continuos Update</b> button to view "
00448 "PureFTPd server log file in real-time. Depress the "
00449 "button to freeze view on current state.</qml>"
00450 ));
00451 break;
00452 case LogWriteError:
00453 mesgLogText->setText(i18n(
00454 "<qt>You don't have permission to write the log "
00455 "file here or some serious write error "
00456 "happened.<p>Please verify and try again.</qt>"));
00457 break;
00458 case LogExecTailError:
00459 mesgLogText->setText(i18n(
00460 "<qt>There was an error executing UNIX <b>tail</b> "
00461 "process. Please verify if you have permissions executing "
00462 "it and if it's accessible from environment variable "
00463 "<tt>PATH</tt>.</qt>"));
00464 break;
00465 case LogExecCommandError:
00466 mesgLogText->setText(i18n(
00467 "<qt>There was an error running command line "
00468 "for log reading. Please verify if you have "
00469 "all necessary permissions or if there's an error "
00470 "in command line.</qt>"));
00471 break;
00472 case LogExecTerminated:
00473 mesgLogText->setText(i18n(
00474 "<qt>The UNIX process for reading log file "
00475 "has terminated or has been killed. Check "
00476 "the logging command line.</qt>"));
00477 break;
00478 case LogFull:
00479 mesgLogText->setText(i18n(
00480 "<qt>The maximum number of logged lines "
00481 "has been reached. Please press <b>Clear</b> "
00482 "button to be able to start logging again. "
00483 "If you want more lines logged increase the "
00484 "\"Number of history lines\" counter in "
00485 "<b>Configuration</b> tab.</qt>"));
00486 break;
00487 default:
00488 kdWarning() << __FUNCTION__ << "(): unknown message display type t=" << t << endl;
00489 }
00490 }
00491
00492
00493 //---------------------- SLOTS ---------------------//
00494 void KPureftpdStat::configChanged() {
00495 emit changed(true);
00496 }
00497
00498 void KPureftpdStat::configChanged(const QString &text) {
00499 QString dummy=text;
00500 configChanged();
00501 }
00502
00503 void KPureftpdStat::configChanged(int number) {
00504 int dummy;
00505 dummy=number;
00506 configChanged();
00507 }
00508
00509 // "Log" tab
00510 void KPureftpdStat::slotLogSearch() {
00511 int dummy = (!findBackwards->isChecked()) ? 0 : INT_MAX;
00512 if (!mFound) {
00513 mFound=!logOutput->find(editSearch->text(),caseSensitive->isChecked(),wholeWords->isChecked(),
00514 !findBackwards->isChecked());
00515 } else {
00516 mFound=!logOutput->find(editSearch->text(),caseSensitive->isChecked(),wholeWords->isChecked(),
00517 !findBackwards->isChecked(),&dummy,&dummy);
00518 }
00519 }
00520
00521 void KPureftpdStat::slotLogResetSearch() {
00522 mFound=false;
00523 logOutput->setCursorPosition(0,0,false);
00524 }
00525
00526
00527 void KPureftpdStat::slotLogSave() {
00528 displayLogMessage(LogClear);
00529
00530 KURL urlName = KFileDialog::getSaveURL(startDir+"/"+fileName,
00531 i18n("*.log|Log Files\n"
00532 "*.txt|Text Files\n"
00533 "*|All Files"),0,
00534 i18n("Save Log Output"));
00535 if (!urlName.isEmpty()) {
00536 startDir = urlName.directory(true,true);
00537 fileName = urlName.filename();
00538 if (!fileName.isEmpty()) {
00539 QFile f(startDir+"/"+fileName);
00540 if (f.open(IO_WriteOnly)) {
00541 QTextStream t(&f);
00542 t << logOutput->text();
00543 f.close();
00544 } else {
00545 displayLogMessage(LogWriteError);
00546 }
00547 }
00548 }
00549
00550 config->setGroup("Log Tab");
00551 config->writeEntry("Log Saving Directory",startDir);
00552 config->writeEntry("Log FileName",fileName);
00553 config->sync();
00554 }
00555
00556 void KPureftpdStat::slotLogCopy() {
00557 displayLogMessage(LogClear);
00558 QApplication::clipboard()->setText(logOutput->text());
00559 }
00560
00561 void KPureftpdStat::slotLogClear() {
00562 displayLogMessage(LogClear);
00563 logOutput->clear();
00564 logUpdate->setEnabled(true);
00565 }
00566
00567
00568 void KPureftpdStat::slotLogProcessToggleUpdate(bool toggled) {
00569 if (toggled) {
00570 displayLogMessage(LogClear);
00571 startLogProcess();
00572 } else {
00573 stopLogProcess();
00574 logOutput->append(i18n("---- Stopped ----"));
00575 }
00576 }
00577
00578
00579 void KPureftpdStat::startLogProcess()
00580 {
00581 if (logProcess->isRunning()) {
00582 kdWarning() << __FUNCTION__ << "(): the log process is already running" << endl;
00583 return;
00584 }
00585
00586 tmpStdout=QString::null;
00587 tmpStderr=QString::null;
00588 logProcess->clearArguments();
00589 if (rbLogFile->isChecked()) {
00590 *logProcess << "tail" << " -n 1 -f " << KShellProcess::quote(logFileName->url());
00591 } else {
00592 *logProcess << logCommand->text().stripWhiteSpace();
00593 }
00594
00595 bool started=logProcess->start(KProcess::NotifyOnExit,KProcess::AllOutput);
00596
00597 if (started) {
00598 reachedMaxNumLines=false;
00599 logMaxNumLines=historyLines->value();
00600 } else {
00601 if (rbLogFile->isChecked()) {
00602 displayLogMessage(LogExecTailError);
00603 } else {
00604 displayLogMessage(LogExecCommandError);
00605 }
00606 logUpdate->setOn(false);
00607 }
00608 }
00609
00610
00611 void KPureftpdStat::stopLogProcess()
00612 {
00613 int countdown=2000;
00614
00615 logProcess->closeStdout();
00616 logProcess->closeStderr();
00617 if (logProcess->isRunning()) {
00618 logProcess->kill(SIGKILL);
00619 while (countdown && logProcess->isRunning()) {
00620 kapp->processEvents();
00621 usleep(200000);
00622 countdown--;
00623 }
00624 if (countdown==0) {
00625 kdWarning() << __FUNCTION__ << "(): The logging process has not exited! pid=" << logProcess->pid() << endl;
00626 }
00627 }
00628 }
00629
00630
00631 void KPureftpdStat::slotLogProcessRecvStdout(KProcess *p, char *buf, int len) {
00632 KProcess *dummy;
00633 dummy=p;
00634
00635 QString m_buf = tmpStdout + QString::fromLatin1(buf,len);
00636 int pos = m_buf.findRev("\n");
00637 if (pos == (int) m_buf.length()-1) {
00638 logOutput->append(m_buf.left(pos));
00639 tmpStdout=QString::null;
00640 } else if (pos == -1) {
00641 tmpStdout=m_buf;
00642 } else {
00643 logOutput->append(m_buf.left(pos));
00644 tmpStdout=m_buf.mid(pos+1);
00645 }
00646
00647 if (logOutput->numLines()>=logMaxNumLines) {
00648 reachedMaxNumLines=true;
00649 // flush the line buffer
00650 if (pos == -1) {
00651 logOutput->append(tmpStdout);
00652 }
00653 displayLogMessage(LogFull);
00654 logUpdate->setEnabled(false);
00655 logUpdate->setOn(false);
00656 return;
00657 }
00658 }
00659
00660 void KPureftpdStat::slotLogProcessRecvStderr(KProcess *p, char *buf, int len) {
00661 KProcess *dummy;
00662 dummy=p;
00663
00664 QString m_buf = tmpStderr+QString::fromLatin1(buf,len);
00665 int pos = m_buf.findRev("\n");
00666 if (pos == (int) (m_buf.length()-1)) {
00667 logOutput->append(m_buf.left(pos));
00668 tmpStderr=QString::null;
00669 } else if (pos == -1) {
00670 tmpStderr=m_buf;
00671 } else {
00672 logOutput->append(m_buf.left(pos));
00673 tmpStderr=m_buf.mid(pos+1);
00674 }
00675
00676 if (logOutput->numLines()>=logMaxNumLines) {
00677 reachedMaxNumLines=true;
00678 // flush the line buffer
00679 if (pos == -1) {
00680 logOutput->append(tmpStderr);
00681 }
00682 displayLogMessage(LogFull);
00683 logUpdate->setEnabled(false);
00684 logUpdate->setOn(false);
00685 return;
00686 }
00687 }
00688
00689 void KPureftpdStat::slotLogProcessExited(KProcess *p) {
00690 if (!reachedMaxNumLines) {
00691 if (p->normalExit() && ! p->exitStatus()) {
00692 displayLogMessage(LogExecTerminated);
00693 } else {
00694 if (logUpdate->isOn()) {
00695 displayLogMessage(LogExecCommandError);
00696 }
00697 }
00698 }
00699 if (logUpdate->isOn()) {
00700 logUpdate->setOn(false);
00701 }
00702 }
00703
00704
00705 // "Info" tab
00706 void KPureftpdStat::slotInfoProcessToggleUpdate() {
00707 if (infoUpdate->isOn()) {
00708 txtExtInfo->setText("");
00709 ftpSessionMap.clear();
00710 ftpGuiMap.clear();
00711 connList->clear();
00712 txtExtInfo->setPaper(QBrush(qApp->palette().active().base()));
00713 displayInfoMessage(InfoClear);
00714 pureftpwhoExe=pureftpwhoPath->url();
00715 startInfoProcess();
00716 infoTimer->start(1000*updateInterval->value());
00717 } else {
00718 deliberatedKill=true;
00719 infoTimer->stop();
00720 stopInfoProcess();
00721 }
00722 }
00723
00724 void KPureftpdStat::startInfoProcess() {
00725 if (isProcessingInfo) {
00726 displayInfoMessage(InfoExecRunning);
00727 } else {
00728 isProcessingInfo=true;
00729 infoProcess->clearArguments();
00730 if (rbInfoDefault->isChecked()) {
00731 if (pureftpwhoDefault->isChecked()) {
00732 *infoProcess << pureftpwhoDefaultPath << "-x";
00733 } else {
00734 *infoProcess << pureftpwhoExe << "-x";
00735 }
00736 } else {
00737 *infoProcess << infoCommand->text().stripWhiteSpace();
00738 }
00739
00740 bool started = infoProcess->start(KProcess::NotifyOnExit,KProcess::AllOutput);
00741
00742 if (started) {
00743 deliberatedKill=false;
00744 infoOutput = QString::null;
00745 } else {
00746 infoUpdate->setOn(false);
00747 displayInfoMessage(InfoExecCommandError);
00748 }
00749 }
00750 }
00751
00752 void KPureftpdStat::stopInfoProcess() {
00753 int countdown=2000;
00754
00755 infoProcess->closeStdout();
00756 infoProcess->closeStderr();
00757 if (infoProcess->isRunning()) {
00758 infoProcess->kill(SIGKILL);
00759 while (countdown && infoProcess->isRunning()) {
00760 kapp->processEvents();
00761 usleep(200000);
00762 countdown--;
00763 }
00764 if (countdown==0) {
00765 kdWarning() << __FUNCTION__ << "(): The info process has not exited! pid=" << infoProcess->pid() << endl;
00766 }
00767 }
00768 }
00769
00770
00771 void KPureftpdStat::slotInfoProcessRecvStdout(KProcess *p, char *buf, int len) {
00772 KProcess *dummy_p;
00773 int dummy_len;
00774
00775 dummy_p=p;
00776 dummy_len=len;
00777 infoOutput.append(buf);
00778 }
00779
00780 void KPureftpdStat::slotInfoProcessRecvStderr(KProcess *p, char *buf, int len) {
00781 KProcess *dummy_p;
00782 int dummy_len;
00783 char *dummy_buf;
00784
00785 dummy_p=p;
00786 dummy_len=len;
00787 dummy_buf=buf;
00788
00789 // nothing usable do with STDERR for the moment
00790 }
00791
00792 void KPureftpdStat::slotInfoProcessExited(KProcess *p) {
00793 KProcess *dummy;
00794 dummy=p;
00795
00796 if (infoProcess->normalExit()) {
00797 // infoProcess terminated its execution
00798 if (infoProcess->exitStatus()) {
00799 // terminated with some error
00800 displayInfoMessage(InfoExecCommandError);
00801 if (infoTimer->isActive()) {
00802 infoTimer->stop();
00803 }
00804 infoUpdate->setOn(false);
00805 } else {
00806 // terminated OK, so process the received data
00807 processInfoOutput();
00808 }
00809 } else {
00810 // infoProcess was killed
00811 if (! deliberatedKill) {
00812 displayInfoMessage(InfoExecCommandKill);
00813 }
00814 }
00815 isProcessingInfo=false;
00816 }
00817
00818 QString KPureftpdStat::prettyByte(unsigned long long m_byte) {
00819 QString ext;
00820
00821 if (m_byte==1) return i18n("1 Byte");
00822 if (m_byte==0) return i18n("0 Bytes");
00823 if (m_byte >= 1024) {
00824 double m_kbyte = m_byte / 1024.0;
00825 if (m_kbyte >= 1024) {
00826 double m_mbyte = m_kbyte / 1024.0;
00827 if (m_mbyte >= 1024) {
00828 double m_gbyte = m_mbyte / 1024.0;
00829 QString s_gbyte;
00830 s_gbyte.sprintf("%4.2f",m_gbyte);
00831 return i18n("%1 GBytes").arg(s_gbyte);
00832 } else {
00833 QString s_mbyte;
00834 s_mbyte.sprintf("%4.2f",m_mbyte);
00835 return i18n("%1 MBytes").arg(s_mbyte);
00836 }
00837 } else {
00838 QString s_kbyte;
00839 s_kbyte.sprintf("%4.2f",m_kbyte);
00840 return i18n("%1 KBytes").arg(s_kbyte);
00841 }
00842 } else {
00843 return i18n("%1 Bytes").arg((unsigned long)m_byte);
00844 }
00845 return QString::null;
00846 }
00847
00848 void KPureftpdStat::slotShowExtendedInfo(QListViewItem *item) {
00849 if (!item) return;
00850
00851 FTPSessionItem f;
00852 bool itemFound=false;
00853
00854 for (FtpGuiMap::Iterator it=ftpGuiMap.begin(); it!=ftpGuiMap.end(); ++it) {
00855 if (*it == item) {
00856 f=ftpSessionMap[it.key()];
00857 itemFound=true;
00858 break;
00859 }
00860 }
00861
00862 if (!itemFound) {
00863 kdWarning() << __FUNCTION__ << "(): clicked QListViewItem was not found in ftpGuiMap! ptr=" << item << endl;
00864 return;
00865 }
00866
00867 txtExtInfo->setPaper(QBrush(kapp->palette().active().base()));
00868 switch (f.state()) {
00869 case FTPSessionItem::Idle:
00870 txtExtInfo->setText(i18n(
00871 "<qml><b>Local Host:</b> %1:%2<br>"
00872 "<b>Remote Host:</b> %3<br>"
00873 "</qml>"
00874 ).arg(f.localhost()).arg(f.port()).arg(f.host()));
00875 break;
00876 case FTPSessionItem::Error:
00877 txtExtInfo->setText(i18n(
00878 "<qml>There is an FTP error on this connection. In short "
00879 "time connection should close.</qml>"
00880 ));
00881 break;
00882 case FTPSessionItem::Download:
00883 case FTPSessionItem::Upload:
00884 txtExtInfo->setText(i18n(
00885 "<qml><b>File:</b> %1<br>"
00886 "<b>Local Host:</b> %2:%3 <b>Remote Host:</b> %4<br>"
00887 "<b>Current Size:</b> %5 of %6 (resumed at %7)<br>"
00888 "<b>Bandwidth:</b> %8/s<br>"
00889 "</qml>"
00890 ).arg(f.file()).arg(f.localhost()).arg(f.port()).arg(f.host())
00891 .arg(prettyByte(f.current_size())).arg(prettyByte(f.total_size()))
00892 .arg(prettyByte(f.resume())).arg(prettyByte(f.bandwidth())));
00893 break;
00894 case FTPSessionItem::Unknown:
00895 txtExtInfo->setText(i18n(
00896 "<qml>Unknown FTP session state. There may be incompatibility "
00897 "between <b>pure-ftpd</b> and this application.</qml>"
00898 ));
00899 break;
00900 default:
00901 kdWarning() << __FUNCTION__ << "(): Unknown FTP session state=" << f.state() << endl;
00902 }
00903
00904 }
00905
00906
00907 void KPureftpdStat::processInfoOutput() {
00908 FtpSessionMap tmp_ftpSessionMap;
00909 FTPSessionItem::Status attr_state;
00910 pid_t attr_pid;
00911 int attr_percentage;
00912 unsigned long attr_time, attr_bandwidth;
00913 unsigned long long attr_resume, attr_current_size, attr_total_size;
00914 QString tmp, attr_account, attr_file, attr_host, attr_localhost, attr_port;
00915 QDomDocument doc;
00916 KListViewItem *item;
00917
00918
00919 doc.setContent(infoOutput);
00920 QDomElement docElem0 = doc.documentElement();
00921 QDomNode n = docElem0.firstChild();
00922
00923 while (!n.isNull()) {
00924 QDomElement docElem = n.toElement();
00925 if (!docElem.isNull()) {
00926 tmp = docElem.attribute("state","");
00927 if (tmp == "IDLE") {
00928 attr_state = FTPSessionItem::Idle;
00929 } else if (tmp == "DOWNLOAD" || tmp == " DL ") {
00930 attr_state = FTPSessionItem::Download;
00931 } else if (tmp == "UPLOAD" || tmp == " UL ") {
00932 attr_state = FTPSessionItem::Upload;
00933 } else if (tmp == "ERROR" || tmp == "ERR!") {
00934 attr_state = FTPSessionItem::Error;
00935 } else {
00936 attr_state = FTPSessionItem::Unknown;
00937 }
00938 attr_account = docElem.attribute("account","");
00939 attr_file = docElem.attribute("file","");
00940 attr_host = docElem.attribute("host","");
00941 attr_localhost = docElem.attribute("localhost","");
00942 attr_port = docElem.attribute("localport","");
00943 tmp = docElem.attribute("resume","0");
00944 attr_resume = tmp.toULong();
00945 tmp = docElem.attribute("current_size","0");
00946 attr_current_size = tmp.toULong();
00947 tmp = docElem.attribute("total_size","0");
00948 attr_total_size = tmp.toULong();
00949 tmp = docElem.attribute("time","0");
00950 attr_time = tmp.toULong();
00951 tmp = docElem.attribute("bandwidth","0");
00952 attr_bandwidth = tmp.toULong();
00953 tmp = docElem.attribute("percentage","0");
00954 attr_percentage = tmp.toULong();
00955 tmp = docElem.attribute("pid","0");
00956 attr_pid = tmp.toInt();
00957 FTPSessionItem ftpItem(attr_percentage, attr_pid, attr_state,
00958 attr_time, attr_bandwidth,
00959 attr_resume, attr_current_size, attr_total_size,
00960 attr_account, attr_file, attr_host,
00961 attr_localhost, attr_port);
00962 tmp_ftpSessionMap[attr_pid]=ftpItem;
00963 }
00964 n = n.nextSibling();
00965 }
00966
00967 // first, remove the items which are no longer
00968 FtpSessionMap::Iterator it=ftpSessionMap.begin();
00969 while (it != ftpSessionMap.end()) {
00970 if (!tmp_ftpSessionMap.contains(it.key())) {
00971 delete ftpGuiMap[it.key()];
00972 ftpGuiMap.remove(it.key());
00973 ftpSessionMap.remove(it);
00974 it=ftpSessionMap.begin();
00975 } else {
00976 ++it;
00977 }
00978 }
00979
00980 // second, add the new elements & update the current ones
00981 for (FtpSessionMap::Iterator it=tmp_ftpSessionMap.begin(); it!=tmp_ftpSessionMap.end(); ++it) {
00982 QString tmp_state;
00983 switch ((*it).state()) {
00984 case FTPSessionItem::Idle:
00985 tmp_state = i18n("ftp state","Idle");
00986 break;
00987 case FTPSessionItem::Download:
00988 tmp_state = i18n("ftp state","Download");
00989 break;
00990 case FTPSessionItem::Upload:
00991 tmp_state = i18n("ftp state","Upload");
00992 break;
00993 case FTPSessionItem::Error:
00994 tmp_state = i18n("ftp state","Error");
00995 break;
00996 default:
00997 tmp_state = i18n("ftp state","Unknown");
00998 }
00999 long int total_sec = (*it).time();
01000 int m_hour = (int) total_sec / 3600;
01001 int m_min = (int) (total_sec - m_hour * 3600) / 60;
01002 int m_sec = total_sec % 60;
01003 QString m_time;
01004 m_time.sprintf("%d:%02d:%02d",m_hour,m_min,m_sec);
01005
01006 if (!ftpSessionMap.contains(it.key())) {
01007 // add new element
01008 item = new KListViewItem(connList,(*it).account(),tmp_state,m_time,QString::number((*it).percentage())+"%",(*it).file());
01009 ftpGuiMap[it.key()]=item;
01010 } else {
01011 // update the old one with current data
01012 ftpGuiMap[it.key()]->setText(0,(*it).account());
01013 ftpGuiMap[it.key()]->setText(1,tmp_state);
01014 ftpGuiMap[it.key()]->setText(2,m_time);
01015 ftpGuiMap[it.key()]->setText(3,QString::number((*it).percentage())+"%");
01016 ftpGuiMap[it.key()]->setText(4,(*it).file());
01017 }
01018 ftpSessionMap[it.key()]=tmp_ftpSessionMap[it.key()];
01019 }
01020
01021 bool ftpSessionIsActive=false;
01022 for (FtpGuiMap::Iterator it=ftpGuiMap.begin(); it!=ftpGuiMap.end(); ++it) {
01023 if (connList->isSelected(*it)) {
01024 slotShowExtendedInfo(*it);
01025 ftpSessionIsActive=true;
01026 }
01027 }
01028 if (ftpSessionIsActive) {
01029 txtExtInfo->setPaper(QBrush(kapp->palette().active().base()));
01030 } else {
01031 txtExtInfo->setPaper(QBrush(kapp->palette().active().background()));
01032 }
01033 }
01034
01035
01036 void KPureftpdStat::slotChangedInterval(int interval) {
01037 if (infoTimer->isActive()) {
01038 infoTimer->changeInterval(1000*interval);
01039 }
01040 }
01041
01042
01043 // "Configuration" tab
01044 void KPureftpdStat::slotInfoConfDefault(bool b) {
01045 pureftpwhoDefault->setEnabled(b);
01046 pureftpwhoPath->setEnabled(b && !pureftpwhoDefault->isChecked());
01047 txtPureftpwhoPath->setEnabled(b && !pureftpwhoDefault->isChecked());
01048 txtInfoCommand->setEnabled(!b);
01049 infoCommand->setEnabled(!b);
01050 }
01051
01052 void KPureftpdStat::slotInfoConfUseDefault(bool b) {
01053 txtPureftpwhoPath->setEnabled(!b);
01054 pureftpwhoPath->setEnabled(!b);
01055 }
01056
01057 void KPureftpdStat::slotLogConfDefault(bool b) {
01058 logFileName->setEnabled(b);
01059 txtLogFileName->setEnabled(b);
01060 logCommand->setEnabled(!b);
01061 txtLogCommand->setEnabled(!b);
01062 }
01063
01064
01065
01066 // KCMModule usual stuff
01067
01068 void KPureftpdStat::load() {
01069 config->setGroup("Find");
01070 caseSensitive->setChecked(config->readBoolEntry("Case Sensitive",false));
01071 wholeWords->setChecked(config->readBoolEntry("Whole Words",false));
01072 findBackwards->setChecked(config->readBoolEntry("Find Backwards",false));
01073 editSearch->setText(config->readEntry("Search String",QString::null));
01074
01075 config->setGroup("Log Tab");
01076 startDir = config->readEntry("Log Saving Directory",QDir::currentDirPath());
01077 fileName = config->readEntry("Log Filename","pureftpd.log");
01078
01079 config->setGroup("Options");
01080 updateInterval->setValue(config->readUnsignedNumEntry("Info Update Interval",3));
01081 infoTimer->changeInterval(1000*updateInterval->value());
01082 infoTimer->stop();
01083
01084 historyLines->setValue(config->readUnsignedNumEntry("History Log Lines",500));
01085 logFileName->setURL(config->readEntry("Log FileName","/var/log/pureftpd.log"));
01086 pureftpwhoPath->setURL(config->readEntry("Pureftpwho Path","/usr/local/sbin/pure-ftpwho"));
01087 infoCommand->setText(config->readEntry("Custom Info Command",QString::null));
01088 logCommand->setText(config->readEntry("Custom Log Command",QString::null));
01089 pureftpwhoDefault->setChecked(config->readBoolEntry("Use Default Pureftpwho",true));
01090 rbInfoDefault->setChecked(config->readBoolEntry("Use Pureftpwho",true));
01091 rbInfoCustom->setChecked(!config->readBoolEntry("Use Pureftpwho",true));
01092 rbLogFile->setChecked(config->readBoolEntry("Use Log File",true));
01093 rbLogCustom->setChecked(!config->readBoolEntry("Use Log File",true));
01094
01095 KConfig *tmp_config = new KConfig("kcmpureftpdrc",true,false);
01096 tmp_config->setGroup("Options");
01097 pureftpwhoDefaultPath=tmp_config->readEntry("Pureftpwho Path","/usr/local/sbin/pure-ftpwho");
01098 delete tmp_config;
01099
01100 emit changed(false);
01101 }
01102
01103 void KPureftpdStat::save() {
01104 config->setGroup("Find");
01105 config->writeEntry("Case Sensitive",caseSensitive->isChecked());
01106 config->writeEntry("Whole Words",wholeWords->isChecked());
01107 config->writeEntry("Find Backwards",findBackwards->isChecked());
01108 config->writeEntry("Search String",editSearch->text());
01109
01110 config->setGroup("Options");
01111 config->writeEntry("Info Update Interval",updateInterval->value());
01112 config->writeEntry("History Log Lines",historyLines->value());
01113 config->writeEntry("Log FileName",logFileName->url());
01114 config->writeEntry("Pureftpwho Path",pureftpwhoPath->url());
01115 config->writeEntry("Custom Info Command",infoCommand->text());
01116 config->writeEntry("Custom Log Command",logCommand->text());
01117 config->writeEntry("Use Default Pureftpwho",pureftpwhoDefault->isChecked());
01118 config->writeEntry("Use Pureftpwho",rbInfoDefault->isChecked());
01119 config->writeEntry("Use Log File",rbLogFile->isChecked());
01120
01121 config->sync();
01122 emit changed(false);
01123 }
01124
01125
01126 void KPureftpdStat::defaults() {
01127 load();
01128 emit changed(false);
01129 }
01130
01131 int KPureftpdStat::buttons() {
01132 return KCModule::Default | KCModule::Apply | KCModule::Help;
01133 }
01134
01135 QString KPureftpdStat::quickHelp() const {
01136 return i18n("<h1>PureFTPd Statistics</h1> <p>This module allow you to track statistics "
01137 "from <b>pure-ftpd</b> FTP server. You can see real time information about "
01138 "FTP connection on your FTP server as well you may follow information written "
01139 "to syslog by the server. <p>To obtain this high "
01140 "quality server go to <a href=\"http://www.pureftpd.org/\">http://www.pureftpd.org/</a>.</p>"
01141 );
01142 }
01143
01144 const KAboutData *KPureftpdStat::aboutData() const {
01145 KAboutData *myAboutData = new KAboutData(
01146 "kcmpureftpdstat", I18N_NOOP("KCM PureFtpd Statistics"),
01147 VERSION, I18N_NOOP("KControl module for PureFtpd Statistics"),
01148 KAboutData::License_GPL, "(c) 2002, 2003 Claudiu Costin",0,
01149 "http://www.ro.kde.org/kcmpureftpd/",
01150 "claudiuc@kde.org");
01151 myAboutData->addAuthor("Claudiu Costin",I18N_NOOP("Original author"),"claudiuc@kde.org");
01152 myAboutData->addCredit("Iuliana Costin",
01153 I18N_NOOP("My lovely wife who allowed me to spend countless hours in "
01154 "front of computer."),QString::null);
01155 myAboutData->addCredit("Frank Denis",
01156 I18N_NOOP("Pureftpd FTP server author. "
01157 "Many thanks for such great piece of code."),
01158 "j@pureftpd.org");
01159 return myAboutData;
01160 }
01161
01162 extern "C" {
01163 KCModule *create_pureftpdstat(QWidget *parent, const char *name) {
01164 QString dummy=name;
01165 KGlobal::locale()->insertCatalogue("kcmpureftpd");
01166 return new KPureftpdStat(parent,"kcmpureftpdstat");
01167 };
01168
01169 void init_pureftpdstat() {
01170 kapp->startServiceByDesktopName("kcmpureftpdstat");
01171 };
01172 }
01173
01174
Generated on Thu Jul 24 01:57:13 2003 by doxygen 1.2.15.
