PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // vmatmain.cc 00004 // Copyright (C) 2002 Pascal Vincent, Julien Keable, Xavier Saint-Mleux, Rejean Ducharme 00005 // 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // 00009 // 1. Redistributions of source code must retain the above copyright 00010 // notice, this list of conditions and the following disclaimer. 00011 // 00012 // 2. Redistributions in binary form must reproduce the above copyright 00013 // notice, this list of conditions and the following disclaimer in the 00014 // documentation and/or other materials provided with the distribution. 00015 // 00016 // 3. The name of the authors may not be used to endorse or promote 00017 // products derived from this software without specific prior written 00018 // permission. 00019 // 00020 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00021 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00022 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00023 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00025 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 // 00031 // This file is part of the PLearn library. For more information on the PLearn 00032 // library, go to the PLearn Web site at www.plearn.org 00033 00034 /* ******************************************************* 00035 * $Id: vmatmain.cc 6316 2006-10-16 23:22:54Z lamblin $ 00036 ******************************************************* */ 00037 00038 #include "viewVMat.h" 00039 #include <algorithm> // for max 00040 #include <plearn/base/general.h> 00041 #include <plearn/base/stringutils.h> 00042 #include <plearn/vmat/ConcatColumnsVMatrix.h> 00043 #include <plearn/vmat/SortRowsVMatrix.h> 00044 #include <plearn/vmat/SubVMatrix.h> 00045 #include <plearn/db/getDataSet.h> 00046 00047 #if defined(WIN32) && !defined(__CYGWIN__) 00048 // There does not seem to be a Windows implementation of 'ncurses', thus we 00049 // use 'pdcurses' instead. 00050 #include <pdcurses/curses.h> 00051 #else 00052 #include "curses.h" 00053 #endif 00054 00055 // Some of the above 'curses.h' includes may define those annoying macros, 00056 // which would conflict with the code that follows. 00057 #ifdef min 00058 #undef min 00059 #endif 00060 #ifdef max 00061 #undef max 00062 #endif 00063 #ifdef clear 00064 #undef clear 00065 #endif 00066 00067 namespace PLearn { 00068 using namespace std; 00069 00070 00071 // returns false if the input is invalid and write in strReason the reason 00072 bool getList(char* str, int curj, const VMat& vm, Vec& outList, 00073 char* strReason) 00074 { 00075 vector<string>columnList; 00076 if (str[0] == '\0') 00077 { 00078 // nothing was inserted, then gets the current column 00079 char strj[10]; 00080 sprintf(strj, "%d", curj); 00081 columnList.push_back(strj); 00082 } 00083 else 00084 { 00085 columnList = split(str, " -,", true); 00086 } 00087 00088 vector<string>::iterator vsIt; 00089 00090 // checks for errors 00091 bool invalidInput = false; 00092 int colVal = 0; 00093 char separator = 0; 00094 00095 for (vsIt = columnList.begin(); vsIt != columnList.end(); vsIt++) 00096 { 00097 if (pl_isnumber(*vsIt)) 00098 { 00099 if (colVal > toint(*vsIt) && separator == '-') 00100 { 00101 invalidInput = true; 00102 strcpy(strReason, 00103 "Second element in range smaller than the first"); 00104 break; 00105 } 00106 colVal = toint(*vsIt); 00107 if (colVal < 0 || colVal >= vm->width()) 00108 { 00109 invalidInput = true; 00110 strcpy(strReason, "Invalid column number"); 00111 break; 00112 } 00113 } 00114 else 00115 { 00116 // there was already a separator! 00117 if (separator == '-') 00118 { 00119 invalidInput = true; 00120 strcpy(strReason, "Too many '-' separators"); 00121 break; 00122 } 00123 00124 separator = (*vsIt)[0]; 00125 if (separator != '-' && 00126 separator != ',') 00127 { 00128 invalidInput = true; 00129 strcpy(strReason, "Invalid column separator"); 00130 break; 00131 } 00132 } 00133 } 00134 00135 outList.clear(); 00136 if (separator == '-') 00137 { 00138 int start = toint(columnList.front()); 00139 int end = toint(columnList.back()); 00140 for (int colIdx = start; colIdx <= end; ++colIdx) 00141 outList.push_back(colIdx); 00142 } 00143 else if (separator == ',') 00144 { 00145 for (vsIt = columnList.begin(); vsIt != columnList.end(); ++vsIt) 00146 { 00147 if (pl_isnumber(*vsIt)) 00148 outList.push_back(toint(*vsIt)); 00149 } 00150 } 00151 else if (separator == 0) 00152 { 00153 outList.push_back(toint(columnList.front())); 00154 } 00155 00156 return invalidInput; 00157 } 00158 00159 void viewVMat(const VMat& vm, PPath filename) 00160 { 00161 initscr(); 00162 cbreak(); 00163 noecho(); 00164 keypad(stdscr,TRUE); 00165 00166 VMat vm_showed = vm; 00167 00168 int key = 0; 00169 bool view_strings = true; 00170 // If 'indent_strings_left' is set to false, then strings will be indented 00171 // to the right. 00172 bool indent_strings_left = true; 00179 int hide_sameval = 0; 00180 bool transposed = false; 00181 00184 bool display_filename = false; 00185 int namewidth = 0; 00186 for(int j=0; j<vm->width(); j++) 00187 namewidth = max(namewidth, (int) vm->fieldName(j).size()); 00188 int namewidth_ = namewidth; 00189 00190 int valwidth = 15; 00191 int valstrwidth = valwidth-1; 00192 00193 const char* valstrformat = "%14s"; 00194 00195 int curi = 0; 00196 int curj = 0; 00197 int starti = 0; 00198 int startj = 0; 00199 00200 int vStartHelp = 0; 00201 00202 bool onError=false; 00203 00204 map<int,Vec> cached_columns; 00205 00206 try { 00207 00208 while(key != 'q' && key != 'Q') 00209 { 00210 erase(); 00211 00212 int leftcolwidth = transposed ?1+namewidth :10; 00213 00214 int nj = transposed ? LINES-3 : (COLS-leftcolwidth)/valwidth; 00215 int ni = transposed ? (COLS-leftcolwidth)/valwidth : LINES-4; 00216 if(display_filename && filename.length()>(size_t)COLS) 00217 ni -= filename.length()/COLS; 00218 00219 int endj = min(vm_showed->width(), startj+nj); 00220 int endi = min(vm_showed->length(), starti+ni); 00221 00222 int x=0, y=0; // (curses coordinates are (y,x) ) 00223 00224 // print field names 00225 for(int j=startj; j<endj; j++) 00226 { 00227 string s = vm_showed->fieldName(j); 00228 if ( int(s.size()) > namewidth) 00229 s = s.substr(0, namewidth); 00230 00231 // if(j==curj) 00232 // attron(A_REVERSE); 00233 if(transposed) 00234 mvprintw(1+(j-startj),0,"%s", s.c_str()); 00235 else 00236 { 00237 x = 1+leftcolwidth+(j-startj)*valwidth; 00238 mvprintw(0, x, valstrformat, 00239 s.substr(0,valstrwidth).c_str() ); 00240 if((int)s.length() > valstrwidth) 00241 mvprintw(1, x, valstrformat, 00242 s.substr(valstrwidth,valstrwidth).c_str() ); 00243 } 00244 // attroff(A_REVERSE); 00245 } 00246 00247 Vec v(vm_showed.width()); 00248 Vec oldv(vm_showed.width()); 00249 00250 for(int i=starti; i<endi; i++) 00251 { 00252 if(transposed) 00253 { 00254 y = 0; 00255 x = 1+leftcolwidth+(i-starti)*valwidth; 00256 mvprintw(y,x,"%14d",i); 00257 } 00258 else 00259 { 00260 y = i-starti+2; 00261 x = 0; 00262 mvprintw(y,x,"%d",i); 00263 } 00264 00265 vm_showed->getRow(i,v); 00266 00267 for(int j=startj; j<endj; j++) 00268 { 00269 real val = v[j]; 00270 string s = vm_showed->getValString(j,val); 00271 if (!view_strings || s == "") 00272 { 00273 // We only have 14 characters, and have to display 00274 // correctly numbers like "18270326". 00275 // Best compromise found is "%14.8g". 00276 char tmp[1000]; 00277 sprintf(tmp, "%14.8g", val); 00278 s = tmp; 00279 } 00280 else { 00281 // This is a string. Maybe we want to indent it to the 00282 // right. 00283 // In this case we truncate it to its last characters. 00284 if (!indent_strings_left) { 00285 if (s.size() >= (size_t) valstrwidth) { 00286 s = s.substr(s.size() - valstrwidth, 00287 valstrwidth); 00288 } else { 00289 string added_spaces((size_t) (valstrwidth - s.size()), ' '); 00290 s = added_spaces + s; 00291 } 00292 } 00293 } 00294 00295 if(transposed) 00296 y = 1+(j-startj); 00297 else 00298 x = 1+leftcolwidth+(j-startj)*valwidth; 00299 00300 if( i == curi || (vm_showed.width() > 1 && j == curj) ) 00301 attron(A_REVERSE); 00302 //else if () 00303 // attron(A_REVERSE); 00304 00305 if(hide_sameval== 2 && i>starti && (is_equal(val,oldv[j])) ) 00306 mvprintw(y, x, valstrformat, "..."); 00307 else if(fast_exact_is_equal(hide_sameval, 1) && i>starti && 00308 (fast_exact_is_equal(val, oldv[j]) || 00309 (is_missing(val) && is_missing(oldv[j])))) 00310 mvprintw(y, x, valstrformat, "..."); 00311 else 00312 mvprintw(y, x, valstrformat, 00313 s.substr(0,valstrwidth).c_str()); 00314 00315 attroff(A_REVERSE); 00316 } 00317 oldv << v; 00318 } 00319 00320 string strval = vm_showed->getString(curi, curj); 00321 mvprintw(0,0,"Cols[%d-%d]", 0, vm_showed.width()-1); 00322 if(display_filename){ 00323 mvprintw(LINES-filename.length()/COLS-1,0,"%s",filename.c_str()); 00324 }else 00325 mvprintw(LINES-1,0, 00326 " %dx%d line= %d col= %d %s = %s (%f)", 00327 vm_showed->length(), vm_showed->width(), 00328 curi, curj, vm_showed->fieldName(curj).c_str(), 00329 strval.c_str(), vm_showed(curi,curj)); 00330 00331 refresh(); 00332 if (!onError) 00333 key = getch(); 00334 else 00335 onError = false; 00336 00338 switch(key) 00339 { 00340 case KEY_LEFT: 00341 if(transposed) 00342 { 00343 if(curi>0) 00344 --curi; 00345 if(curi<starti) 00346 starti = curi; 00347 } 00348 else 00349 { 00350 if(curj>0) 00351 --curj; 00352 if(curj<startj) 00353 startj=curj; 00354 } 00355 break; 00357 case KEY_RIGHT: 00358 if(transposed) 00359 { 00360 if(curi<vm_showed->length()-1) 00361 ++curi; 00362 if(curi>=starti+ni) 00363 ++starti; 00364 } 00365 else 00366 { 00367 if(curj<vm_showed->width()-1) 00368 ++curj; 00369 if(curj>=startj+nj) 00370 ++startj; 00371 } 00372 break; 00374 case KEY_UP: 00375 if(transposed) 00376 { 00377 if(curj>0) 00378 --curj; 00379 if(curj<startj) 00380 startj=curj; 00381 } 00382 else 00383 { 00384 if(curi>0) 00385 --curi; 00386 if(curi<starti) 00387 starti = curi; 00388 } 00389 break; 00391 case KEY_DOWN: 00392 if(transposed) 00393 { 00394 if(curj<vm_showed->width()-1) 00395 ++curj; 00396 if(curj>=startj+nj) 00397 ++startj; 00398 } 00399 else 00400 { 00401 if(curi<vm_showed->length()-1) 00402 ++curi; 00403 if(curi>=starti+ni) 00404 ++starti; 00405 } 00406 break; 00408 case KEY_PPAGE: 00409 if(transposed) 00410 { 00411 curj -= nj; 00412 startj -= nj; 00413 if(startj<0) 00414 startj = 0; 00415 if(curj<0) 00416 curj = 0; 00417 } 00418 else 00419 { 00420 curi -= ni; 00421 starti -= ni; 00422 if(starti<0) 00423 starti = 0; 00424 if(curi<0) 00425 curi = 0; 00426 } 00427 break; 00429 case KEY_NPAGE: 00430 if(transposed) 00431 { 00432 curj += nj; 00433 startj += nj; 00434 if(curj>=vm_showed->width()) 00435 curj = vm_showed->width()-1; 00436 if(startj>vm_showed->width()-nj) 00437 startj = max(0,vm_showed->width()-nj); 00438 } 00439 else 00440 { 00441 curi += ni; 00442 starti += ni; 00443 if(curi>=vm_showed->length()) 00444 curi = vm_showed->length()-1; 00445 if(starti>vm_showed->length()-ni) 00446 starti = max(0,vm_showed->length()-ni); 00447 } 00448 break; 00450 case KEY_HOME: 00451 // not working on unix for the moment: see 00452 // http://dickey.his.com/xterm/xterm.faq.html#xterm_pc_style 00453 if(transposed) 00454 { 00455 curi = 0; 00456 starti = 0; 00457 } 00458 else 00459 { 00460 curj = 0; 00461 startj = 0; 00462 } 00463 break; 00465 case KEY_END: 00466 // not working on unix for the moment: see 00467 // http://dickey.his.com/xterm/xterm.faq.html#xterm_pc_style 00468 if(transposed) 00469 { 00470 curi = vm_showed->length()-1; 00471 starti = max(curi-ni + 1, 0); 00472 } 00473 else 00474 { 00475 curj = vm_showed->width()-1; 00476 startj = max(curj-nj + 1, 0); 00477 } 00478 break; 00480 case '.': 00481 if (hide_sameval == 1) 00482 hide_sameval = 0; 00483 else 00484 hide_sameval = 1; 00485 break; 00487 case ',': 00488 if (hide_sameval == 2) 00489 hide_sameval = 0; 00490 else 00491 hide_sameval = 2; 00492 break; 00494 case 't': case 'T': 00495 transposed = !transposed; 00496 nj = transposed ? LINES-3 : (COLS-leftcolwidth)/valwidth; 00497 ni = transposed ? (COLS-leftcolwidth)/valwidth : LINES-4; 00498 starti = max(0,curi-ni/2); 00499 startj = max(0,curj-nj/2); 00500 //endj = min(vm_showed->width(), startj+nj); 00501 //endi = min(vm_showed->length(), starti+ni); 00502 break; 00504 case '/': // search for value 00505 { 00506 echo(); 00507 char strmsg[] = {"Search for value or string: "}; 00508 mvprintw(LINES-1,0,strmsg); 00509 // clear the rest of the line 00510 clrtoeol(); 00511 move(LINES-1, (int)strlen(strmsg)); 00512 char l[20]; 00513 getnstr(l, 20); 00514 string searchme = removeblanks(l); 00515 real searchval = vm_showed(curi,curj); 00516 if(searchme!="") 00517 { 00518 searchval = vm_showed->getStringVal(curj, searchme); 00519 if(is_missing(searchval)) 00520 { 00521 searchval = toreal(searchme); 00522 // This one gives a very bad error: to be changed 00523 if(is_missing(searchval)) 00524 PLERROR("Search item is neither a string with a valid mapping, nor convertible to a real"); 00525 } 00526 } 00527 00528 Vec cached; 00529 if(cached_columns.find(curj)!=cached_columns.end()) 00530 cached = cached_columns[curj]; 00531 else 00532 { 00533 mvprintw(LINES-1,0,"Building cache..."); 00534 // clear the rest of the line 00535 clrtoeol(); 00536 refresh(); 00537 cached.resize(vm_showed->length()); 00538 vm_showed->getColumn(curj,cached); 00539 cached_columns[curj] = cached; 00540 } 00541 00542 mvprintw(LINES-1,0,"Searching for value %f ...",searchval); 00543 clrtoeol(); 00544 refresh(); 00545 int curi_backup = curi; 00546 ++curi; // start searching from next row 00547 while(curi<vm_showed->length() && 00548 !fast_exact_is_equal(cached[curi], searchval)) 00549 ++curi; 00550 bool found = (curi < vm_showed->length()); 00551 if (!found) { 00552 // Try approximate match. 00553 curi = curi_backup + 1; 00554 while(curi<vm_showed->length() && 00555 !is_equal(cached[curi], searchval)) 00556 ++curi; 00557 } 00558 if(curi>=vm_showed->length()) 00559 curi = 0; 00560 ni = transposed ? (COLS-leftcolwidth)/valwidth : LINES-4; 00561 starti = max(0,curi-ni/2); 00562 } 00563 break; 00565 case (int)'l': case (int)'L': 00566 { 00567 echo(); 00568 char strmsg[] = {"Goto line: "}; 00569 mvprintw(LINES-1,0,strmsg); 00570 clrtoeol(); 00571 move(LINES-1, (int)strlen(strmsg)); 00572 char l[10]; 00573 getnstr(l, 10); 00574 if(l[0] == '\0' || !pl_isnumber(l) || toint(l) < 0 || toint(l)>=vm_showed->length()) 00575 { 00576 mvprintw(LINES-1,0,"*** Invalid line number ***"); 00577 clrtoeol(); 00578 refresh(); 00579 // wait until the user types something 00580 key = getch(); 00581 onError = true; 00582 } 00583 else 00584 { 00585 curi= toint(l); 00586 starti = max(curi-ni + 1, 0); 00587 //starti = curi; 00588 } 00589 noecho(); 00590 } 00591 break; 00593 case (int)'c': case (int)'C': 00594 { 00595 echo(); 00596 char strmsg[] = {"Goto column: "}; 00597 mvprintw(LINES-1,0,strmsg); 00598 clrtoeol(); 00599 move(LINES-1, (int)strlen(strmsg)); 00600 char c[200]; 00601 getnstr(c, 10); 00602 string the_col = c; 00603 int col_num = -1; 00604 try { 00605 col_num = vm_showed->getFieldIndex(the_col); 00606 } catch (...) {} 00607 if(col_num < 0) 00608 { 00609 mvprintw(LINES-1,0,"*** Invalid column number ***"); 00610 clrtoeol(); 00611 refresh(); 00612 // wait until the user types something 00613 key = getch(); 00614 onError = true; 00615 } 00616 else 00617 { 00618 curj = col_num; 00619 startj = max(curj-nj + 1, 0); 00620 } 00621 noecho(); 00622 } 00623 break; 00625 case (int)'v': case (int)'V': 00626 { 00627 echo(); 00628 char strmsg[] = {"View dataset ('Enter' = reload last dataset): "}; 00629 mvprintw(LINES-1,0,strmsg); 00630 clrtoeol(); 00631 move(LINES-1, (int) strlen(strmsg)); 00632 char c[200]; 00633 getnstr(c, 200); 00634 if (!string(c).empty()) 00635 filename = string(c); 00636 VMat new_vm; 00637 bool error = false; 00638 try { 00639 new_vm = getDataSet(filename); 00640 } catch(const PLearnError&) { 00641 error = true; 00642 } 00643 if (error) { 00644 mvprintw(LINES-1,0,"*** Invalid dataset ***"); 00645 clrtoeol(); 00646 refresh(); 00647 // Wait until the user types something. 00648 key = getch(); 00649 onError = true; 00650 } else { 00651 // Display the new dataset. 00652 // First close the current display. 00653 mvprintw(LINES-1,0,""); 00654 clrtoeol(); 00655 refresh(); 00656 endwin(); 00657 // And launch the new one. 00658 viewVMat(new_vm, filename); 00659 if(string(c).empty()) 00660 //if we reload, we should forget the last one 00661 key='q'; 00662 } 00663 } 00664 break; 00666 case (int)'i': case (int)'I': 00667 { 00668 echo(); 00669 char strmsg[] = {"Insert before column ('Enter' = current, '-1' = insert at the end): "}; 00670 mvprintw(LINES-1,0,strmsg); 00671 clrtoeol(); 00672 move(LINES-1, (int)strlen(strmsg)); 00673 char l[10]; 00674 getnstr(l, 10); 00675 int ins_col = curj; 00676 if (l[0] != '\0') { 00677 if (!pl_isnumber(l) || toint(l) < -1 || toint(l)>=vm_showed->width()) { 00678 mvprintw(LINES-1,0,"*** Invalid column number ***"); 00679 clrtoeol(); 00680 refresh(); 00681 // wait until the user types something 00682 key = getch(); 00683 onError = true; 00684 noecho(); 00685 break; 00686 } else { 00687 ins_col = toint(l); 00688 } 00689 } 00690 if (ins_col == -1) 00691 ins_col = vm_showed->width(); 00692 char strmsg2[] = {"Name of the column to insert ('Enter' = column number): "}; 00693 mvprintw(LINES-1,0,strmsg2); 00694 clrtoeol(); 00695 move(LINES-1, (int)strlen(strmsg2)); 00696 char l2[100]; 00697 getnstr(l2, 100); 00698 string ins_name = tostring(ins_col); 00699 if (l2[0] != '\0') { 00700 ins_name = l2; 00701 } 00702 char strmsg3[] = {"Default value ('Enter' = 0): "}; 00703 mvprintw(LINES-1,0,strmsg3); 00704 clrtoeol(); 00705 move(LINES-1, (int)strlen(strmsg3)); 00706 char l3[100]; 00707 getnstr(l3, 100); 00708 string default_val = tostring(0); 00709 if (l3[0] != '\0') { 00710 default_val = l3; 00711 } 00712 TVec<VMat> vmats; 00713 if (ins_col > 0) 00714 vmats.append(new SubVMatrix(vm_showed, 0, 0, 00715 vm_showed->length(), ins_col)); 00716 Mat col_mat(vm_showed->length(), 1); 00717 VMat col_vmat(col_mat); 00718 col_vmat->declareFieldNames(TVec<string>(1, ins_name)); 00719 real val; 00720 if (pl_isnumber(default_val, &val)) 00721 col_mat.fill(val); 00722 else { 00723 col_mat.fill(-1000); 00724 col_vmat->addStringMapping(0, default_val, -1000); 00725 } 00726 vmats.append(col_vmat); 00727 if (ins_col < vm_showed->width()) 00728 vmats.append(new SubVMatrix(vm_showed, 0, ins_col, 00729 vm_showed->length(), 00730 vm_showed->width() - ins_col)); 00731 vm_showed = new ConcatColumnsVMatrix(vmats); 00732 mvprintw(LINES-1,0,"*** Inserted column '%s' at position %d with default value %s ***", 00733 ins_name.c_str(), ins_col, default_val.c_str()); 00734 clrtoeol(); 00735 refresh(); 00736 // Wait for a key to be pressed. 00737 key = getch(); 00738 noecho(); 00739 } 00740 break; 00742 case (int)'e': case (int)'E': 00743 { 00744 echo(); 00745 char strmsg[100]; 00746 sprintf(strmsg, "Enter column(s) or range (ex: 7;1-20;7,8,12) to export (enter=%d): ", curj); 00747 mvprintw(LINES-1,0,strmsg); 00748 clrtoeol(); 00749 00750 move(LINES-1, (int)strlen(strmsg)); 00751 char strRange[50]; 00752 getnstr(strRange, 50); 00753 00754 Vec indexs; 00755 char strReason[100] = {"\0"}; 00756 bool invalidInput = getList(strRange, curj, vm_showed, indexs, 00757 strReason); 00758 00759 if (invalidInput) 00760 { 00761 mvprintw(LINES-1,0,"*** Invalid input: %s ***", strReason); 00762 clrtoeol(); 00763 refresh(); 00764 // wait until the user types something 00765 key = getch(); 00766 onError = true; 00767 } 00768 else 00769 { 00770 00771 char filemsg[] = {"Enter file name (enter=outCol.txt): "}; 00772 mvprintw(LINES-1,0,filemsg); 00773 clrtoeol(); 00774 00775 move(LINES-1, (int)strlen(filemsg)); 00776 char fname[200]; 00777 getnstr(fname, 200); 00778 00779 if (fname[0] == '\0') 00780 strcpy(fname, "outCol.txt"); 00781 string fname_str = fname; 00782 00783 mvprintw(LINES-1,0,"Writing file '%s'...", fname); 00784 clrtoeol(); 00785 refresh(); 00786 00787 // Save the selected columns to the desired file, keeping 00788 // the string values if 'view_strings' is currently true 00789 // (can be toggled with 's'/'S' keys). 00790 vm_showed.columns(indexs)->saveAMAT(fname_str, false, 00791 false, view_strings); 00792 00793 mvprintw(LINES-1,0,"*** Output written on: %s ***", fname); 00794 clrtoeol(); 00795 refresh(); 00796 // wait until the user types something 00797 key = getch(); 00798 00799 } 00800 00801 noecho(); 00802 } 00803 break; 00805 case (int)'r': case (int)'R': 00806 { 00807 echo(); 00808 char strmsg[100]; 00809 sprintf(strmsg, "Enter column(s) or range (ex: 7;1-20;7,8,12) to view (enter=%d): ", curj); 00810 mvprintw(LINES-1,0,strmsg); 00811 clrtoeol(); 00812 00813 move(LINES-1, (int)strlen(strmsg)); 00814 char c[50]; 00815 getnstr(c, 50); 00816 00817 Vec indexs; 00818 char strReason[100] = {"\0"}; 00819 bool invalidInput = getList(c, curj, vm_showed, indexs, 00820 strReason); 00821 00822 if (invalidInput) 00823 { 00824 mvprintw(LINES-1,0,"*** Invalid input: %s ***", strReason); 00825 clrtoeol(); 00826 refresh(); 00827 // wait until the user types something 00828 key = getch(); 00829 onError = true; 00830 } 00831 else 00832 { 00833 vm_showed = vm_showed.columns(indexs); 00834 if (curj>=vm_showed.width()) 00835 { 00836 curj = vm_showed.width()-1; 00837 startj = max(curj-nj + 1, 0); 00838 } 00839 } 00840 00841 noecho(); 00842 } 00843 break; 00845 case (int)'x': case (int)'X': 00846 // Hide the currently selected row. 00847 { 00848 //echo(); 00849 Vec index(vm_showed.width() - 1); 00850 for (int i = 0; i < curj; i++) { 00851 index[i] = i; 00852 } 00853 for (int i = curj + 1; i < vm_showed.width(); i++) { 00854 index[i - 1] = i; 00855 } 00856 vm_showed = vm_showed.columns(index); 00857 if (curj>=vm_showed.width()) { 00858 curj = vm_showed.width()-1; 00859 startj = max(curj-nj + 1, 0); 00860 } 00861 00862 // noecho(); 00863 } 00864 break; 00866 case (int)'<': case (int)'>': 00867 // Sort by increasing or decreasing order. 00868 { 00869 PP<SortRowsVMatrix> new_vm; 00870 if(vm_showed->classname()!="SortRowsVMatrix" 00871 || ((PP<SortRowsVMatrix>)vm_showed)->sort_columns[0]!=curj){ 00872 //if it is a SortRowsVMatrix and we sort on a new column 00873 // we can't reuse the last SortRowsVMatrix as it don't suport 00874 // different order on each row. 00875 new_vm = new SortRowsVMatrix(); 00876 new_vm->source = vm_showed; 00877 vm_showed = get_pointer(new_vm); 00878 } else 00879 //in the case where we sort multiple time on the same column 00880 //we reuse the last VMatrix. 00881 new_vm= (PP<SortRowsVMatrix>)vm_showed; 00882 new_vm->sort_columns = TVec<int>(1, curj); 00883 if (key == (int)'>') 00884 new_vm->increasing_order = false; 00885 else 00886 new_vm->increasing_order = true; 00887 new_vm->build(); 00888 } 00889 break; 00891 case (int)'a': case (int)'A': 00892 vm_showed = vm; 00893 break; 00895 case (int)'n': case (int)'N': 00896 if ( namewidth != namewidth_ ) 00897 namewidth = namewidth_; 00898 else 00899 { 00900 int def = (namewidth < 80) ? namewidth : 80; 00901 00902 echo(); 00903 char strmsg[100]; 00904 sprintf(strmsg, "Enter namewidth to use (between 10 and %d -- enter=%d): ", 00905 namewidth, def); 00906 mvprintw(LINES-1,0,strmsg); 00907 clrtoeol(); 00908 00909 move(LINES-1, (int)strlen(strmsg)); 00910 char l[10]; 00911 getnstr(l, 10); 00912 if(l[0] == '\0') 00913 { 00914 namewidth = def; 00915 } 00916 else if( !pl_isnumber(l) || toint(l) < 0 || toint(l)>namewidth ) 00917 { 00918 mvprintw(LINES-1,0,"*** Invalid line number ***"); 00919 clrtoeol(); 00920 refresh(); 00921 // wait until the user types something 00922 key = getch(); 00923 onError = true; 00924 } 00925 else 00926 { 00927 namewidth = toint(l); 00928 } 00929 noecho(); 00930 } 00931 break; 00933 case (int)'s': 00934 if (indent_strings_left) 00935 // Toggle display. 00936 view_strings = !view_strings; 00937 else { 00938 // Do not remove display if we only asked to change 00939 // indentation. 00940 indent_strings_left = true; 00941 if (!view_strings) 00942 view_strings = true; 00943 } 00944 break; 00945 case (int)'S': 00946 // Same as above, except we indent to the right. 00947 if (!indent_strings_left) 00948 view_strings = !view_strings; 00949 else { 00950 indent_strings_left = false; 00951 if (!view_strings) 00952 view_strings = true; 00953 } 00954 break; 00956 case (int)'h': case (int)'H': 00957 erase(); 00958 00959 vStartHelp = 2; 00960 00961 mvprintw(0,COLS/2-6,"*** HELP ***"); 00962 00963 mvprintw(vStartHelp++,10,"KEYS:"); 00964 mvprintw(vStartHelp++,10," - up: move up one line"); 00965 mvprintw(vStartHelp++,10," - down: move down one line"); 00966 mvprintw(vStartHelp++,10," - right: move right one column"); 00967 mvprintw(vStartHelp++,10," - left: move left one column"); 00968 mvprintw(vStartHelp++,10," - page up: move up one screen"); 00969 mvprintw(vStartHelp++,10," - page down: move down one screen"); 00970 mvprintw(vStartHelp++,10," - home: move to the first column"); 00971 mvprintw(vStartHelp++,10," - end: move to the last column"); 00972 mvprintw(vStartHelp++,10," - 'r' or 'R': show only a range or a set of columns"); 00973 mvprintw(vStartHelp++,10," - 'x' or 'X': hide the currently selected column"); 00974 mvprintw(vStartHelp++,10," - 'a' or 'A': show the original VMat"); 00975 mvprintw(vStartHelp++,10," - 'f' or 'F': toggle the display of the filename"); 00976 mvprintw(vStartHelp++,10," - 'i' or 'I': insert a new column with default value"); 00977 mvprintw(vStartHelp++,10," - 'l' or 'L': prompt for a line number and go to that line"); 00978 mvprintw(vStartHelp++,10," - 'c' or 'C': prompt for a column number and go to that column"); 00979 mvprintw(vStartHelp++,10," - 's' or 'S': toggle display string fields as strings or numbers ('S' = right indentation)"); 00980 mvprintw(vStartHelp++,10," - 't' or 'T': toggle transposed display mode"); 00981 mvprintw(vStartHelp++,10," - 'n' or 'N': toggle truncated field name display mode (under transposed display mode)"); 00982 mvprintw(vStartHelp++,10," - 'e' or 'E': export a range or a set of columns to file"); 00983 mvprintw(vStartHelp++,10," - 'v' or 'V': prompt for another dataset to view"); 00984 mvprintw(vStartHelp++,10," - '.' : toggle displaying of ... for values that do not change (exact match)"); 00985 mvprintw(vStartHelp++,10," - ',' : toggle displaying of ... for values that do not change (approximate match)"); 00986 mvprintw(vStartHelp++,10," - '/' : search for a value of the current field"); 00987 mvprintw(vStartHelp++,10," - '<' or '>': sort column by increasing or decreasing order"); 00988 mvprintw(vStartHelp++,10," - 'h' or 'H': display this screen"); 00989 mvprintw(vStartHelp++,10," - 'q' or 'Q': quit program"); 00990 mvprintw(vStartHelp++,COLS/2-13,"(press any key to continue)"); 00991 00992 refresh(); 00993 getch(); 00994 00995 break; 00996 00997 case (int)'f': case (int)'F': 00998 display_filename = !display_filename; 00999 01000 case (int)'q': case (int)'Q': 01001 break; 01002 01004 default: 01005 mvprintw(LINES-1,0,"*** Invalid command (type 'h' for help) ***"); 01006 // clear the rest of the line 01007 clrtoeol(); 01008 01009 refresh(); 01010 01011 // wait until the user types something 01012 key = getch(); 01013 onError = true; 01014 01015 //sleep(1); 01016 break; 01017 } 01018 } 01019 } // end try 01020 catch(const PLearnError& e) 01021 { 01022 endwin(); 01023 throw(e); 01024 } 01025 01026 // make sure it is clean 01027 mvprintw(LINES-1,0,""); 01028 clrtoeol(); 01029 refresh(); 01030 01031 endwin(); 01032 } 01033 01034 01035 BEGIN_DECLARE_REMOTE_FUNCTIONS 01036 01037 declareFunction("viewVMat", &viewVMat, 01038 (BodyDoc("Displays a VMat's contents using curses.\n"), 01039 ArgDoc("vm", 01040 "the VMat to display"), 01041 ArgDoc("filename", 01042 "optional filename of the dataset, that may be used to reload it (\"\" works just fine)"))); 01043 01044 END_DECLARE_REMOTE_FUNCTIONS 01045 01046 01047 } // end of namespace PLearn 01048 01049 01050 /* 01051 Local Variables: 01052 mode:c++ 01053 c-basic-offset:4 01054 c-file-style:"stroustrup" 01055 c-file-offsets:((innamespace . 0)(inline-open . 0)) 01056 indent-tabs-mode:nil 01057 fill-column:79 01058 End: 01059 */ 01060 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :