Changeset 11088
- Timestamp:
- 06/21/11 12:52:38 (13 years ago)
- Location:
- fact
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
fact/Evidence/GUI.cc
r10984 r11088 20 20 // History chooser function (opens plot for numeric data, TextHist for all other) 21 21 // 22 QWidget *OpenHistory(char *Service, int Index) {22 void OpenHistory(char *Service, int Index) { 23 23 24 24 QString Format; 25 25 DimBrowser Browser; 26 26 class EvidenceHistory *Hist = Handler->GetHistory(Service); 27 char *Name, *Fmt; 27 28 28 29 // Check if history service available 29 30 if (Hist == NULL || Hist->GetFormat() == NULL) { 30 31 QMessageBox::warning(NULL, "Edd Message", QString("Could not retrieve history for service ") + Service ,QMessageBox::Ok); 31 32 // If service currently available, take its format 33 char *Name, *Fmt; 34 35 Browser.getServices(Service); 36 if (Browser.getNextService(Name, Fmt) != 0) Format = QString(Fmt); 37 else { 38 Handler->DropHistory(Service); 39 return NULL; 40 } 41 } 42 43 if (Format.isEmpty()) Format = Hist->GetFormat(); 32 } 33 else Format = Hist->GetFormat(); 34 35 // If service currently available, take its format 36 Browser.getServices(Service); 37 if (Browser.getNextService(Name, Fmt) != 0) Format = QString(Fmt); 38 44 39 Handler->DropHistory(Service); 45 40 46 if (Format.size() == 1 && Format[0] != 'C') return new EddPlot(Service, Index); 47 else return new EddText(Service); 48 49 41 // Open new window 42 QMainWindow *M = new QMainWindow; 43 M->setCentralWidget(new QWidget(M)); 44 M->setStatusBar(new QStatusBar(M)); 45 M->setAttribute(Qt::WA_DeleteOnClose); 46 47 QWidget *W; 48 if (Format.size() == 1 && Format[0] != 'C') W = new EddPlot(Service, Index); 49 else W = new EddText(Service); 50 51 QGridLayout *Layout = new QGridLayout(M->centralWidget()); 52 Layout->addWidget(W, 0, 0); 53 Layout->addWidget(new EddLineDisplay(Service, Index), 1, 0); 54 M->resize(300,350); 55 M->show(); 50 56 } 51 57 … … 183 189 // 184 190 void EddLineDisplay::contextMenuEvent(QContextMenuEvent *Event) { 185 191 186 192 Menu->exec(Event->globalPos()); 187 193 } … … 190 196 void EddLineDisplay::MenuOpenHistory() { 191 197 192 LastHist = OpenHistory(ServiceName.toAscii().data(), Index); 193 if (LastHist != NULL) LastHist->show(); 198 OpenHistory(ServiceName.toAscii().data(), Index); 194 199 } 195 200 … … 217 222 218 223 setToolTip("Send command "+Name); 224 setStatusTip(QString("Command %1").arg(Name)); 225 219 226 connect(this, SIGNAL(returnPressed()), SLOT(SendCommand())); 227 } 228 229 // Get command format and returns NULL (not empty) QString if not available 230 QString EddCommand::GetFormat() { 231 232 char *ItsName, *Format; 233 DimBrowser Browser; 234 235 Browser.getServices(Name.toAscii().data()); 236 237 if (Browser.getNextService(ItsName, Format) != DimCOMMAND) return QString(); 238 else return Format; 220 239 } 221 240 … … 223 242 void EddCommand::SendCommand() { 224 243 225 DimClient::sendCommand(Name.toAscii().data(), text().toAscii().data()); 244 QByteArray Data; 245 246 // Ignore empty commands 247 if (text().isEmpty()) return; 248 249 // Check if command available and retrieve format 250 QString Format = GetFormat(); 251 252 if (Format.isNull()) { 253 QMessageBox::warning(this, "Edd Message", "Command " + Name + " currently unavailable", QMessageBox::Ok); 254 return; 255 } 256 257 // Command has no argument 258 if (Format.isEmpty()) { 259 DimClient::sendCommand(Name.toAscii().data(), NULL, 0); 260 return; 261 } 262 263 // Command has string as argument 264 if (Format == "C") { 265 DimClient::sendCommand(Name.toAscii().data(), text().toAscii().data()); 266 return; 267 } 268 269 // Command has structure format, interpret data as hex 270 if (Format.size() > 1) { 271 Data = QByteArray::fromHex(text().toAscii()); 272 } 273 else { 274 QDataStream Stream(&Data, QIODevice::WriteOnly); 275 std::vector<std::string> Values = EvidenceServer::Tokenize(text().toStdString()); 276 277 for (unsigned int i=0; i<Values.size(); i++) { 278 switch (Format[0].toAscii()) { 279 case 'I': 280 case 'L': Stream << (int) atoi(Values[i].c_str()); break; 281 case 'S': Stream << (short) atoi(Values[i].c_str()); break; 282 case 'F': Stream << (float) atof(Values[i].c_str()); break; 283 case 'D': Stream << (double) atof(Values[i].c_str()); break; 284 case 'X': Stream << (long long) (atof(Values[i].c_str())); break; 285 } 286 } 287 } 288 289 DimClient::sendCommand(Name.toAscii().data(), Data.data(), Data.size()); 226 290 clear(); 227 291 } 228 292 293 // Opening context menu 294 void EddCommand::contextMenuEvent(QContextMenuEvent *Event) { 295 296 QMenu *Menu = createStandardContextMenu(); 297 Menu->addSeparator(); 298 Menu->addAction("Command help", this, SLOT(MenuCommandHelp())); 299 Menu->exec(Event->globalPos()); 300 delete Menu; 301 } 302 303 // Help text 304 void EddCommand::MenuCommandHelp() { 305 306 QString Format = GetFormat(); 307 QString Text = Name; 308 309 if (Format.isNull()) { 310 Text += " is currently unavailable"; 311 } 312 else Text += " has format '"+Format+"'"; 313 314 Text += "\n\nCommand arguments will be transmitted as string for format 'C',\n" 315 "interpreted as an array of numbers for all other single character formats\n" 316 "and as bytes in hexadecimal encoding for all more complex formats"; 317 318 QMessageBox::about(this, "Edd - Command help", Text); 319 } 229 320 230 321 ////////////////////////////////// … … 253 344 Menu->removeAction(Action); 254 345 Menu->insertAction(Menu->actions().value(1), Action); 255 346 347 Action = Menu->addAction("Show last hour", this, SLOT(MenuShowLastHour())); 348 Menu->insertAction(Menu->actions().value(8), Action); 349 Action = Menu->addAction("Show last day", this, SLOT(MenuShowLastDay())); 350 Menu->insertAction(Menu->actions().value(8), Action); 351 256 352 // Set timer to regularly update plot if new data available 257 353 SingleShot = new QTimer(this); … … 378 474 AddService(E.left(E.lastIndexOf(' ')), E.right(E.size()-E.lastIndexOf(' ')).toInt()); 379 475 } 476 477 // Show last hour/last day 478 void EddPlot::MenuShowLastHour() { 479 480 setAxisScale(QwtPlot::xBottom, time(NULL)-60*60, time(NULL)+60); 481 setAxisAutoScale(QwtPlot::yLeft); 482 replot(); 483 } 484 485 void EddPlot::MenuShowLastDay() { 486 487 setAxisScale(QwtPlot::xBottom, time(NULL)-24*3600, time(NULL)+3600); 488 setAxisAutoScale(QwtPlot::yLeft); 489 replot(); 490 } 491 380 492 381 493 // Remove list entry … … 783 895 void EddBasePlot::MenuPlotHelp() { 784 896 785 QMessageBox::about(this, "Edd - Plot navigation",897 QMessageBox::about(this, "Edd - Plot help", 786 898 "Zoom\tMouse wheel\n" 787 899 "\tKeys m and shift-m\n" … … 793 905 "ESC cancels selection\n" 794 906 "Cursor keys move mouse\n\n" 795 "Statistics are calculated over the current x axis extend"); 907 "Statistics are calculated over the current x axis extend\n\n" 908 "Items can be added to history plot by drag&drop from\n" 909 "DIM service displays or from other plots legends"); 796 910 } 797 911 … … 880 994 Mutex = new QMutex(QMutex::Recursive); 881 995 Volume = 0; 996 Period = 10; 882 997 883 998 // Timer to calculate data rates 884 999 QTimer *Timer = new QTimer(this); 885 1000 Timer->connect(Timer, SIGNAL(timeout()), this, SLOT(UpdateStatistics())); 886 Timer->start( 10000);1001 Timer->start(Period*1000); 887 1002 888 1003 // Connect to DIM handler … … 917 1032 void EddDim::MakeSubscriptions() { 918 1033 919 if (WaitingList.isEmpty()) return;920 921 1034 // Lock before accessing list 922 1035 QMutexLocker Locker(Mutex); 1036 1037 if (WaitingList.isEmpty()) return; 923 1038 924 1039 QString Name = WaitingList.first(); … … 1001 1116 } 1002 1117 1003 float Rate = Volume/1024.0/ 10;1118 float Rate = Volume/1024.0/Period; 1004 1119 Volume = 0; 1005 1120 YEP("Edd/Rate_kBSec", time(NULL), QByteArray::number(Rate), "F", QString::number(Rate)); … … 1034 1149 } 1035 1150 1036 // Update statistics only for actual Dim services1037 if (!Name.startsWith("Edd/")) Volume += Data.size();1038 1039 1151 // Emit signal to all widgets 1040 1152 YEP(Name, Time, Data, Format, Text); … … 1047 1159 if (!EvidenceServer::ServiceOK(getInfo())) INT(getInfo()->getName(), -1); 1048 1160 else { 1161 // Signal to EddDim::Update() 1049 1162 INT(getInfo()->getName(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), 1050 1163 getInfo()->getSize()), getInfo()->getFormat(), QString::fromStdString(EvidenceServer::ToString(getInfo()->getFormat(), getInfo()->getData(), getInfo()->getSize()))); 1164 // No mutex protection for Volume (otherwise must be in Update()) 1165 Volume += getInfo()->getSize(); 1051 1166 } 1052 1167 } … … 1064 1179 M->setStatusBar(new QStatusBar(M)); 1065 1180 M->setWindowTitle(WindowName); 1066 1067 1181 L = new QGridLayout(M->centralWidget()); 1068 1182 1069 connect(this, SIGNAL(pressed()), SLOT(Toggle())); 1070 } 1071 1072 // Show or hide window 1073 void EddWindow::Toggle() { 1074 1075 if (M->isVisible()) M->hide(); 1076 else { 1077 M->show(); 1078 M->raise(); 1079 } 1183 connect(this, SIGNAL(pressed()), M, SLOT(show())); 1184 connect(this, SIGNAL(pressed()), M, SLOT(raise())); 1080 1185 } 1081 1186 -
fact/Evidence/GUI.h
r10984 r11088 31 31 const QColor EddPlotBackgroundColor(Qt::yellow); 32 32 33 QWidget *OpenHistory(char *, int);33 void OpenHistory(char *, int); 34 34 bool SetStatus(QWidget *, QString, int, QString, int = -1); 35 36 35 37 36 // Base class for Edd plot … … 131 130 132 131 QString Name; 133 132 133 QString GetFormat(); 134 134 135 public: 135 136 EddCommand(QString, QWidget * = NULL); … … 137 138 private slots: 138 139 void SendCommand(); 140 void contextMenuEvent(QContextMenuEvent *); 141 void MenuCommandHelp(); 139 142 }; 140 143 … … 192 195 void LegendClicked(QwtPlotItem *); 193 196 void MenuPasteService(); 197 void MenuShowLastHour(); 198 void MenuShowLastDay(); 194 199 }; 195 200 … … 238 243 QMap<QString, struct HistItem> HistoryList; 239 244 245 unsigned int Period; 240 246 long long Volume; 241 247 … … 273 279 QGridLayout *Layout(); 274 280 QMainWindow *Window(); 275 private slots:276 void Toggle();277 281 }; 278 282 -
fact/Evidence/History.cc
r10996 r11088 31 31 const string DEFAULT_MAX_SIZE_KB = "2000"; 32 32 const string DEFAULT_NUM_ENTRIES = "1000"; // Number of entries in each history buffer 33 const double MIN_SAVE_PERDIOD = 0.5; // Minimum period between saving history buffers in hours 33 34 34 35 // … … 44 45 double MinAbsChange; 45 46 string Format; 47 time_t LastSave; 46 48 }; 47 49 map<string, struct Item> Map; … … 55 57 void AddService(string, const char *); 56 58 void RemoveService(string); 59 void SaveHistory(string); 57 60 off_t FileSize(FILE *); 58 61 FILE *OpenFile(string, const char *); … … 73 76 GetConfig("maxsize_kb", DEFAULT_MAX_SIZE_KB); 74 77 GetConfig("numentries", DEFAULT_NUM_ENTRIES); 78 GetConfig("saveperiod", "1"); 75 79 GetConfig("exclude", ""); 76 80 … … 95 99 // Check if service available 96 100 if (!ServiceOK(I)) return; 97 101 98 102 // ====== Part A: Handle service subscriptions === 99 103 … … 143 147 if (Map.count(Service) == 0 || I->getSize()==0 || I->getTimestamp()<=0) return; 144 148 149 // Save history buffers periodically (in case of program crash) 150 if (time(NULL)-Map[Service].LastSave > max(atof(GetConfig("saveperiod").c_str()),MIN_SAVE_PERDIOD)*3600) { 151 Map[Service].LastSave = time(NULL); 152 SaveHistory(Service); 153 } 154 145 155 // Resize buffer if necessary 146 156 int NEntries = atoi(GetConfig("numentries").c_str()); … … 266 276 Map[Name].Format = Format; 267 277 Map[Name].MinAbsChange = 0.0; 278 Map[Name].LastSave = 0.0; 268 279 269 280 // Set minimum required change if given in configuratrion … … 319 330 320 331 // Save history buffer 332 SaveHistory(Name); 333 334 Map.erase(Name); 335 } 336 337 338 // 339 // Save history buffer to file 340 // 341 void History::SaveHistory(string Name) { 342 321 343 FILE *File = OpenFile(Name, "wb"); 344 322 345 if (File != NULL) { 323 346 fwrite(&Map[Name].Next, sizeof(Map[Name].Next), 1, File); // Next pointer … … 327 350 // If error, try to delete (possibly erroneous) file 328 351 if (ferror(File) != 0) { 329 if (remove(Name.c_str()) == -1) Message(WARN, "Error writing history file '%s' in RemoveService(), could also not delete file", Name.c_str());330 else Message(WARN, "Error writing history file '%s' in RemoveService(), deleted file", Name.c_str());331 } 332 if (fclose(File) != 0) Message(WARN, "Error closing history file '%s' in RemoveService()", Name.c_str());;333 } 334 335 Map.erase(Name); 336 } 352 if (remove(Name.c_str()) == -1) Message(WARN, "Error writing history file '%s', could also not delete file", Name.c_str()); 353 else Message(WARN, "Error writing history file '%s', deleted file", Name.c_str()); 354 } 355 if (fclose(File) != 0) Message(WARN, "Error closing history file '%s'", Name.c_str()); 356 } 357 else Message(WARN, "Could not open history file '%s' for writing", Name.c_str());; 358 } 359 337 360 338 361 // -
fact/Evidence/readme.txt
r10996 r11088 51 51 Signal handler calls abort() if invoked three times or more. 52 52 10/6/2011 Services can be excluded from History buffer (mainly for large event data services) 53 20/6/2011 History buffers periodically saved to file (in case program crash or computer reboot) -
fact/tools/Edd/Edd.cc
r10984 r11088 901 901 // Menu bar 902 902 QMenu* Menu = menuBar()->addMenu("&Menu"); 903 Menu->addAction("New history plot", this, SLOT(MenuNewHistory())); 903 Menu->addAction("Open history plot", this, SLOT(MenuNewHistory())); 904 Menu->addAction("Send command", this, SLOT(MenuCommand())); 904 905 Menu->addAction("Raw data browser", this, SLOT(MenuRawDataBrowser())); 905 906 Menu->addSeparator(); … … 939 940 } 940 941 941 // Open request fornew history plot942 // Open new history plot 942 943 void GUI::MenuNewHistory() { 943 944 … … 956 957 // Open dialog and open history window 957 958 QString Result = QInputDialog::getItem(this, "Edd Request", 958 "Enter DIM service name", List, 0, true, &OK); 959 "Enter or choose DIM service name (add index separated by colon)", List, 0, true, &OK); 960 961 // Check if cancelled or empty data 962 List = Result.trimmed().split(":", QString::SkipEmptyParts); 963 if (!OK || List.isEmpty()) return; 964 965 if (List.size() == 1) OpenHistory(List[0].toAscii().data(), 0); 966 else OpenHistory(List[0].toAscii().data(), atoi(List[1].toAscii().data())); 967 } 968 969 // Send command selected from list 970 void GUI::MenuCommand() { 971 972 QStringList List; 973 char *Name, *Format; 974 int Type; 975 bool OK; 976 977 // Find all DIM commands and sort 978 getServices("*"); 979 while ((Type = getNextService(Name, Format)) != 0) { 980 if (Type==DimCOMMAND) List.append(Name); 981 } 982 List.sort(); 983 984 // Open dialog and open window for entering command 985 QString Result = QInputDialog::getItem(this, "Edd Request", 986 "Enter or choose DIM command name", List, 0, true, &OK); 959 987 if (OK && !Result.isEmpty()) { 960 988 Result = Result.trimmed(); 961 QWidget *Hist = OpenHistory(Result.toAscii().data(), 0); 962 if (Hist != NULL) Hist->show(); 989 990 QMainWindow *M = new QMainWindow; 991 M->setCentralWidget(new QWidget(M)); 992 M->setStatusBar(new QStatusBar(M)); 993 M->setAttribute(Qt::WA_DeleteOnClose); 994 QWidget *W = new EddCommand(Result.toAscii().data()); 995 QFormLayout *FormLayout = new QFormLayout(M->centralWidget()); 996 FormLayout->setRowWrapPolicy(QFormLayout::WrapAllRows); 997 FormLayout->addRow("Enter argument for " + Result, W); 998 M->show(); 963 999 } 964 1000 } -
fact/tools/Edd/Edd.h
r10904 r11088 142 142 void MenuAbout(); 143 143 void MenuNewHistory(); 144 void MenuCommand(); 144 145 void MenuRawDataBrowser(); 145 146 void DetachTab(int, bool=false);
Note:
See TracChangeset
for help on using the changeset viewer.