int main(int argc, char *argv[]) { QString APP_ID = (APP_DEBUG) ? UNIQUIE_DEBUG_ID : UNIQUE_ID; SingleApplication App(argc, argv,APP_ID); //check if there is another process running if(App.AlreadyExists()) { App.SendInstanceMessage(QString(APP_MESSAGE_SHOWAPP)); return 0; } WriteAppInfo(APP_LOCAL_VERSION_FILENAME,QString::number(APP_MAJOR_VERSION),QString::number(APP_MINOR_VERSION)); CheckUpdaterFiles(APP_UPDATER); bool Args = false; if(!APP_DEBUG) { if(argc < 2) { Args = true; QString UpdaterPath = QApplication::applicationDirPath() + QDir::separator() + APP_UPDATER; // Check if an updater exists QFile Updater(UpdaterPath); if(!Updater.exists()) { if(QMessageBox::critical(0,"Error","Cannot find Ouroboros Updater.exe, please re-install Ouroboros") == QMessageBox::Ok) return 0; } QProcess::startDetached(UpdaterPath,QStringList()); } } if(!Args) { //run the application Ouroboros Window; Window.show(); Window.raise(); Window.activateWindow(); App.connect(&App,SIGNAL(MessageAvailable(QStringList)),&Window,SLOT(RecievedMessageFromInstance(QStringList))); return App.exec(); } return 0; }
void LPWatcher::readReplicationFile(){ QString stat; while( !RFSTREAM->atEnd() ){ QString line = RFSTREAM->readLine(); if(line.contains("total estimated size")){ repTotK = line.section(" ",-1).simplified(); } //save the total size to replicate else if(line.startsWith("send from ")){} else if(line.startsWith("TIME ")){} else if(line.startsWith("warning: ")){} //start of an error else{ stat = line; } //only save the relevant/latest status line } if(!stat.isEmpty()){ //qDebug() << "New Status Message:" << stat; //Divide up the status message into sections stat.replace("\t"," "); QString dataset = stat.section(" ",2,2,QString::SectionSkipEmpty).section("/",0,0).simplified(); QString cSize = stat.section(" ",1,1,QString::SectionSkipEmpty); //Now Setup the tooltip if(cSize != lastSize){ //don't update the info if the same size info QString percent; if(!repTotK.isEmpty()){ //calculate the percentage double tot = displayToDoubleK(repTotK); double c = displayToDoubleK(cSize); if( tot!=-1 & c!=-1){ double p = (c*100)/tot; p = int(p*10)/10.0; //round to 1 decimel places percent = QString::number(p) + "%"; } } if(repTotK.isEmpty()){ repTotK = "??"; } //Format the info string QString status = cSize+"/"+repTotK; if(!percent.isEmpty()){ status.append(" ("+percent+")"); } QString txt = QString(tr("Replicating %1: %2")).arg(dataset, status); lastSize = cSize; //save the current size for later //Now set the current process status LOGS.insert(20,"RUNNING"); LOGS.insert(21,dataset); LOGS.insert(22,txt); LOGS.insert(23,txt); emit MessageAvailable(""); } } }
void LPWatcher::checkPoolStatus(){ //Now check zpool status for bad/running statuses QStringList zstat = getCmdOutput("zpool status"); //parse the output QString pool, state, timestamp; QStringList cDev, cStat, cMsg, cSummary; //qDebug() << "-----zpool status------\n" << zstat.join("\n"); bool newresilver = false; bool newscrub = false; bool newerror = false; for(int i=0; i<zstat.length(); i++){ zstat[i] = zstat[i].simplified(); if(zstat[i].isEmpty()){ continue; } //qDebug() << zstat[i]; if(zstat[i].startsWith("pool:")){ pool = zstat[i].section(":",1,10).simplified(); } else if(zstat[i].startsWith("state:")){ state = zstat[i].section(":",1,10).simplified(); } else if(zstat[i].startsWith("scan:")){ //check for scrubs/resilvering progress // ------ SCRUB ------ if(zstat[i].contains("scrub")){ if(zstat[i].contains(" scrub repaired ")){ //Scrub Finished zstat[i] = zstat[i].replace("\t"," ").simplified(); timestamp = zstat[i].section(" ",10,14,QString::SectionSkipEmpty); QString numFixed = zstat[i].section(" ",3,3,QString::SectionSkipEmpty); QString numErr = zstat[i].section(" ",7,7,QString::SectionSkipEmpty); QString timeRun = zstat[i].section(" ",5,5,QString::SectionSkipEmpty); //Scrub finished previously if(numFixed.toInt() > 0){ if(LOGS.value(60)!="ERROR"){ newscrub=true; } LOGS.insert(60, "ERROR"); LOGS.insert(62, QString(tr("Scrub repaired %1 bad blocks")).arg(numFixed) ); LOGS.insert(63, QString(tr("Scrub repaired %1 blocks in %2 with %3 errors")).arg(numFixed, timeRun, numErr) ); }else{ if(LOGS.contains(60) && LOGS.value(60)!="FINISHED"){ newscrub=true; } LOGS.insert(60,"FINISHED"); LOGS.insert(62, tr("Scrub completed") ); LOGS.insert(63, tr("Scrub completed without needing repairs") ); } LOGS.insert(61,pool); LOGS.insert(64, timestamp); LOGS.insert(65, timestamp.section(" ",3,3) ); if(timer->interval() != sysCheckTime){ timer->start(sysCheckTime); } }else if(zstat[i].contains(" scrub cancel")){ //Scrub was cancelled before finishing zstat[i] = zstat[i].replace("\t"," ").simplified(); timestamp = zstat[i].section(" ",4,8,QString::SectionSkipEmpty); LOGS.insert(60, "FINISHED"); LOGS.insert(61, pool); LOGS.insert(62, QString(tr("Scrub cancelled for %1")).arg(pool) ); LOGS.insert(63, QString(tr("Scrub cancelled for %1")).arg(pool) ); LOGS.insert(64, timestamp); LOGS.insert(65,timestamp.section(" ",3,3) ); }else{ //Scrub is running - parse the line timestamp = zstat[i].section(" ",5,9,QString::SectionSkipEmpty); i++; QString remain = zstat[i].section(" ",7,7,QString::SectionSkipEmpty); i++; QString percent = zstat[i].section(" ",2,2,QString::SectionSkipEmpty); if(LOGS.value(60) != "RUNNING"){newscrub=true;} LOGS.insert(60,"RUNNING"); LOGS.insert(61,pool); LOGS.insert(62, QString(tr("Scrubbing %1: %2 (%3 remaining)")).arg(pool, percent, remain) ); LOGS.insert(63, QString(tr("Scrubbing %1: %2 (%3 remaining)")).arg(pool, percent, remain) ); LOGS.insert(64, timestamp); LOGS.insert(65, timestamp.section(" ",3,3) ); if(timer->interval() != 60000){ timer->start(60000); } //put the timer on a 1 minute refresh since it is running } if(LOGS.contains(50) ){ //Only resilvering OR scrub is shown at a time - so remove the resilver info LOGS.remove(50); LOGS.remove(51); LOGS.remove(52); LOGS.remove(53); LOGS.remove(54); LOGS.remove(55); } // --------- RESILVERING ------- }else if(zstat[i].contains("resilver in progress")){ //Resilvering is currently running timestamp = zstat[i].section(" ",5,9,QString::SectionSkipEmpty); //need info from the next two lines i++; QString timeleft = zstat[i].section(" ",7,7,QString::SectionSkipEmpty); i++; QString percent = zstat[i].section(" ", 2,2,QString::SectionSkipEmpty); //Setup the running re-silvering progress if(LOGS.value(50)!="RUNNING"){newresilver=true; } LOGS.insert(50, "RUNNING"); // 51 - need to put the actual device in here (not available on this line) LOGS.insert(52, QString(tr("Resilvering: %1 (%2 remaining)")).arg(percent, timeleft) ); if(newresilver){ LOGS.insert(53, QString(tr("Resilvering Started: %1 remaining ")).arg( timeleft) ); } else{ LOGS.insert(53,QString(tr("Resilvering: %1 (%2 remaining)")).arg(percent, timeleft) ); } LOGS.insert(54, timestamp); LOGS.insert(55, timestamp.section(" ",3,3) ); if(LOGS.contains(60) ){ //Only resilvering OR scrub is shown at a time - so remove the scrub info LOGS.remove(60); LOGS.remove(61); LOGS.remove(62); LOGS.remove(63); LOGS.remove(64); LOGS.remove(65); } if(timer->interval() != 60000){ timer->start(60000); }//put the timer on a 1 minute refresh since it is running }else if(zstat[i].contains("resilvered")){ //Resilvering is finished timestamp = zstat[i].section(" ",9,13,QString::SectionSkipEmpty); QString timecomplete = zstat[i].section(" ",4,4,QString::SectionSkipEmpty); QString errors = zstat[i].section(" ", 6,6,QString::SectionSkipEmpty); //Setup the running re-silvering progress if(LOGS.value(50) != "FINISHED" && LOGS.value(50) != "ERROR" ){newresilver=true; } //don't display message for first run if(errors.toInt() > 0){ LOGS.insert(50, "ERROR"); LOGS.insert(52, QString(tr("Resilver completed in %1 with %2 errors")).arg(timecomplete, errors) ); LOGS.insert(53, QString(tr("Resilver completed in %1 with %2 errors")).arg(timecomplete, errors) ); }else{ LOGS.insert(50, "FINISHED"); LOGS.insert(52, QString(tr("Resilver completed successfully in %1")).arg(timecomplete) ); LOGS.insert(53, QString(tr("Resilver completed successfully in %1")).arg(timecomplete) ); } // 51 - need to put the actual device in here (not available on this line) LOGS.insert(54, timestamp); LOGS.insert(55, timestamp.section(" ",3,3) ); if(LOGS.contains(60) ){ //Only resilvering OR scrub is shown at a time - so remove the scrub info LOGS.remove(60); LOGS.remove(61); LOGS.remove(62); LOGS.remove(63); LOGS.remove(64); LOGS.remove(65); } if(timer->interval() != sysCheckTime){ timer->start(sysCheckTime); } } }else if(zstat[i].startsWith("errors:")){ if(zstat[i] != "errors: No known data errors"){ qDebug() << "New zpool status error line that needs parsing:" << zstat[i]; } }else if( state != "ONLINE" || !LOGS.value(50).isEmpty() ){ //Check for state/resilvering of all real devices QString msg, summary, status; QString device = zstat[i].section(" ",0,0,QString::SectionSkipEmpty); if(zstat[i].contains("NAME STATE READ")){continue;} //nothing on this header line else if(zstat[i].contains("(resilvering)")){ LOGS.insert(51, device ); continue;} else if(zstat[i].contains("ONLINE")){continue;} //do nothing for this device - it is good else if(zstat[i].contains("OFFLINE")){ continue; } //do nothing - this status must be set manually - it is not a "random" status else if(zstat[i].contains("DEGRADED")){ // This should only happen on pools, not actual devices cStat << "DEGRADED"; cMsg << tr("The pool is in a degraded state. See additional device error(s)."); cSummary << QString(tr("%1 is degraded.")).arg(device); cDev << device; }else if(zstat[i].contains("FAULTED")){ cStat << "FAULTED"; cMsg << tr("The device is faulty, and should be replaced."); cSummary << QString(tr("%1 is faulty.")).arg(device); cDev << device; }else if(zstat[i].contains("REMOVED")){ cStat << "REMOVED"; cMsg << tr("The device was removed, and should be either be re-attached or replaced."); cSummary << QString(tr("%1 was removed.")).arg(device); cDev << device; }else if(zstat[i].contains("UNAVAIL")){ cStat << "UNAVAILABLE"; cMsg << tr("The device is unavailable and should be re-added to the pool."); cSummary << QString(tr("%1 is unavailable.")).arg(device); cDev << device; } } } //end of loop over zpool status lines //Add the critical messages to the hash if(cStat.isEmpty() || (cStat.join(" ").simplified() == "DEGRADED") ){ //No errors, or the pool is degraded without any additional errors (usually because of a resilver going on) if(LOGS.contains(30)){ LOGS.remove(30); LOGS.remove(31); LOGS.remove(32); LOGS.remove(33); LOGS.remove(34); LOGS.remove(35); } }else{ if(LOGS.value(30) != cStat.join(":::") ){ newerror = true; } LOGS.insert(30, cStat.join(":::") ); LOGS.insert(31, cDev.join(":::") ); LOGS.insert(32, cSummary.join(":::") ); LOGS.insert(33, cMsg.join(":::") ); LOGS.insert(34, timestamp); LOGS.insert(35, timestamp.section(" ",3,3) ); } //Now emit the appropriate signal if(newerror){ emit MessageAvailable("critical"); } else if(newresilver){ emit MessageAvailable("resilver"); } else if(newscrub){ emit MessageAvailable("scrub"); } else{ emit StatusUpdated(); } }
// ------------------------------------- // PRIVATE FUNCTIONS // ------------------------------------- void LPWatcher::readLogFile(bool quiet){ QStringList reppools = listReplicatedPools(); QTextStream in(logfile); while(!LFSTREAM->atEnd()){ QString log = LFSTREAM->readLine(); //Divide up the log into it's sections QString timestamp = log.section(":",0,2).simplified(); QString time = timestamp.section(" ",3,3).simplified(); QString message = log.section(":",3,3).toLower().simplified(); QString dev = log.section(":",4,4).simplified(); //dataset/snapshot/nothing //Now decide what to do/show because of the log message //qDebug() << "New Log Message:" << log; if(message.contains("creating snapshot")){ dev = message.section(" ",-1).simplified(); //Setup the status of the message LOGS.insert(10,"SNAPCREATED"); LOGS.insert(11,dev); //dataset LOGS.insert(12, QString(tr("New snapshot of %1")).arg(dev) ); //summary LOGS.insert(13, QString(tr("Creating snapshot for %1")).arg(dev) ); LOGS.insert(14, timestamp); //full timestamp LOGS.insert(15, time); // time only if(!quiet){ emit MessageAvailable("message"); } }else if(message.contains("starting replication")){ //Setup the file watcher for this new log file FILE_REPLICATION = dev; dev = message.section(" ",5,5,QString::SectionSkipEmpty); //Make sure the device is currently setup for replication if( !reppools.contains(dev) ){ FILE_REPLICATION.clear(); continue; } //Try to start the replication watcher if( startRepFileWatcher() ){ //Set the appropriate status variables LOGS.insert(20,"STARTED"); LOGS.insert(21, dev); //zpool LOGS.insert(22, tr("Replication Starting") ); //summary LOGS.insert(23, QString(tr("Starting replication for %1")).arg(dev) ); //Full message LOGS.insert(24, timestamp); //full timestamp LOGS.insert(25, time); // time only LOGS.insert(26,tr("Replication Log")+" <"+FILE_REPLICATION+">"); //log file if(!quiet){ emit MessageAvailable("replication"); } } }else if(message.contains("finished replication")){ stopRepFileWatcher(); dev = message.section(" ",-1).simplified(); //Make sure the device is currently setup for replication if( reppools.contains(dev) ){ //Now set the status of the process LOGS.insert(20,"FINISHED"); LOGS.insert(21,dev); //dataset LOGS.insert(22, tr("Finished Replication") ); //summary LOGS.insert(23, QString(tr("Finished replication for %1")).arg(dev) ); LOGS.insert(24, timestamp); //full timestamp LOGS.insert(25, time); // time only LOGS.insert(26, ""); //clear the log file entry if(!quiet){ emit MessageAvailable("replication"); } }else if( !reppools.contains( LOGS.value(21) ) ){ //Clear the current replication log, device was removed from replication LOGS.remove(20); LOGS.remove(21); LOGS.remove(22); LOGS.remove(23); LOGS.remove(24); LOGS.remove(25); LOGS.remove(26); if(!quiet){ emit MessageAvailable(""); } } }else if( message.contains("failed replication") ){ stopRepFileWatcher(); //Now set the status of the process dev = message.section(" ",-1).simplified(); //Make sure the device is currently setup for replication if( reppools.contains(dev) ){ //Update the logs QString file = log.section("LOGFILE:",1,1).simplified(); QString tt = QString(tr("Replication Failed for %1")).arg(dev) +"\n"+ QString(tr("Logfile available at: %1")).arg(file); LOGS.insert(20,"ERROR"); LOGS.insert(21,dev); //dataset LOGS.insert(22, tr("Replication Failed") ); //summary LOGS.insert(23, tt ); LOGS.insert(24, timestamp); //full timestamp LOGS.insert(25, time); // time only LOGS.insert(26, tr("Replication Error Log")+" <"+file+">" ); if(!quiet){ emit MessageAvailable("replication"); } }else if( !reppools.contains( LOGS.value(21) ) ){ //Clear the current replication log, device was removed from replication LOGS.remove(20); LOGS.remove(21); LOGS.remove(22); LOGS.remove(23); LOGS.remove(24); LOGS.remove(25); LOGS.remove(26); if(!quiet){ emit MessageAvailable(""); } } } } }
void LPWatcher::checkPoolStatus(){ //Now check zpool status for bad/running statuses QStringList zstat = LPBackend::getCmdOutput("zpool status"); //parse the output QString pool, state, timestamp; qDebug() << "-----zpool status------"; bool newresilver = false; for(int i=0; i<zstat.length(); i++){ zstat[i] = zstat[i].simplified(); if(zstat[i].isEmpty()){ continue; } qDebug() << zstat[i]; if(zstat[i].startsWith("pool:")){ pool = zstat[i].section(":",1,10).simplified(); } else if(zstat[i].startsWith("state:")){ state = zstat[i].section(":",1,10).simplified(); } else if(zstat[i].startsWith("scan:")){ //check for scrubs/resilvering progress bool isnew = false; // ------ SCRUB ------ if(zstat[i].contains("scrub")){ //Setup the latest/running scrub info if(zstat[i].contains(" scrub repaired ")){ zstat[i] = zstat[i].replace("\t"," ").simplified(); timestamp = zstat[i].section(" ",10,14,QString::SectionSkipEmpty); QString numFixed = zstat[i].section(" ",3,3,QString::SectionSkipEmpty); QString numErr = zstat[i].section(" ",7,7,QString::SectionSkipEmpty); QString timeRun = zstat[i].section(" ",5,5,QString::SectionSkipEmpty); //Scrub finished previously if(numFixed.toInt() > 0){ if(LOGS.value(60)!="ERROR"){ isnew=true; } LOGS.insert(60, "ERROR"); LOGS.insert(62, QString(tr("Scrub repaired %1 bad blocks")).arg(numFixed) ); LOGS.insert(63, QString(tr("Scrub repaired %1 blocks in %2 with %3 errors")).arg(numFixed, timeRun, numErr) ); }else{ if(LOGS.value(60)!= " " && LOGS.value(60)!="FINISHED"){ isnew=true; } LOGS.insert(60,"FINISHED"); LOGS.insert(62, tr("Scrub completed") ); LOGS.insert(63, tr("Scrub completed without needing repairs") ); } LOGS.insert(61,pool); LOGS.insert(64, timestamp); LOGS.insert(65, timestamp.section(" ",3,3) ); }else{ //Scrub is running - parse the line timestamp = "??"; QString percent = "??"; QString remain = "??"; if(LOGS.value(60) != "RUNNING"){isnew=true;} LOGS.insert(60,"RUNNING"); LOGS.insert(61,pool); LOGS.insert(62, QString(tr("Scrubbing: %1 (%2 remaining)")).arg(percent, remain) ); LOGS.insert(63, QString(tr("Scrubbing: %1 (%2 remaining)")).arg(percent, remain) ); LOGS.insert(64, timestamp); LOGS.insert(65, timestamp.section(" ",3,3) ); qDebug() << "***Running Scrub: line needs parsing"; } if(isnew){ emit MessageAvailable("scrub"); } if(LOGS.contains(50) ){ //Only resilvering OR scrub is shown at a time - so remove the resilver info LOGS.remove(50); LOGS.remove(51); LOGS.remove(52); LOGS.remove(53); LOGS.remove(54); LOGS.remove(55); } // --------- RESILVERING ------- }else if(zstat[i].contains("resilver in progress")){ //Resilvering is currently running timestamp = zstat[i].section(" ",5,9,QString::SectionSkipEmpty); //need info from the next two lines i++; QString timeleft = zstat[i].section(" ",7,7,QString::SectionSkipEmpty); i++; QString percent = zstat[i].section(" ", 2,2,QString::SectionSkipEmpty); //Setup the running re-silvering progress if(LOGS.value(50)!="RUNNING"){newresilver=true; } LOGS.insert(50, "RUNNING"); // 51 - need to put the actual device in here (not available on this line) LOGS.insert(52, QString(tr("Resilvering: %1 (%2 remaining)")).arg(percent, timeleft) ); if(newresilver){ LOGS.insert(53, QString(tr("Resilvering Started: %1 remaining ")).arg( timeleft) ); } else{ LOGS.insert(53,QString(tr("Resilvering: %1 (%2 remaining)")).arg(percent, timeleft) ); } LOGS.insert(54, timestamp); LOGS.insert(55, timestamp.section(" ",3,3) ); if(LOGS.contains(60) ){ //Only resilvering OR scrub is shown at a time - so remove the scrub info LOGS.remove(60); LOGS.remove(61); LOGS.remove(62); LOGS.remove(63); LOGS.remove(64); LOGS.remove(65); } }else if(zstat[i].contains("resilvered")){ //Resilvering is finished timestamp = zstat[i].section(" ",9,13,QString::SectionSkipEmpty); QString timecomplete = zstat[i].section(" ",4,4,QString::SectionSkipEmpty); QString errors = zstat[i].section(" ", 6,6,QString::SectionSkipEmpty); //Setup the running re-silvering progress if(LOGS.value(50)!= " "){newresilver=true; } //don't display message for first run if(errors.toInt() > 0){ LOGS.insert(50, "ERROR"); LOGS.insert(52, QString(tr("Resilver completed in &1 with %2 errors")).arg(timecomplete, errors) ); LOGS.insert(53, QString(tr("Resilver completed in &1 with %2 errors")).arg(timecomplete, errors) ); }else{ LOGS.insert(50, "FINISHED"); LOGS.insert(52, QString(tr("Resilver completed successfully in &1")).arg(timecomplete) ); LOGS.insert(53, QString(tr("Resilver completed successfully in &1")).arg(timecomplete) ); } // 51 - need to put the actual device in here (not available on this line) LOGS.insert(54, timestamp); LOGS.insert(55, timestamp.section(" ",3,3) ); if(LOGS.contains(60) ){ //Only resilvering OR scrub is shown at a time - so remove the scrub info LOGS.remove(60); LOGS.remove(61); LOGS.remove(62); LOGS.remove(63); LOGS.remove(64); LOGS.remove(65); } } }else if(zstat[i].startsWith("errors:")){ if(zstat[i] != "errors: No known data errors"){ qDebug() << "New zpool status error line that needs parsing:" << zstat[i]; } }else if( state != "ONLINE" || !LOGS.value(50).isEmpty() ){ //Check for state/resilvering of all real devices if(zstat[i].contains("NAME\tSTATE\tREAD")){continue;} //nothing on this header line else if(zstat[i].contains("(resilvering)")){ LOGS.insert(51, zstat[i].section("\t",0,0,QString::SectionSkipEmpty) ); } else if(zstat[i].contains("ONLINE")){continue;} //do nothing for this device - it is good else if(zstat[i].contains("OFFLINE")){ } else if(zstat[i].contains("DEGRADED")){ } else if(zstat[i].contains("FAULTED")){ } else if(zstat[i].contains("REMOVED")){ } else if(zstat[i].contains("UNAVAIL")){ } } } //end of loop over zpool status lines if(newresilver){ emit MessageAvailable("resilvering"); } }
// ------------------------------------- // PRIVATE FUNCTIONS // ------------------------------------- void LPWatcher::readLogFile(bool quiet){ QTextStream in(logfile); while(!LFSTREAM->atEnd()){ QString log = LFSTREAM->readLine(); //Divide up the log into it's sections QString timestamp = log.section(":",0,2).simplified(); QString time = timestamp.section(" ",3,3).simplified(); QString message = log.section(":",3,3).toLower().simplified(); QString dev = log.section(":",4,4).simplified(); //dataset/snapshot/nothing //Now decide what to do/show because of the log message //qDebug() << "New Log Message:" << log; if(message.contains("creating snapshot")){ dev = message.section(" ",-1).simplified(); //Setup the status of the message LOGS.insert(10,"SNAPCREATED"); LOGS.insert(11,dev); //dataset LOGS.insert(12, QString(tr("New snapshot of %1")).arg(dev) ); //summary LOGS.insert(13, QString(tr("Creating snapshot for %1")).arg(dev) ); LOGS.insert(14, timestamp); //full timestamp LOGS.insert(15, time); // time only if(!quiet){ emit MessageAvailable("message"); } }else if(message.contains("starting replication")){ //Setup the file watcher for this new log file FILE_REPLICATION = dev; startRepFileWatcher(); //Set the appropriate status variables LOGS.insert(20,"REPSTARTED"); // 21 - dataset set on update ping LOGS.insert(22, tr("Replication Started") ); //summary // 23 - Full message set on update ping LOGS.insert(24, timestamp); //full timestamp LOGS.insert(25, time); // time only if(!quiet){ emit MessageAvailable("replication"); } }else if(message.contains("finished replication")){ stopRepFileWatcher(); dev = message.section(" ",-1).simplified(); //Now set the status of the process LOGS.insert(20,"REPFINISHED"); LOGS.insert(21,dev); //dataset LOGS.insert(22, tr("Finished Replication") ); //summary LOGS.insert(23, QString(tr("Finished replication for %1")).arg(dev) ); LOGS.insert(24, timestamp); //full timestamp LOGS.insert(25, time); // time only if(!quiet){ emit MessageAvailable("replication"); } }else if( message.contains("FAILED replication") ){ stopRepFileWatcher(); //Now set the status of the process dev = message.section(" ",-1).simplified(); QString file = log.section("LOGFILE:",1,1).simplified(); QString tt = QString(tr("Replication Failed for %1")).arg(dev) +"\n"+ QString(tr("Logfile available at: %1")).arg(file); LOGS.insert(20,"REPERROR"); LOGS.insert(21,dev); //dataset LOGS.insert(22, tr("Replication Failed") ); //summary LOGS.insert(23, tt ); LOGS.insert(24, timestamp); //full timestamp LOGS.insert(25, time); // time only if(!quiet){ emit MessageAvailable("replication"); } } } }
//PUBLIC LPTray::LPTray() : QSystemTrayIcon() { qDebug() << "Starting up Life-preserver Tray..."; //Start up the log file watcher and connect the signals/slots watcher = new LPWatcher(); connect(watcher,SIGNAL(MessageAvailable(QString)),this,SLOT(watcherMessage(QString)) ); connect(watcher,SIGNAL(StatusUpdated()),this,SLOT(watcherMessage()) ); //Load the tray settings file settings = new QSettings(QSettings::UserScope,"PCBSD", "life-preserver-tray"); //Create the notification option widgets nShowAll = new QRadioButton(tr("Show all")); naAll = new QWidgetAction(this); naAll->setDefaultWidget(nShowAll); nShowError = new QRadioButton(tr("Warnings Only")); naErr = new QWidgetAction(this); naErr->setDefaultWidget(nShowError); nShowNone = new QRadioButton(tr("None")); naNone = new QWidgetAction(this); naNone->setDefaultWidget(nShowNone); //Create notification menu notificationMenu = new QMenu(tr("Popup Settings")); notificationMenu->setIcon( QIcon(":/images/configure.png") ); notificationMenu->addAction(naAll); notificationMenu->addAction(naErr); notificationMenu->addAction(naNone); //Activate the proper notification setting widget QString popset = settings->value("popup-policy", "").toString(); qDebug() << "Current Popup Policy:" << popset; if(popset=="all") { nShowAll->setChecked(true); popupPolicy = 2; } else if(popset=="errors") { nShowError->setChecked(true); popupPolicy = 1; } else if(popset=="none") { nShowNone->setChecked(true); popupPolicy = 0; } else { nShowError->setChecked(true); settings->setValue("popup-policy","errors"); //save the proper setting popupPolicy = 1; } //Now connect the popup settings signals/slots connect(nShowAll, SIGNAL(clicked()), this, SLOT(changePopupPolicy()) ); connect(nShowError, SIGNAL(clicked()), this, SLOT(changePopupPolicy()) ); connect(nShowNone, SIGNAL(clicked()), this, SLOT(changePopupPolicy()) ); //Setup the context menu menu = new QMenu; menu->addAction(QIcon(":/images/tray-icon-idle.png"),tr("Open Life Preserver"),this,SLOT(startGUI()) ); menu->addSeparator(); menu->addAction(QIcon(":/images/backup-failed.png"),tr("View Messages"),this,SLOT(startMessageDialog()) ); menu->addMenu(notificationMenu); menu->addAction(QIcon(":/images/refresh.png"),tr("Refresh Tray"),this,SLOT(refreshStatus()) ); menu->addSeparator(); menu->addAction(QIcon(":/images/application-exit.png"),tr("Close Tray"),this,SLOT(slotClose()) ); this->setContextMenu(menu); //Setup initial icon for the tray this->setIcon( QIcon(":/images/tray-icon-idle.png") ); //Create the messages GUI msgdlg = new LPMessages(); //connect other signals/slots connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(slotTrayClicked(QSystemTrayIcon::ActivationReason)) ); //Start up the watcher watcher->start(); updateTrayIcon(); updateToolTip(); }