00001
00014 #include <kapp.h>
00015 #include <klocale.h>
00016 #include <kiconloader.h>
00017 #include <kmessagebox.h>
00018 #include <kaudioplayer.h>
00019
00020 #include <qcursor.h>
00021 #include <qstring.h>
00022 #include <qstringlist.h>
00023 #include <qheader.h>
00024 #include <qlist.h>
00025 #include <qdir.h>
00026 #include <qpushbutton.h>
00027 #include <qpopupmenu.h>
00028 #include <qcombobox.h>
00029 #include <qtooltip.h>
00030 #include <qlabel.h>
00031 #include <qtimer.h>
00032 #include <qbitmap.h>
00033 #include <qpainter.h>
00034
00035 #include "setiloc.h"
00036 #include "ksetiwatch.h"
00037 #include "analysis.h"
00038 #include "addsetilocdlg.h"
00039 #include "sigmsg.h"
00040 #include "poplistview.h"
00041
00042
00044 QString AnalysisListViewItem::key(int column, bool) const
00045 {
00046
00047 static QString ret;
00048 QString val;
00049 double tmp;
00050
00051 if(column == 2 || column == 3 || (column >= 6 && column <= 8))
00052 {
00053 val = text(column);
00054 tmp = val.toDouble();
00055 val.sprintf("%f", tmp);
00056 ret = val.rightJustify(32, '0');
00057 }
00058 else if(column == 4 || column == 5)
00059 {
00060 int colon;
00061 int d(0), h(0), m(0), s(0);
00062
00063 val = text(column);
00064 colon = val.contains(':');
00065 if(colon == 2)
00066 {
00067 sscanf(text(column), "%d:%d:%d", &h, &m, &s);
00068 }
00069 else if(colon == 3)
00070 {
00071 sscanf(text(column), "%dd:%d:%d:%d", &d, &h, &m, &s);
00072 }
00073 tmp = 86400*d + 3600*h + 60*m + s;
00074 ret.sprintf("%032d", (int)tmp);
00075 }
00076 else if(column == 9)
00077 {
00078 if(text(column).isEmpty())
00079 tmp = 0.0;
00080 else
00081 sscanf(text(column), " scr=%lf", &tmp);
00082 val.sprintf("%f", tmp);
00083 ret = val.rightJustify(32, '0');
00084 }
00085 else if(column == 1)
00086 {
00087 SetiLoc* loc = Ksetiwatch::getLocation(this->text(0));
00088 ret.sprintf("%d", loc->clientState());
00089 }
00090 else
00091 {
00092 ret = text(column);
00093 }
00094
00095 return(ret);
00096 }
00097
00098
00099
00100 Analysis::Analysis(QWidget *parent, const char *name) : QWidget(parent,name)
00101 {
00102 Ksetiwatch::TableColumn antc[] =
00103 {
00104 {i18n("Location"), -1, AlignLeft},
00105 {i18n("Status"), -1, AlignCenter},
00106 {i18n("Chirp Rate"), -1, AlignRight},
00107 {i18n("% Done"), -1, AlignRight},
00108 {i18n("CPU Time"), 65, AlignRight},
00109 {i18n("Time Left"), 60, AlignRight},
00110 {i18n("%/CPU Hour"), -1, AlignRight},
00111 {i18n("MFlops"), -1, AlignRight},
00112 {i18n("Spike"), 55, AlignRight},
00113 {i18n("Strongest Gaussian"), -1, AlignLeft},
00114 {i18n("Strongest Pulse"), -1, AlignLeft},
00115 {i18n("Strongest Triplet"), -1, AlignLeft}
00116 };
00117
00118 const QStringList statusfilterList = QStringList() << i18n("All")
00119 << i18n("Stopped")
00120 << i18n("Running")
00121 << i18n("Finished")
00122 << i18n("Loading")
00123 << i18n("Running+Finished");
00124
00125
00126 LocListView = new popListView(this, globalopts->DrawGrid);
00127 LocListView->setShowSortIndicator(false);
00128 LocListView->popupSetTitle(i18n("Location"));
00129 LocListView->insertPopupItem(SmallIcon("mini-setiadd"),
00130 i18n("Add... "), PopupAdd);
00131 LocListView->setAccel(CTRL + Key_Plus, PopupAdd);
00132 LocListView->insertPopupItem(SmallIcon("configure"),
00133 i18n("Edit..."), PopupEdit);
00134 LocListView->setAccel(CTRL + Key_Enter, PopupEdit);
00135 LocListView->insertPopupItem(SmallIcon("mini-setiremove"),
00136 i18n("Delete"), PopupDelete);
00137 LocListView->setAccel(CTRL + Key_Minus, PopupDelete);
00138 LocListView->insertSeparator();
00139 LocListView->insertPopupItem(SmallIcon("mini-setirunning"),
00140 i18n("Start Client"), PopupStart);
00141 LocListView->setAccel(CTRL + Key_R, PopupStart);
00142 LocListView->insertPopupItem(SmallIcon("mini-setistopped"),
00143 i18n("Stop Client"), PopupStop);
00144 LocListView->setAccel(CTRL + Key_S, PopupStop);
00145 LocListView->insertSeparator();
00146 showOptions = new QPopupMenu(this);
00147 showOptions->insertItem(QIconSet(SmallIcon("mini-gaussian"), QIconSet::Small),
00148 i18n("Gaussian"), SetiLoc::GaussianGraph);
00149 showOptions->insertItem(QIconSet(SmallIcon("mini-pulse"), QIconSet::Small),
00150 i18n("Pulse"), SetiLoc::PulseGraph);
00151 showOptions->insertItem(QIconSet(SmallIcon("mini-triplet"), QIconSet::Small),
00152 i18n("Triplet"), SetiLoc::TripletGraph);
00153 showOptions->insertSeparator();
00154 showOptions->insertItem(QIconSet(SmallIcon("leftjust"), QIconSet::Small),
00155 i18n("Client Output"), SetiLoc::ClientOutput);
00156 LocListView->insertPopupItem(i18n("Show..."), showOptions, PopupShow);
00157 LocListView->setPopupStyle(popListView::ShowAnywhere);
00158 LocListView->move(5,1);
00159 connect(showOptions, SIGNAL(activated(int)),
00160 this, SLOT(handleShowPopupCommand(int)));
00161 connect(LocListView->popupMenu(), SIGNAL(activated(int)),
00162 this, SLOT(handlePopupCommand(int)));
00163 connect(LocListView->popupMenu(), SIGNAL(aboutToShow()),
00164 this, SLOT(checkPopupStatus()));
00165 connect(LocListView->header(), SIGNAL(sectionClicked(int)),
00166 this, SLOT(toggleSorting(int)));
00167 sortingorder = true;
00168 connect(LocListView, SIGNAL(selectionChanged(QListViewItem*)),
00169 this, SLOT(handleNewSelection(QListViewItem*)));
00170 connect(LocListView->header(), SIGNAL(sizeChange(int, int, int)),
00171 this, SLOT(slotAdjustAllStatusIcons(int, int, int)));
00172
00173 LocListViewHidden = new QListView(this);
00174 LocListViewHidden->hide();
00175
00176
00177 for(int i=0; i<(int)(sizeof(antc)/sizeof(antc[0])); i++)
00178 {
00179 LocListView->addColumn(antc[i].text, -1);
00180 LocListViewHidden->addColumn(antc[i].text, -1);
00181 if(antc[i].width != -1)
00182 LocListView->setColumnWidth(i, antc[i].width);
00183 LocListView->setColumnAlignment(i, antc[i].alignment);
00184 }
00185
00186
00187 StartAllBtn = new QPushButton(this);
00188 StartAllBtn->resize(35, 27);
00189 StartAllBtn->setPixmap(SmallIcon("mini-setirunning"));
00190 QToolTip::add(StartAllBtn, i18n("Start All"));
00191 connect(StartAllBtn, SIGNAL(clicked()), SLOT(slotStartAll()));
00192
00193 RefreshBtn = new QPushButton(this);
00194 RefreshBtn->resize(35, 27);
00195 RefreshBtn->setPixmap(SmallIcon("reload"));
00196 QToolTip::add(RefreshBtn, i18n("Refresh"));
00197 connect(RefreshBtn, SIGNAL(clicked()), SLOT(refreshList()));
00198
00199 StopAllBtn = new QPushButton(this);
00200 StopAllBtn->resize(35, 27);
00201 StopAllBtn->setPixmap(SmallIcon("mini-setistopped"));
00202 QToolTip::add(StopAllBtn, i18n("Stop All"));
00203 connect(StopAllBtn, SIGNAL(clicked()), SLOT(slotStopAll()));
00204
00205 HelpBtn = new QPushButton(this);
00206 HelpBtn->setMinimumSize(HelpBtn->sizeHint().width() + 20, 27);
00207 HelpBtn->resize(HelpBtn->sizeHint());
00208 HelpBtn->setText(i18n("Help"));
00209 connect(HelpBtn, SIGNAL(clicked()), SLOT(slotShowHelp()) );
00210
00211
00212 HomepageBtn = new QPushButton(i18n("Homepage"), this);
00213 HomepageBtn->setIconSet(SmallIconSet("ksetiwatch"));
00214 HomepageBtn->setMinimumSize(HomepageBtn->sizeHint().width(), 27);
00215 HomepageBtn->resize(HomepageBtn->sizeHint().width(), 27);
00216 connect(HomepageBtn, SIGNAL(clicked()), SLOT(openBrowser()) );
00217
00218 StatusFilter = new QComboBox(false, this);
00219 StatusFilter->insertStringList(statusfilterList);
00220 StatusFilter->setMinimumSize(StatusFilter->sizeHint().width(), 27);
00221 StatusFilter->resize(StatusFilter->sizeHint().width(), 27);
00222 ComboLabel = new QLabel(this);
00223 ComboLabel->setAutoResize(true);
00224 ComboLabel->setAlignment(AlignRight);
00225 ComboLabel->setText(i18n("Show:"));
00226 connect(StatusFilter, SIGNAL(activated(int)), SLOT(modifyStatusFilter(int)));
00227
00228
00229 StatusIcon[0] = SmallIcon("mini-setistopped");
00230 StatusIcon[1] = SmallIcon("mini-setirunning");
00231 StatusIcon[2] = SmallIcon("mini-setifinished");
00232 StatusIcon[3] = SmallIcon("mini-setiloading");
00233 StatusIcon[4] = SmallIcon("connect_creating");
00234
00235
00236
00237 QTimer::singleShot(1500, this, SLOT(slotAskForLocation()));
00238
00239
00240 refreshList();
00241 }
00242
00243
00244 Analysis::~Analysis()
00245 {
00246 }
00247
00248
00249 void Analysis::resizeEvent(QResizeEvent*)
00250 {
00251 LocListView->resize(this->width()-10,
00252 this->height()-HelpBtn->height()-5);
00253 StartAllBtn->move(5, LocListView->y()+LocListView->height()+
00254 (HelpBtn->height()-StartAllBtn->height())/2+2);
00255 RefreshBtn->move(10+StartAllBtn->width(), LocListView->y()+
00256 LocListView->height()+
00257 (HelpBtn->height()-RefreshBtn->height())/2+2);
00258 StopAllBtn->move(15+StartAllBtn->width()+RefreshBtn->width(),
00259 LocListView->y()+LocListView->height()+
00260 (HelpBtn->height()-StopAllBtn->height())/2+2);
00261 ComboLabel->move(StopAllBtn->x()+StopAllBtn->width()+16,
00262 LocListView->y()+LocListView->height()+
00263 (HelpBtn->height()-ComboLabel->height())/2+2);
00264 StatusFilter->move(ComboLabel->x()+ComboLabel->width()+4,
00265 LocListView->y()+LocListView->height()+2);
00266 HomepageBtn->move(width()-HomepageBtn->width()-5,
00267 LocListView->y()+LocListView->height()+2);
00268 HelpBtn->move(width()-HomepageBtn->width()-HelpBtn->width()-15,
00269 LocListView->y()+LocListView->height()+2);
00270 }
00271
00272
00273 void Analysis::paintEvent(QPaintEvent* e)
00274 {
00275 LocListView->setGridEnabled(globalopts->DrawGrid);
00276 QWidget::paintEvent(e);
00277 }
00278
00279
00280 void Analysis::handlePopupCommand(int id)
00281 {
00282 SetiLoc* loc = getLocation(selectedItem());
00283
00284 switch(id)
00285 {
00286 case PopupAdd:
00287 {
00288 AddSetiLocDlg dlg(topLevelWidget());
00289 dlg.setCaption(i18n("Add SETI@home Location..."));
00290 if(dlg.exec() == QDialog::Accepted)
00291 {
00292 LocSettings ls = dlg.options();
00293 SetiLoc* loc = new SetiLoc(dlg.setiDirectory());
00294 loc->setOptions(ls);
00295
00296
00297 emit listChangeRequested(loc, Ksetiwatch::ListAdd);
00298 }
00299 break;
00300 }
00301 case PopupEdit:
00302 {
00303 if(loc)
00304 {
00305
00306 AddSetiLocDlg dlg(topLevelWidget());
00307 dlg.setCaption(i18n("Edit SETI@home Location..."));
00308 dlg.setOptions(loc->options());
00309 if(dlg.exec() == QDialog::Accepted)
00310 {
00311 loc->setOptions(dlg.options());
00312
00313
00314 emit listChangeRequested(loc, Ksetiwatch::ListEdit);
00315 }
00316 }
00317 break;
00318 }
00319 case PopupDelete:
00320 {
00321 if(loc)
00322 {
00323 emit selectionChanged(0);
00324
00325
00326 emit listChangeRequested(loc, Ksetiwatch::ListDelete);
00327 }
00328 break;
00329 }
00330 case PopupStart:
00331 {
00332 if(loc)
00333 loc->startClient();
00334 break;
00335 }
00336 case PopupStop:
00337 {
00338 if(loc)
00339 loc->stopClient();
00340 break;
00341 }
00342 }
00343 }
00344
00345
00346 void Analysis::checkPopupStatus()
00347 {
00348
00349 QPoint p = LocListView->mapFromGlobal(QCursor::pos()) -
00350 QPoint(0, LocListView->header()->height());
00351
00352 if(LocListView->itemAt(p))
00353 {
00354 LocListView->popupMenu()->setItemEnabled(PopupEdit, true);
00355 LocListView->popupMenu()->setItemEnabled(PopupDelete, true);
00356
00357
00358 LocListView->popupMenu()->setItemEnabled(PopupStart, false);
00359 LocListView->popupMenu()->setItemEnabled(PopupStop, false);
00360 SetiLoc* loc = getLocation(static_cast<AnalysisListViewItem*>(LocListView->currentItem()));
00361 if(loc)
00362 {
00363 switch(loc->clientState())
00364 {
00365 case SetiLoc::Running:
00366 case SetiLoc::Loading:
00367 case SetiLoc::Connecting:
00368 {
00369
00370 LocListView->popupMenu()->setItemEnabled(PopupStop, true);
00371 break;
00372 }
00373 case SetiLoc::Stopped:
00374 {
00375
00376 LocListView->popupMenu()->setItemEnabled(PopupStart, true);
00377 break;
00378 }
00379 case SetiLoc::Finished:
00380 {
00381 if(loc->isClientRunning() == true)
00382 LocListView->popupMenu()->setItemEnabled(PopupStop, true);
00383 else
00384 LocListView->popupMenu()->setItemEnabled(PopupStart, true);
00385 break;
00386 }
00387 }
00388 LocListView->popupMenu()->setItemEnabled(PopupShow, true);
00389
00390 WUScore max = loc->wuScore();
00391 if(max.gaussian.score > 0.0 && loc->clientVersion() > 100)
00392 showOptions->setItemEnabled(soGaussian, true);
00393 else
00394 showOptions->setItemEnabled(soGaussian, false);
00395
00396 if(max.pulse.score > 0.0 && loc->clientVersion() >= 300)
00397 showOptions->setItemEnabled(soPulse, true);
00398 else
00399 showOptions->setItemEnabled(soPulse, false);
00400
00401 if(max.triplet.score > 0.0 && loc->clientVersion() >= 300)
00402 showOptions->setItemEnabled(soTriplet, true);
00403 else
00404 showOptions->setItemEnabled(soTriplet, false);
00405 }
00406 }
00407 else
00408 {
00409 LocListView->popupMenu()->setItemEnabled(PopupEdit, false);
00410 LocListView->popupMenu()->setItemEnabled(PopupDelete, false);
00411 LocListView->popupMenu()->setItemEnabled(PopupStart, false);
00412 LocListView->popupMenu()->setItemEnabled(PopupStop, false);
00413 LocListView->popupMenu()->setItemEnabled(PopupShow, false);
00414 }
00415 }
00416
00417
00418 void Analysis::handleShowPopupCommand(int id)
00419 {
00420 AnalysisListViewItem *it = selectedItem();
00421 SetiLoc* loc = getLocation(it);
00422
00423 if(loc)
00424 loc->showGraph(id);
00425 }
00426
00427
00428 void Analysis::refreshList()
00429 {
00430 QList<SetiLoc> seli = Ksetiwatch::locationList();
00431
00432 for(SetiLoc* loc=seli.first(); loc != 0; loc=seli.next())
00433 {
00434 AnalysisListViewItem* it = locationItemById(loc->id());
00435 if(it == 0)
00436 slotUpdateList(loc, Ksetiwatch::ListAdd);
00437 else
00438 refreshListItem(loc);
00439 }
00440 }
00441
00442
00443 void Analysis::refreshListItem(SetiLoc* loc)
00444 {
00445 updateStateIcon(loc, loc->clientState(), 0);
00446 updateListItemTimeData(loc);
00447 updateListItemSpikeData(loc);
00448 updateListItemGaussianData(loc);
00449 updateListItemPulseData(loc);
00450 updateListItemTripletData(loc);
00451 }
00452
00453
00454 void Analysis::slotUpdateList(SetiLoc* loc, int type)
00455 {
00456 AnalysisListViewItem* it;
00457
00458 switch(type)
00459 {
00460 case Ksetiwatch::ListAdd:
00461 {
00462 it = lvDictHidden[loc->id()];
00463 if(it)
00464 {
00465 lvDictHidden.remove(loc->id());
00466 lvDict.insert(loc->id(), it);
00467 LocListViewHidden->takeItem(it);
00468 LocListView->insertItem(it);
00469 centerStatusIcon(it, loc->clientState());
00470 }
00471 else
00472 {
00473 it = new AnalysisListViewItem(LocListView);
00474 if(it)
00475 {
00476 lvDict.insert(loc->id(), it);
00477 connect(loc, SIGNAL(stateChanged(int,int)),
00478 this, SLOT(slotShowNewState(int,int)));
00479 connect(loc, SIGNAL(progressIncreased()),
00480 this, SLOT(slotUpdateAnalysisTimeData()));
00481 connect(loc, SIGNAL(newSpike(SpikeScore)),
00482 this, SLOT(slotUpdateAnalysisSpikeData(SpikeScore)));
00483 connect(loc, SIGNAL(newGaussian(GaussianScore)),
00484 this, SLOT(slotUpdateAnalysisGaussianData(GaussianScore)));
00485 connect(loc, SIGNAL(newPulse(PulseScore)),
00486 this, SLOT(slotUpdateAnalysisPulseData(PulseScore)));
00487 connect(loc, SIGNAL(newTriplet(TripletScore)),
00488 this, SLOT(slotUpdateAnalysisTripletData(TripletScore)));
00489 loc->initMaxScore();
00490 refreshListItem(loc);
00491 }
00492 }
00493 break;
00494 }
00495 case Ksetiwatch::ListEdit:
00496 {
00497 refreshListItem(loc);
00498 break;
00499 }
00500 case Ksetiwatch::ListDelete:
00501 {
00502 disconnect(loc, SIGNAL(stateChanged(int,int)),
00503 this, SLOT(slotShowNewState(int,int)));
00504 disconnect(loc, SIGNAL(progressIncreased()),
00505 this, SLOT(slotUpdateAnalysisTimeData()));
00506 disconnect(loc, SIGNAL(newSpike(SpikeScore)),
00507 this, SLOT(slotUpdateAnalysisSpikeData(SpikeScore)));
00508 disconnect(loc, SIGNAL(newGaussian(GaussianScore)),
00509 this, SLOT(slotUpdateAnalysisGaussianData(GaussianScore)));
00510 disconnect(loc, SIGNAL(newPulse(PulseScore)),
00511 this, SLOT(slotUpdateAnalysisPulseData(PulseScore)));
00512 disconnect(loc, SIGNAL(newTriplet(TripletScore)),
00513 this, SLOT(slotUpdateAnalysisTripletData(TripletScore)));
00514 it = lvDict[loc->id()];
00515 if(it)
00516 {
00517 lvDict.remove(loc->id());
00518 delete it;
00519 }
00520 break;
00521 }
00522 case Ksetiwatch::ListRemove:
00523 {
00524 it = lvDict[loc->id()];
00525 if(it)
00526 {
00527 LocListView->takeItem(it);
00528 LocListViewHidden->insertItem(it);
00529 lvDict.remove(loc->id());
00530 lvDictHidden.insert(loc->id(), it);
00531 }
00532 break;
00533 }
00534 }
00535 }
00536
00537
00538 void Analysis::updateListItemTimeData(SetiLoc* loc)
00539 {
00540 AnalysisListViewItem* it;
00541
00542 if(loc && (it = locationItemById(loc->id())))
00543 {
00544
00545 it->setText(ColLocation, loc->description());
00546
00547 if(loc->exists(SetiLoc::SC_StateFile))
00548 {
00549 if(loc->clientState() != SetiLoc::Finished &&
00550 loc->clientState() != SetiLoc::Connecting)
00551 {
00552
00553 it->setText(ColChirpRate, QString::number(loc->chirpRate(), 'f', 4));
00554
00555 it->setText(ColProgress, QString::number(loc->progress(), 'f', 3));
00556
00557 it->setText(ColTimeLeft, (loc->remainingTime() > 0.0) ?
00558 loc->convertTime(loc->remainingTime(), globalopts->hms) : QString::null);
00559 }
00560
00561 it->setText(ColCpuTime, loc->convertTime(loc->cpuTime(), globalopts->hms));
00562
00563 it->setText(ColProgressRate, QString::number(loc->progressRate(), 'f', 5));
00564
00565 it->setText(ColMFlops, QString::number(loc->megaFlopsPerSecond(), 'f', 2));
00566 }
00567 else
00568 {
00569 it->setText(ColChirpRate, QString::null);
00570 it->setText(ColProgress, QString::null);
00571 it->setText(ColCpuTime, QString::null);
00572 it->setText(ColTimeLeft, QString::null);
00573 it->setText(ColProgressRate, QString::null);
00574 it->setText(ColMFlops, QString::null);
00575 }
00576 }
00577 }
00578
00579
00580 void Analysis::updateListItemSpikeData(SetiLoc* loc)
00581 {
00582 AnalysisListViewItem* it;
00583
00584 if(loc && (it = locationItemById(loc->id())))
00585 {
00586 WUScore max = loc->wuScore();
00587
00588 if(loc->exists(SetiLoc::SC_StateFile) && max.spike.power > 0.0)
00589 it->setText(ColSpike, " " + ((max.spike.power > 1.0e6) ?
00590 QString::number(max.spike.power, 'e', 6) :
00591 QString::number(max.spike.power, 'f', 3)));
00592 else
00593 it->setText(ColSpike, QString::null);
00594 }
00595 }
00596
00597
00598 void Analysis::updateListItemGaussianData(SetiLoc* loc)
00599 {
00600 AnalysisListViewItem* it;
00601
00602 if(loc && (it = locationItemById(loc->id())))
00603 {
00604 WUScore max = loc->wuScore();
00605
00606 if(loc->exists(SetiLoc::SC_StateFile) && max.gaussian.score > 0.0)
00607 it->setText(ColGaussian, QString(" scr=%1, pwr=%2, fit=%3")
00608 .arg(max.gaussian.score, 0, 'f', 4)
00609 .arg(max.gaussian.power, 0, 'f', 2)
00610 .arg(max.gaussian.chisq, 0, 'f', 2));
00611 else
00612 it->setText(9, QString::null);
00613 }
00614 }
00615
00616
00617 void Analysis::updateListItemPulseData(SetiLoc* loc)
00618 {
00619 AnalysisListViewItem* it;
00620
00621 if(loc && (it = locationItemById(loc->id())))
00622 {
00623 WUScore max = loc->wuScore();
00624
00625 if(loc->exists(SetiLoc::SC_StateFile) && max.pulse.score > 0.0)
00626 it->setText(ColPulse, QString(" scr=%1, pwr=%2, prd=%3")
00627 .arg(max.pulse.score, 0, 'f', 4)
00628 .arg(max.pulse.power, 0, 'f', 2)
00629 .arg(max.pulse.period, 0, 'f', 4));
00630 else
00631 it->setText(ColPulse, QString::null);
00632 }
00633 }
00634
00635
00636 void Analysis::updateListItemTripletData(SetiLoc* loc)
00637 {
00638 AnalysisListViewItem* it;
00639
00640 if(loc && (it = locationItemById(loc->id())))
00641 {
00642 WUScore max = loc->wuScore();
00643
00644 if(loc->exists(SetiLoc::SC_StateFile) && max.triplet.score > 0.0)
00645 it->setText(ColTriplet, QString(" scr=%1, prd=%2")
00646 .arg(max.triplet.score, 0, 'f', 4)
00647 .arg(max.triplet.period, 0, 'f', 4));
00648 else
00649 it->setText(ColTriplet, QString::null);
00650 }
00651 }
00652
00653
00654 void Analysis::updateMaxScore(SetiLoc* loc, const SpikeScore& newspike)
00655 {
00656 WUScore max = loc->maxScore();
00657
00658 if(globalopts->ReportSpike &&
00659 newspike.power > globalopts->Record.spike.power)
00660 {
00661
00662 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00663 KAudioPlayer::play(globalopts->HighSignalSound);
00664
00665 QString msgbuf, title;
00666 msgbuf.sprintf(i18n("<b>New record spike:</b><br>"
00667 "peak = %.3lf at %.4lf Hz/s,<br>"
00668 "found in WU %s.<br><br>"
00669 "<b>Previous spike:</b><br>"
00670 "peak = %.3lf at %.4lf Hz/s,<br>"
00671 "found in WU %s."),
00672 newspike.power, newspike.chirprate,
00673 (const char*)newspike.wu_name,
00674 globalopts->Record.spike.power,
00675 globalopts->Record.spike.chirprate,
00676 (const char*)globalopts->Record.spike.wu_name);
00677 title = i18n("New Record Spike for %1").arg(loc->description());
00678 SigMsg* sm = new SigMsg(newspike, msgbuf, 0, "New Signal");
00679 sm->setCaption(title);
00680 sm->show();
00681 }
00682
00683
00684
00685 if(!globalopts->ShowRecords && globalopts->ReportSpike &&
00686 max.spike.power != -1.0)
00687 {
00688 if(newspike.power > max.spike.power &&
00689 newspike.power <= globalopts->Record.spike.power)
00690 {
00691
00692 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00693 KAudioPlayer::play(globalopts->HighSignalSound);
00694
00695 QString msgbuf, title;
00696 msgbuf.sprintf(i18n("<b>New high spike in the current WU:</b><br>"
00697 "peak = %.3lf at %.4lf Hz/s.<br><br>"
00698 "<b>Previous spike:</b><br>"
00699 "peak = %.3lf at %.4lf Hz/s."),
00700 newspike.power, newspike.chirprate,
00701 max.spike.power, max.spike.chirprate);
00702 title = i18n("New High Spike for %1").arg(loc->description());
00703 SigMsg* sm = new SigMsg(newspike, msgbuf, 0, "New Signal");
00704 sm->setCaption(title);
00705 sm->show();
00706 }
00707 }
00708
00709
00710 if(newspike.power > max.spike.power || max.spike.power == -1.0)
00711 {
00712
00713 if(loc->exists(SetiLoc::SC_StateFile))
00714 {
00715 max.spike = newspike;
00716 loc->setMaxScore(max);
00717 }
00718 }
00719 if(newspike.power > globalopts->Record.spike.power)
00720 {
00721 globalopts->Record.spike = newspike;
00722 }
00723 }
00724
00725
00726 void Analysis::updateMaxScore(SetiLoc* loc, const GaussianScore& newgaussian)
00727 {
00728 WUScore max = loc->maxScore();
00729
00730 if(globalopts->ReportGaussian &&
00731 newgaussian.score > globalopts->Record.gaussian.score)
00732 {
00733
00734 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00735 KAudioPlayer::play(globalopts->HighSignalSound);
00736
00737 QString msgbuf, title;
00738 msgbuf.sprintf(i18n("<b>New record gaussian:</b><br>"
00739 "scr = %.4lf, pwr = %.2lf, fit = %.2lf at %.4lf Hz/s,<br>"
00740 "found in WU %s.<br><br>"
00741 "<b>Previous record gaussian:</b><br>"
00742 "scr = %.4lf, pwr = %.2lf, fit = %.2lf at %.4lf Hz/s,<br>"
00743 "found in WU %s."),
00744 newgaussian.score, newgaussian.power, newgaussian.chisq,
00745 newgaussian.chirprate, (const char*)newgaussian.wu_name,
00746 globalopts->Record.gaussian.score,
00747 globalopts->Record.gaussian.power,
00748 globalopts->Record.gaussian.chisq,
00749 globalopts->Record.gaussian.chirprate,
00750 (const char*)globalopts->Record.gaussian.wu_name);
00751 title = i18n("New Record Gaussian for %1").arg(loc->description());
00752 SigMsg* sm = new SigMsg(newgaussian, msgbuf, 0, "New Signal");
00753 sm->setCaption(title);
00754 sm->show();
00755 }
00756
00757
00758
00759 if(!globalopts->ShowRecords && globalopts->ReportGaussian &&
00760 max.gaussian.score != -1.0)
00761 {
00762 if(newgaussian.score > max.gaussian.score &&
00763 newgaussian.score <= globalopts->Record.gaussian.score)
00764 {
00765
00766 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00767 KAudioPlayer::play(globalopts->HighSignalSound);
00768
00769 QString msgbuf, title;
00770 msgbuf.sprintf(i18n("<b>New high gaussian in the current WU:</b><br>"
00771 "scr = %.4lf, pwr = %.2lf, fit = %.2lf at %.4lf Hz/s.<br><br>"
00772 "<b>Previous gaussian:</b><br>"
00773 "scr = %.4lf, pwr = %.2lf, fit = %.2lf at %.4lf Hz/s."),
00774 newgaussian.score, newgaussian.power, newgaussian.chisq,
00775 newgaussian.chirprate,
00776 max.gaussian.score, max.gaussian.power, max.gaussian.chisq,
00777 max.gaussian.chirprate);
00778 title = i18n("New High Gaussian for %1").arg(loc->description());
00779 SigMsg* sm = new SigMsg(newgaussian, msgbuf, 0, "New Signal");
00780 sm->setCaption(title);
00781 sm->show();
00782 }
00783 }
00784
00785
00786 if(newgaussian.score > max.gaussian.score || max.gaussian.score == -1.0)
00787 {
00788
00789 if(loc->exists(SetiLoc::SC_StateFile))
00790 {
00791 max.gaussian = newgaussian;
00792 loc->setMaxScore(max);
00793 }
00794 }
00795 if(newgaussian.score > globalopts->Record.gaussian.score)
00796 {
00797 globalopts->Record.gaussian = newgaussian;
00798 }
00799 }
00800
00801
00802 void Analysis::updateMaxScore(SetiLoc* loc, const PulseScore& newpulse)
00803 {
00804 WUScore max = loc->maxScore();
00805
00806 if(globalopts->ReportPulse &&
00807 newpulse.score > globalopts->Record.pulse.score)
00808 {
00809
00810 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00811 KAudioPlayer::play(globalopts->HighSignalSound);
00812
00813 QString msgbuf, title;
00814 msgbuf.sprintf(i18n("<b>New record pulse:</b><br>"
00815 "scr = %.4lf, pwr = %.2lf, prd = %.4lf at %.4lf Hz/s,<br>"
00816 "found in WU %s.<br><br>"
00817 "<b>Previous record pulse:</b><br>"
00818 "scr = %.4lf, pwr = %.2lf, prd = %.4lf at %.4lf Hz/s,<br>"
00819 "found in WU %s."),
00820 newpulse.score, newpulse.power, newpulse.period,
00821 newpulse.chirprate, (const char*)newpulse.wu_name,
00822 globalopts->Record.pulse.score,
00823 globalopts->Record.pulse.power,
00824 globalopts->Record.pulse.period,
00825 globalopts->Record.pulse.chirprate,
00826 (const char*)globalopts->Record.pulse.wu_name);
00827 title = i18n("New Record Pulse for %1").arg(loc->description());
00828 SigMsg* sm = new SigMsg(newpulse, msgbuf, 0, "New Signal");
00829 sm->setCaption(title);
00830 sm->show();
00831 }
00832
00833
00834
00835 if(!globalopts->ShowRecords && globalopts->ReportPulse &&
00836 max.pulse.score != -1.0)
00837 {
00838 if(newpulse.score > max.pulse.score &&
00839 newpulse.score <= globalopts->Record.pulse.score)
00840 {
00841
00842 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00843 KAudioPlayer::play(globalopts->HighSignalSound);
00844
00845 QString msgbuf, title;
00846 msgbuf.sprintf(i18n("<b>New high pulse in the current WU:</b><br>"
00847 "scr = %.4lf, pwr = %.2lf, prd = %.4lf at %.4lf Hz/s.<br><br>"
00848 "<b>Previous pulse:</b><br>"
00849 "scr = %.4lf, pwr = %.2lf, prd = %.4lf at %.4lf Hz/s."),
00850 newpulse.score, newpulse.power, newpulse.period,
00851 newpulse.chirprate,
00852 max.pulse.score, max.pulse.power, max.pulse.period,
00853 max.pulse.chirprate);
00854 title = i18n("New High Pulse for %1").arg(loc->description());
00855 SigMsg* sm = new SigMsg(newpulse, msgbuf, 0, "New Signal");
00856 sm->setCaption(title);
00857 sm->show();
00858 }
00859 }
00860
00861
00862 if(newpulse.score > max.pulse.score || max.pulse.score == -1.0)
00863 {
00864
00865 if(loc->exists(SetiLoc::SC_StateFile))
00866 {
00867 max.pulse = newpulse;
00868 loc->setMaxScore(max);
00869 }
00870 }
00871 if(newpulse.score > globalopts->Record.pulse.score)
00872 {
00873 globalopts->Record.pulse = newpulse;
00874 }
00875 }
00876
00877
00878 void Analysis::updateMaxScore(SetiLoc* loc, const TripletScore& newtriplet)
00879 {
00880 WUScore max = loc->maxScore();
00881
00882 if(globalopts->ReportTriplet &&
00883 newtriplet.score > globalopts->Record.triplet.score)
00884 {
00885
00886 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00887 KAudioPlayer::play(globalopts->HighSignalSound);
00888
00889 QString msgbuf, title;
00890 msgbuf.sprintf(i18n("<b>New record triplet:</b><br>"
00891 "scr = %.4lf, prd = %.4lf at %.4lf Hz/s,<br>"
00892 "found in WU %s.<br><br>"
00893 "<b>Previous triplet:</b><br>"
00894 "scr = %.4lf, prd = %.4lf at %.4lf Hz/s,<br>"
00895 "found in WU %s."),
00896 newtriplet.score, newtriplet.period, newtriplet.chirprate,
00897 (const char*)newtriplet.wu_name,
00898 globalopts->Record.triplet.score,
00899 globalopts->Record.triplet.period,
00900 globalopts->Record.triplet.chirprate,
00901 (const char*)globalopts->Record.triplet.wu_name);
00902 title = i18n("New Record Triplet for %1").arg(loc->description());
00903 SigMsg* sm = new SigMsg(newtriplet, msgbuf, 0, "New Signal");
00904 sm->setCaption(title);
00905 sm->show();
00906 }
00907
00908
00909
00910 if(!globalopts->ShowRecords && globalopts->ReportTriplet &&
00911 max.triplet.score != -1.0)
00912 {
00913 if(newtriplet.score > max.triplet.score &&
00914 newtriplet.score <= globalopts->Record.triplet.score)
00915 {
00916
00917 if(globalopts->PlaySound && !globalopts->HighSignalSound.isEmpty())
00918 KAudioPlayer::play(globalopts->HighSignalSound);
00919
00920 QString msgbuf, title;
00921 msgbuf.sprintf(i18n("<b>New high triplet in the current WU:</b><br>"
00922 "scr = %.4lf, prd = %.4lf at %.4lf Hz/s.<br><br>"
00923 "<b>Previous triplet:</b><br>"
00924 "scr = %.4lf, prd = %.4lf at %.4lf Hz/s."),
00925 newtriplet.score, newtriplet.period, newtriplet.chirprate,
00926 max.triplet.score, max.triplet.period, max.triplet.chirprate);
00927 title = i18n("New High Triplet for %1").arg(loc->description());
00928 SigMsg* sm = new SigMsg(newtriplet, msgbuf, 0, "New Signal");
00929 sm->setCaption(title);
00930 sm->show();
00931 }
00932 }
00933
00934
00935 if(newtriplet.score > max.triplet.score || max.triplet.score == -1.0)
00936 {
00937
00938 if(loc->exists(SetiLoc::SC_StateFile))
00939 {
00940
00941 if(max.triplet.score != -1.0) loc->storeTripletData(newtriplet);
00942 max.triplet = newtriplet;
00943 loc->setMaxScore(max);
00944 }
00945 }
00946 if(newtriplet.score > globalopts->Record.triplet.score)
00947 {
00948 globalopts->Record.triplet = newtriplet;
00949 }
00950 }
00951
00952
00953 void Analysis::slotUpdateAnalysisTimeData()
00954 {
00955 SetiLoc* loc = (SetiLoc*)(sender());
00956 if(loc)
00957 updateListItemTimeData(loc);
00958 }
00959
00960
00961 void Analysis::slotUpdateAnalysisSpikeData(SpikeScore newspike)
00962 {
00963 SetiLoc* loc = (SetiLoc*)(sender());
00964
00965 if(loc)
00966 {
00967 updateMaxScore(loc, newspike);
00968 updateListItemSpikeData(loc);
00969 }
00970 }
00971
00972
00973 void Analysis::slotUpdateAnalysisGaussianData(GaussianScore newgaussian)
00974 {
00975 SetiLoc* loc = (SetiLoc*)(sender());
00976
00977 if(loc)
00978 {
00979 updateMaxScore(loc, newgaussian);
00980 updateListItemGaussianData(loc);
00981 }
00982 }
00983
00984
00985 void Analysis::slotUpdateAnalysisPulseData(PulseScore newpulse)
00986 {
00987 SetiLoc* loc = (SetiLoc*)(sender());
00988
00989 if(loc)
00990 {
00991 updateMaxScore(loc, newpulse);
00992 updateListItemPulseData(loc);
00993 }
00994 }
00995
00996
00997 void Analysis::slotUpdateAnalysisTripletData(TripletScore newtriplet)
00998 {
00999 SetiLoc* loc = (SetiLoc*)(sender());
01000
01001 if(loc)
01002 {
01003 updateMaxScore(loc, newtriplet);
01004 updateListItemTripletData(loc);
01005 }
01006 }
01007
01008
01009 void Analysis::updateStateIcon(SetiLoc* loc, int state, int loadsize)
01010 {
01011 AnalysisListViewItem* it;
01012
01013 if(loc)
01014 {
01015 updateAnalysisList(loc);
01016 it = locationItemById(loc->id());
01017 }
01018 if(loc && it)
01019 {
01020
01021 if(state == SetiLoc::Finished)
01022 {
01023 loc->checkWUStatus();
01024 }
01025
01026
01027 centerStatusIcon(it, state);
01028
01029
01030 switch(state)
01031 {
01032 case SetiLoc::Stopped:
01033
01034 if(loc->optionKeepClientAlive() && !loc->isStoppedNormally())
01035 loc->startClient();
01036
01037 case SetiLoc::Running:
01038 updateListItemTimeData(loc);
01039 updateListItemSpikeData(loc);
01040 updateListItemGaussianData(loc);
01041 updateListItemPulseData(loc);
01042 updateListItemTripletData(loc);
01043 break;
01044 case SetiLoc::Finished:
01045 updateListItemTimeData(loc);
01046 it->setText(ColChirpRate, QString::null);
01047 it->setText(ColProgress, "100.000");
01048 it->setText(ColTimeLeft, QString::null);
01049 break;
01050 case SetiLoc::Connecting:
01051 loadsize = 0;
01052
01053 case SetiLoc::Loading:
01054 it->setText(ColChirpRate, QString::null);
01055 it->setText(ColProgress, QString("%1 %").arg(loadsize));
01056 it->setText(ColCpuTime, QString::null);
01057 it->setText(ColTimeLeft, QString::null);
01058 it->setText(ColProgressRate, QString::null);
01059 it->setText(ColMFlops, QString::null);
01060 it->setText(ColSpike, QString::null);
01061 it->setText(ColGaussian, QString::null);
01062 it->setText(ColPulse, QString::null);
01063 it->setText(ColTriplet, QString::null);
01064 break;
01065 }
01066 }
01067 }
01068
01069
01070 void Analysis::slotShowNewState(int state, int loadsize)
01071 {
01072 SetiLoc* loc = (SetiLoc*)(sender());
01073 updateStateIcon(loc, state, loadsize);
01074 }
01075
01076
01077 void Analysis::updateAnalysisList(SetiLoc* loc)
01078 {
01079 AnalysisListViewItem* it = lvDict[loc->id()];
01080 switch(globalopts->StatusFilterValue)
01081 {
01082 case 0:
01083 {
01084 if(it == 0)
01085 slotUpdateList(loc, Ksetiwatch::ListAdd);
01086 break;
01087 }
01088 case 5:
01089 {
01090 if(it && (loc->clientState() != SetiLoc::Running &&
01091 loc->clientState() != SetiLoc::Finished))
01092 {
01093 if(it->isSelected())
01094 {
01095 LocListView->setSelected(LocListView->currentItem(), false);
01096 emit selectionChanged(0);
01097 }
01098 slotUpdateList(loc, Ksetiwatch::ListRemove);
01099 }
01100 else if(it == 0 && (loc->clientState() == SetiLoc::Running ||
01101 loc->clientState() == SetiLoc::Finished))
01102 {
01103 slotUpdateList(loc, Ksetiwatch::ListAdd);
01104 }
01105 break;
01106 }
01107 default:
01108 {
01109 if(it && loc->clientState() != globalopts->StatusFilterValue-1)
01110 {
01111 if(it->isSelected())
01112 {
01113 LocListView->setSelected(LocListView->currentItem(), false);
01114 emit selectionChanged(0);
01115 }
01116 slotUpdateList(loc, Ksetiwatch::ListRemove);
01117 }
01118 else if(it == 0 && loc->clientState() == globalopts->StatusFilterValue-1)
01119 {
01120 slotUpdateList(loc, Ksetiwatch::ListAdd);
01121 }
01122 break;
01123 }
01124 }
01125 }
01126
01127
01128 void Analysis::modifyStatusFilter(int sel)
01129 {
01130 globalopts->StatusFilterValue = sel;
01131
01132 for(SetiLoc* loc=Ksetiwatch::locationList().first(); loc != 0;
01133 loc=Ksetiwatch::locationList().next())
01134 {
01135 updateAnalysisList(loc);
01136 }
01137 }
01138
01139
01140 void Analysis::toggleSorting(int column)
01141 {
01142 sortingorder = !sortingorder;
01143 LocListView->setSorting(column, sortingorder);
01144 }
01145
01146
01147 void Analysis::slotShowHelp()
01148 {
01149 kapp->invokeHelp();
01150 }
01151
01152
01153 void Analysis::openBrowser()
01154 {
01155 kapp->invokeBrowser("http://ksetiwatch.sourceforge.net");
01156 }
01157
01158
01159 AnalysisListViewItem* Analysis::selectedItem()
01160 {
01161 QListViewItem* it = LocListView->currentItem();
01162
01163 if(LocListView->isSelected(it))
01164 return(static_cast<AnalysisListViewItem*>(it));
01165 else
01166 return(0);
01167 }
01168
01169
01170 AnalysisListViewItem* Analysis::locationItemByName(const QString& locName)
01171 {
01172 QListViewItem* it;
01173
01174
01175 for(it=LocListView->firstChild(); it != 0; it=it->nextSibling() )
01176 {
01177 if(it->text(ColLocation) == locName) break;
01178 }
01179
01180 return( static_cast<AnalysisListViewItem*>(it) );
01181 }
01182
01183
01184 AnalysisListViewItem* Analysis::locationItemById(const QString& locId)
01185 {
01186 AnalysisListViewItem* it;
01187
01188 it = lvDict[locId];
01189 if(it == 0)
01190 it = lvDictHidden[locId];
01191
01192 return(it);
01193 }
01194
01195
01196 SetiLoc* Analysis::getLocation(AnalysisListViewItem* it)
01197 {
01198 SetiLoc* loc = 0;
01199
01200 if(it)
01201 loc = Ksetiwatch::getLocation(it->text(ColLocation));
01202
01203 return( loc );
01204 }
01205
01206
01207 SetiLoc* Analysis::selectedLocation()
01208 {
01209 return(getLocation(selectedItem()));
01210 }
01211
01212
01213 void Analysis::handleNewSelection(QListViewItem* it)
01214 {
01215 SetiLoc* loc(0);
01216
01217 if(it) loc = getLocation((AnalysisListViewItem*)it);
01218 emit selectionChanged(loc);
01219 }
01220
01221
01222 void Analysis::setSelectedLocation(const QString& lid)
01223 {
01224 AnalysisListViewItem* it = lvDict[lid];
01225 if(it) LocListView->setSelected(it, true);
01226 }
01227
01228
01229 void Analysis::slotAskForLocation()
01230 {
01231 int retval;
01232
01233 if(Ksetiwatch::locationList().count() == 0)
01234 {
01235 retval = KMessageBox::questionYesNo(this,
01236 i18n("It appears that you haven't configured\n"
01237 "a SETI@home location. Would you like\n"
01238 "to add one to the list?"));
01239 if(retval == KMessageBox::Yes)
01240 {
01241 handlePopupCommand(PopupAdd);
01242 }
01243 }
01244 }
01245
01246
01247 void Analysis::slotStartAll()
01248 {
01249 for(SetiLoc* loc=Ksetiwatch::locationList().first(); loc != 0;
01250 loc=Ksetiwatch::locationList().next())
01251 {
01252 if(loc->isClientRunning(true) == false) loc->startClient();
01253 }
01254 }
01255
01256
01257 void Analysis::slotStopAll()
01258 {
01259 for(SetiLoc* loc=Ksetiwatch::locationList().first(); loc != 0;
01260 loc=Ksetiwatch::locationList().next())
01261 {
01262 if(loc->isClientRunning(true)) loc->stopClient();
01263 }
01264 }
01265
01266
01267 void Analysis::slotAdjustAllStatusIcons(int col, int, int)
01268 {
01269 if(col == ColStatus)
01270 {
01271 for(SetiLoc* loc=Ksetiwatch::locationList().first(); loc != 0;
01272 loc=Ksetiwatch::locationList().next())
01273 {
01274 centerStatusIcon(locationItemById(loc->id()), loc->clientState());
01275 }
01276 }
01277 }
01278
01279
01280 void Analysis::centerStatusIcon(QListViewItem* it, int state)
01281 {
01282 if(it)
01283 {
01284
01285 int cw = it->listView()->columnWidth(ColStatus);
01286 if(cw < 24)
01287 cw = 24;
01288
01289 QPixmap stpix((cw + StatusIcon[state].width())/2, 16);
01290 QPainter p(&stpix);
01291 p.fillRect(0, 0, (cw + StatusIcon[state].width())/2, 16, white);
01292 p.drawPixmap((cw - StatusIcon[state].width())/2, 0, StatusIcon[state]);
01293 p.end();
01294
01295 stpix.setMask( stpix.createHeuristicMask() );
01296 it->setPixmap(ColStatus, stpix);
01297 }
01298 }
01299
01300 #include "analysis.moc"
01301