Changeset 220bbd4


Ignore:
Timestamp:
09/17/13 08:51:30 (11 months ago)
Author:
Ken Moore <ken@…>
Branches:
master, 9.2-release, releng/10.0, releng/10.0.1, releng/10.0.2
Children:
04144d6
Parents:
6808980
Message:

Get the scrub/resilvering detection working for LPTray/LPWatcher. This is properly set for running/started/finished processes.

Location:
src-qt4/life-preserver
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src-qt4/life-preserver/LPTray.cpp

    rf698804 r220bbd4  
    33//PUBLIC 
    44LPTray::LPTray() : QSystemTrayIcon(){ 
    5   initPhase = true; //flag that we are in the startup process 
     5  //initPhase = true; //flag that we are in the startup process 
    66  //Start up the log file watcher and connect the signals/slots 
    77  watcher = new LPWatcher(); 
    88        connect(watcher,SIGNAL(MessageAvailable(QString)),this,SLOT(watcherMessage(QString)) ); 
    9          
    10   /*QString logfile = "/var/log/lpreserver/lpreserver.log"; 
    11   watcher = new QFileSystemWatcher(); 
    12         if(!QFile::exists(logfile)){  
    13           if(!QFile::exists("/var/log/lpreserver")){ system( "mkdir /var/log/lpreserver"); } 
    14           system( QString("touch "+logfile).toUtf8() );  
    15         } 
    16         watcher->addPath(logfile); 
    17   logFile = new QFile(logfile); 
    18         logFile->open(QIODevice::ReadOnly | QIODevice::Text); //open it now, for faster reading 
    19   LFStream = new QTextStream(logFile); 
    20         connect(watcher, SIGNAL(fileChanged(QString)),this,SLOT(slotNewLogMessage(QString)) ); //now connect the signal/slot 
    21         */ 
     9        connect(watcher,SIGNAL(StatusUpdated()),this,SLOT(watcherMessage()) ); 
    2210  //Setup the context menu 
    2311  menu = new QMenu; 
     
    2513        connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(slotClose()) ); 
    2614  this->setContextMenu(menu); 
    27   //Setup the animated icon timer 
    28   /* 
    29   timer = new QTimer(); 
    30         timer->setInterval(100); 
    31         connect(timer, SIGNAL(timeout()), this, SLOT(displayWorkingIcon()) ); 
    32   */ 
    3315  //Setup initial icon for the tray 
    3416  this->setIcon( QIcon(":/images/tray-icon-idle.png") ); 
     
    3719  //connect other signals/slots 
    3820  connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)) ); 
    39   //Make sure we check the latest line in the logfile 
    40   //QTimer::singleShot(1000, this,SLOT(firstCheck())); 
    4121  //Start up the watcher 
    4222  watcher->start(); 
     
    4626 
    4727LPTray::~LPTray(){ 
    48   //if(statFile != 0){ statFile->close(); } 
    49   //logFile->close(); 
    50   //delete statFile; 
    51   //delete logFile; 
    5228  watcher->stop(); 
    5329  delete watcher; 
    54   //delete menu; 
    55   //delete timer; 
    5630} 
    5731 
     
    5933//  PRIVATE FUNCTIONS 
    6034// =============== 
    61 /* 
    62 void LPTray::parseLogMessage(QString log, bool quiet){ 
    63   //Divide up the log into it's sections 
    64   QString timestamp = log.section(":",0,2).simplified(); 
    65   QString time = timestamp.section(" ",3,3).simplified(); 
    66   QString message = log.section(":",3,3).toLower().simplified(); 
    67   QString dev = log.section(":",4,4).simplified(); //dataset/snapshot/nothing 
    68   //Now decide what to do/show because of the log message 
    69   qDebug() << "New Log Message:" << log; 
    70   if(message.contains("creating snapshot")){ 
    71     dev = message.section(" ",-1).simplified(); 
    72     if(!quiet){ this->showMessage( time, QString(tr("Creating snapshot for %1")).arg(dev), QSystemTrayIcon::Information, 5000); } 
    73     //Just set the standard idle icon 
    74     this->setIcon( QIcon(":/images/tray-icon-idle.png") );    
    75     setIdleToolTip(); 
    76   }else if(message.contains("starting replication")){ 
    77     startWorkingIcon(); 
    78     //Setup the file watcher for this new log file 
    79     sFile = dev; 
    80     if(!sFile.isEmpty()){ 
    81       if(!QFile::exists(sFile)){ system( QString("touch "+sFile).toUtf8() ); } 
    82       statFile = new QFile(sFile); 
    83         statFile->open(QIODevice::ReadOnly | QIODevice::Text); 
    84         SFStream = new QTextStream(statFile); 
    85       watcher->addPath(sFile); //will update/set tooltips 
    86     } 
    87   }else if(message.contains("finished replication")){ 
    88     stopWorkingIcon(); 
    89     //Stop the file wather from watching the status file and clean up 
    90     if(!sFile.isEmpty()){ 
    91       watcher->removePath(sFile); 
    92           statFile->close(); 
    93           sFile.clear(); 
    94     } 
    95     //Clean up and show messages 
    96     repTotK.clear(); 
    97     setIdleToolTip(); 
    98     dev = message.section(" ",-1).simplified(); 
    99     if(!quiet){ this->showMessage( time, QString(tr("Finished replication for %1")).arg(dev), QSystemTrayIcon::Information, 5000); } 
    100   }else if( message.contains("FAILED replication") ){ 
    101     stopWorkingIcon(); 
    102     //Stop the file wather from watching the status file and clean up 
    103     if(!sFile.isEmpty()){ 
    104       watcher->removePath(sFile); 
    105           statFile->close(); 
    106           sFile.clear(); 
    107     } 
    108     //Clean up and show messages 
    109     repTotK.clear(); 
    110     dev = message.section(" ",-1).simplified(); 
    111     QString file = log.section("LOGFILE:",1,1).simplified(); 
    112     QString tt = QString(tr("%1: Replication Failed on %2")).arg(time,dev) +"\n"+ QString(tr("Logfile available at: %1")).arg(file); 
    113     this->setToolTip(tt);    
    114     if(!quiet){ this->showMessage( time, QString(tr("Replication Error for %1")).arg(dev), QSystemTrayIcon::Information, 5000); } 
    115     this->setIcon(QIcon(":/images/tray-icon-failed.png")); 
    116   }else{ 
    117     //Just set the standard idle icon 
    118     //this->setIcon( QIcon(":/images/tray-icon-idle.png") );     
    119   } 
    120   if(GUI->isVisible()){ 
    121     GUI->setupUI(); 
    122   } 
    123 } 
    124  
    125 void LPTray::parseStatusMessage(QString stat){ 
    126   qDebug() << "New Status Message:" << stat; 
    127   //Divide up the status message into sections 
    128   stat.replace("\t"," "); 
    129   QString dataset = stat.section(" ",2,2,QString::SectionSkipEmpty).section("/",0,0).simplified(); 
    130   QString cSize = stat.section(" ",1,1,QString::SectionSkipEmpty); 
    131   //Now Setup the tooltip 
    132   if(cSize != lastSize){ //don't update the tooltip if the same size info 
    133     QString percent; 
    134     if(!repTotK.isEmpty()){ 
    135       //calculate the percentage 
    136       double tot = displayToDoubleK(repTotK); 
    137       double c = displayToDoubleK(cSize); 
    138       if( tot!=-1 & c!=-1){ 
    139         double p = (c*100)/tot; 
    140         p = int(p*10)/10.0; //round to 1 decimel places 
    141         percent = QString::number(p) + "%"; 
    142       } 
    143     } 
    144     if(repTotK.isEmpty()){ repTotK = "??"; } 
    145     //Format the tooltip String 
    146     QString status = cSize+"/"+repTotK; 
    147     if(!percent.isEmpty()){ status.append(" ("+percent+")"); } 
    148     QString txt = QString(tr("Replicating %1: %2")).arg(dataset, status); 
    149     this->setToolTip(txt); 
    150     lastSize = cSize; //save the current size for later 
    151   } 
    152 } 
    153  
    154 void LPTray::setIdleToolTip(){ 
    155   //Get the last snapshot created 
    156   QStringList dsList = LPBackend::listDatasets(); 
    157   if(dsList.isEmpty()){ 
    158     this->setToolTip(tr("Automatic Snapshots Disabled")); 
    159   }else{ 
    160     //Grab the newest snapshot from each dataset 
    161     QString tt; //tooltip 
    162     for(int i=0; i<dsList.length(); i++){ 
    163       QStringList snaps = LPBackend::listLPSnapshots(dsList[0]); 
    164       if(!tt.isEmpty()){ tt.append("\n"); } //put each dataset on a new line 
    165       if(snaps.isEmpty()){ 
    166         tt.append( QString(tr("%1: No snapshots available")).arg(dsList[0]) ); 
    167       }else{ 
    168         tt.append( QString(tr("%1: Latest snapshot: %2")).arg(dsList[0],snaps[0]) ); 
    169       } 
    170     } 
    171     this->setToolTip(tt); 
    172   } 
    173          
    174 } 
    175  
    176 void LPTray::startWorkingIcon(){ 
    177   this->setIcon( QIcon(":/images/tray-icon-active7.png")); 
    178   //wNum = 1; //start on the first image 
    179   //timer->start(); 
    180 } 
    181  
    182 void LPTray::stopWorkingIcon(){ 
    183   //timer->stop(); 
    184   this->setIcon( QIcon(":/images/tray-icon-idle.png") );       
    185 } 
    186  
    187 double LPTray::displayToDoubleK(QString displayNumber){ 
    188   QStringList labels;  
    189     labels << "K" << "M" << "G" << "T" << "P" << "E"; 
    190   QString clab = displayNumber.right(1); //last character is the size label 
    191         displayNumber.chop(1); //remove the label from the number 
    192   double num = displayNumber.toDouble(); 
    193   //Now format the number properly 
    194   bool ok = false; 
    195   for(int i=0; i<labels.length(); i++){ 
    196     if(labels[i] == clab){ ok = true; break; } 
    197     else{ num = num*1024; } //get ready for the next size 
    198   } 
    199   if(!ok){ num = -1; } //could not determine the size 
    200   return num; 
    201 } 
    202 */ 
    203  
    20435void LPTray::updateTrayIcon(){ 
    20536  if( watcher->hasError() ){ 
     
    24980     
    25081  }else if(type=="critical"){ 
    251            
     82    info << "time" << "message" << "device"; 
     83    info = watcher->getMessages(type,info); 
     84    if(!info.isEmpty()){ 
     85      QString msg = QString(tr("Time: %1")).arg(info[0])+"\n"+QString(tr("Device: %1")).arg(info[2])+"\n"+QString(tr("Alert: %1")).arg(info[1]); 
     86      QString title = tr("System Alert"); 
     87      QMessageBox::warning(0, title ,msg); 
     88    } 
    25289  }else if(type=="mirror"){ 
    25390           
     91  }else if(type=="scrub" || type =="resilver"){ 
     92    info << "id" << "time" << "message"; 
     93    info = watcher->getMessages(type, info); 
     94    if(!info.isEmpty()){ 
     95      if(info[0]=="ERROR"){  
     96        this->showMessage(info[1], info[2], QSystemTrayIcon::Warning, 5000); 
     97      }else{  
     98        this->showMessage(info[1], info[2], QSystemTrayIcon::Information, 5000);  
     99      } 
     100    } 
    254101  } 
    255102  //Update the tray icon 
     
    258105  updateToolTip(); 
    259106} 
    260 /* 
    261 void LPTray::firstCheck(){ 
    262   slotNewLogMessage("/var/log/lpreserver/lpreserver.log"); 
    263   initPhase = false; //done with initializations 
    264 } 
    265107 
    266 void LPTray::slotNewLogMessage(QString file){ 
    267   //qDebug() << "New Log Message in file:" << file; 
    268   if(file == "/var/log/lpreserver/lpreserver.log"){ 
    269     //Backend Status Update 
    270     //Now parse the log lines and do stuff with it 
    271     while( !LFStream->atEnd() ){ parseLogMessage(LFStream->readLine(), initPhase); } 
    272   }else{ 
    273     //Replication status update 
    274       //get the last line from the file 
    275       QString stat; 
    276       while( !SFStream->atEnd() ){  
    277         QString line = SFStream->readLine();  
    278         if(line.contains("total estimated size")){ repTotK = line.section(" ",-1).simplified(); } //save the total size to replicate 
    279         else if(line.startsWith("send from ")){} 
    280         else if(line.startsWith("TIME ")){} 
    281         else{ stat = line; } //only save the relevant status line 
    282       } 
    283       //parse the status line 
    284       if(!stat.isEmpty()){ parseStatusMessage(stat); } 
    285   } 
    286 } 
    287 */ 
    288108void LPTray::slotTrayClicked(QSystemTrayIcon::ActivationReason reason){ 
    289109  if(reason == QSystemTrayIcon::Trigger){  
     
    314134    GUI->show(); 
    315135} 
    316  
    317 /*void LPTray::displayWorkingIcon(){ 
    318   QString ico = ":/images/tray-icon-active"+QString::number(wNum)+".png"; 
    319   this->setIcon(QIcon(ico)); 
    320   if(wNum == 16){ wNum = 1; } //go back to the beginning of the loop 
    321   else{ wNum++; } 
    322 }*/ 
  • src-qt4/life-preserver/LPTray.h

    rf698804 r220bbd4  
    44#include <QSystemTrayIcon> 
    55#include <QMenu> 
    6 #include <QFileSystemWatcher> 
     6//#include <QFileSystemWatcher> 
    77#include <QString> 
    8 #include <QTimer> 
    9 #include <QProcess> 
    10 #include <QFile> 
    11 #include <QTextStream> 
     8//#include <QTimer> 
     9//#include <QProcess> 
     10//#include <QFile> 
     11//#include <QTextStream> 
     12#include <QMessageBox> 
    1213 
    1314#include "mainUI.h" 
     
    2122 
    2223private: 
    23         //QFileSystemWatcher *watcher; 
    2424        LPWatcher *watcher; 
    2525        QMenu *menu; 
    26         //QTimer *timer; 
    2726        mainUI *GUI; 
    28         //QString sFile; //location of the replication status file 
    29         //QFile *logFile, *statFile; 
    30         //QTextStream *LFStream, *SFStream; 
    31         //QString repTotK, lastSize; 
    32         //int wNum; //internal tracking of which frame of the icon animation we are on 
    33         bool initPhase; 
     27        //bool initPhase; 
    3428 
    35         //void parseLogMessage(QString, bool quiet = false); 
    36         //void parseStatusMessage(QString); 
    37         //void setIdleToolTip(); 
    38         //void startWorkingIcon(); 
    39         //void stopWorkingIcon(); 
    40         //double displayToDoubleK(QString); 
    4129 
    4230        void updateTrayIcon(); 
     
    4432         
    4533private slots: 
    46         void watcherMessage(QString); 
    47         //void firstCheck(); 
    48         //void slotNewLogMessage(QString); 
     34        void watcherMessage(QString type = ""); 
     35 
    4936        void slotTrayClicked(QSystemTrayIcon::ActivationReason); 
    5037        void slotClose(); 
    5138        void slotSingleInstance(); 
    5239        void startGUI(); 
    53         //void displayWorkingIcon(); 
     40 
    5441}; 
    5542 
  • src-qt4/life-preserver/LPWatcher.cpp

    r23f66b8 r220bbd4  
    77    "critical" status: 30-39 
    88    "mirror" status: 40-49 
    9     "resilvering" status: 50-59 
     9    "resilver" status: 50-59 
    1010    "scrub" status: 60-69 
    1111  Within each set: 
    1212    *0 = ID Code (for internal identification as necessary) 
    13     *1 = dataset (example: tank1) 
     13    *1 = zpool (example: tank1) 
    1414    *2 = summary (shortened version of the message - tooltips) 
    1515    *3 = message (full message) 
     
    3131  FILE_ERROR="/var/log/lpreserver/error.log"; 
    3232  FILE_REPLICATION=""; //this is set automatically based on the log file outputs 
    33  
     33  sysCheckTime = 300000; // 5 minutes 
    3434  //initialize the watcher and timer 
    3535  watcher = new QFileSystemWatcher(this); 
    3636    connect(watcher, SIGNAL(fileChanged(QString)),this,SLOT(fileChanged(QString)) ); 
    3737  timer = new QTimer(); 
    38     timer->setInterval( 300000 ); //5 minute check time 
    3938    connect(timer, SIGNAL(timeout()), this, SLOT(checkPoolStatus()) ); 
    4039  //initialize the log file reader 
     
    7170  checkPoolStatus(); 
    7271  //And start up the error file watcher 
    73   timer->start(); 
     72  if(!timer->isActive()){ timer->start(sysCheckTime); } 
    7473} 
    7574 
     
    9089  else if(type=="critical"){base=30;} 
    9190  else if(type=="mirror"){base=40;} 
    92   else if(type=="resilvering"){base=50;} 
     91  else if(type=="resilver"){base=50;} 
    9392  else if(type=="scrub"){base=60;} 
    9493  else{ return output; } //invalid input type 
     
    9796    msgList[i] = msgList[i].toLower(); 
    9897    if(msgList[i]=="id" && LOGS.contains(base)){ output << LOGS[base]; } 
    99     else if(msgList[i]=="dataset" && LOGS.contains(base+1)){ output << LOGS[base+1]; } 
     98    else if(msgList[i]=="device" && LOGS.contains(base+1)){ output << LOGS[base+1]; } 
    10099    else if(msgList[i]=="summary" && LOGS.contains(base+2)){ output << LOGS[base+2]; } 
    101100    else if(msgList[i]=="message" && LOGS.contains(base+3)){ output << LOGS[base+3]; } 
     
    288287    //parse the output 
    289288    QString pool, state, timestamp; 
    290     qDebug() << "-----zpool status------"; 
    291     bool newresilver = false; 
     289    //qDebug() << "-----zpool status------"; 
     290    bool newresilver = false; bool newscrub = false; bool newerror = false; 
    292291    for(int i=0; i<zstat.length(); i++){ 
    293292      zstat[i] = zstat[i].simplified(); 
    294293      if(zstat[i].isEmpty()){ continue; } 
    295       qDebug() << zstat[i]; 
     294      //qDebug() << zstat[i]; 
    296295      if(zstat[i].startsWith("pool:")){ pool = zstat[i].section(":",1,10).simplified(); } 
    297296      else if(zstat[i].startsWith("state:")){ state = zstat[i].section(":",1,10).simplified(); } 
    298297      else if(zstat[i].startsWith("scan:")){ 
    299298        //check for scrubs/resilvering progress 
    300         bool isnew = false; 
    301299        // ------ SCRUB ------ 
    302300        if(zstat[i].contains("scrub")){ 
    303           //Setup the latest/running scrub info 
    304301          if(zstat[i].contains(" scrub repaired ")){ 
     302            //Scrub Finished 
    305303            zstat[i]  = zstat[i].replace("\t"," ").simplified(); 
    306304            timestamp = zstat[i].section(" ",10,14,QString::SectionSkipEmpty); 
     
    310308            //Scrub finished previously 
    311309            if(numFixed.toInt() > 0){  
    312               if(LOGS.value(60)!="ERROR"){ isnew=true; } 
     310              if(LOGS.value(60)!="ERROR"){ newscrub=true; } 
    313311              LOGS.insert(60, "ERROR");  
    314312              LOGS.insert(62, QString(tr("Scrub repaired %1 bad blocks")).arg(numFixed) ); 
    315313              LOGS.insert(63, QString(tr("Scrub repaired %1 blocks in %2 with %3 errors")).arg(numFixed, timeRun, numErr) ); 
    316314            }else{  
    317               if(LOGS.value(60)!= " " && LOGS.value(60)!="FINISHED"){ isnew=true; } 
     315              if(LOGS.contains(60) && LOGS.value(60)!="FINISHED"){ newscrub=true; } 
    318316              LOGS.insert(60,"FINISHED");  
    319317              LOGS.insert(62, tr("Scrub completed") ); 
     
    323321            LOGS.insert(64, timestamp); 
    324322            LOGS.insert(65, timestamp.section(" ",3,3) ); 
     323            if(timer->interval() != sysCheckTime){ timer->start(sysCheckTime); } 
    325324          }else{ 
    326325            //Scrub is running - parse the line 
    327             timestamp = "??"; 
    328             QString percent = "??"; 
    329             QString remain = "??"; 
    330             if(LOGS.value(60) != "RUNNING"){isnew=true;} 
     326            timestamp = zstat[i].section(" ",5,9,QString::SectionSkipEmpty); 
     327            i++; QString remain = zstat[i].section(" ",7,7,QString::SectionSkipEmpty); 
     328            i++; QString percent = zstat[i].section(" ",2,2,QString::SectionSkipEmpty); 
     329            if(LOGS.value(60) != "RUNNING"){newscrub=true;} 
    331330            LOGS.insert(60,"RUNNING"); 
    332331            LOGS.insert(61,pool); 
    333             LOGS.insert(62, QString(tr("Scrubbing: %1 (%2 remaining)")).arg(percent, remain) ); 
    334             LOGS.insert(63, QString(tr("Scrubbing: %1 (%2 remaining)")).arg(percent, remain) ); 
     332            LOGS.insert(62, QString(tr("Scrubbing %1: %2 (%3 remaining)")).arg(pool, percent, remain) ); 
     333            LOGS.insert(63, QString(tr("Scrubbing %1: %2 (%3 remaining)")).arg(pool, percent, remain) ); 
    335334            LOGS.insert(64, timestamp); 
    336335            LOGS.insert(65, timestamp.section(" ",3,3) ); 
    337             qDebug() << "***Running Scrub: line needs parsing"; 
     336            if(timer->interval() != 60000){ timer->start(60000); } //put the timer on a 1 minute refresh since it is running 
    338337          } 
    339           if(isnew){ emit MessageAvailable("scrub"); } 
    340338          if(LOGS.contains(50) ){ 
    341339            //Only resilvering OR scrub is shown at a time - so remove the resilver info 
     
    372370            LOGS.remove(65); 
    373371          } 
     372          if(timer->interval() != 60000){ timer->start(60000); }//put the timer on a 1 minute refresh since it is running 
    374373        }else if(zstat[i].contains("resilvered")){ 
    375374          //Resilvering is finished 
     
    378377          QString errors = zstat[i].section(" ", 6,6,QString::SectionSkipEmpty); 
    379378          //Setup the running re-silvering progress 
    380           if(LOGS.value(50)!= " "){newresilver=true; } //don't display message for first run 
     379          if(LOGS.contains(50)){newresilver=true; } //don't display message for first run 
    381380          if(errors.toInt() > 0){  
    382381            LOGS.insert(50, "ERROR"); 
     
    400399            LOGS.remove(65); 
    401400          } 
     401          if(timer->interval() != sysCheckTime){ timer->start(sysCheckTime); } 
    402402        } 
    403403      }else if(zstat[i].startsWith("errors:")){ 
     
    407407      }else if( state != "ONLINE" || !LOGS.value(50).isEmpty() ){ 
    408408        //Check for state/resilvering of all real devices 
    409         if(zstat[i].contains("NAME\tSTATE\tREAD")){continue;} //nothing on this header line 
    410         else if(zstat[i].contains("(resilvering)")){ LOGS.insert(51, zstat[i].section("\t",0,0,QString::SectionSkipEmpty) ); } 
     409        QString msg, summary, status; 
     410        if(zstat[i].contains("NAME STATE READ")){continue;} //nothing on this header line 
     411        else if(zstat[i].contains("(resilvering)")){ LOGS.insert(51, zstat[i].section("\t",0,0,QString::SectionSkipEmpty) ); continue;} 
    411412        else if(zstat[i].contains("ONLINE")){continue;} //do nothing for this device - it is good 
    412413        else if(zstat[i].contains("OFFLINE")){ } 
     
    415416        else if(zstat[i].contains("REMOVED")){ } 
    416417        else if(zstat[i].contains("UNAVAIL")){ } 
     418        //Now put the error message into the "critical" message slot 
    417419      } 
    418420    } //end of loop over zpool status lines 
    419   if(newresilver){ emit MessageAvailable("resilvering"); } 
    420 } 
     421  //Now emit the appropriate signal 
     422  if(newerror){ emit MessageAvailable("critical"); } 
     423  else if(newresilver){ emit MessageAvailable("resilver"); } 
     424  else if(newscrub){ emit MessageAvailable("scrub"); } 
     425  else{ emit StatusUpdated(); } 
     426} 
  • src-qt4/life-preserver/LPWatcher.h

    rb5a7675 r220bbd4  
    3737        QFileSystemWatcher *watcher; 
    3838        QTimer *timer; 
     39        int sysCheckTime; 
    3940        QFile *logfile, *repfile; 
    4041        QTextStream *LFSTREAM, *RFSTREAM; 
     
    5657signals: 
    5758        void MessageAvailable(QString type); 
     59        void StatusUpdated(); 
    5860}; 
    5961 
Note: See TracChangeset for help on using the changeset viewer.