|
Isis 3.0 Object Programmers' Reference |
Home |
00001 00020 #include "IsisDebug.h" 00021 #include "CubeViewport.h" 00022 00023 #include <iomanip> 00024 #include <iostream> 00025 #include <QApplication> 00026 #include <QCloseEvent> 00027 #include <QCursor> 00028 #include <QDebug> 00029 #include <QIcon> 00030 #include <QPen> 00031 #include <QPainter> 00032 #include <QFileInfo> 00033 #include <QMessageBox> 00034 #include <QMouseEvent> 00035 #include <QRgb> 00036 #include <QScrollBar> 00037 #include <QString> 00038 #include <QTimer> 00039 00040 #include "Brick.h" 00041 #include "Camera.h" 00042 #include "CubeDataThread.h" 00043 #include "IException.h" 00044 #include "IString.h" 00045 #include "FileName.h" 00046 #include "Histogram.h" 00047 #include "Pvl.h" 00048 #include "PvlGroup.h" 00049 #include "PvlKeyword.h" 00050 #include "PvlObject.h" 00051 #include "Stretch.h" 00052 #include "StretchTool.h" 00053 #include "Tool.h" 00054 #include "UniversalGroundMap.h" 00055 #include "ViewportBuffer.h" 00056 00057 00058 using namespace std; 00059 00060 00061 namespace Isis { 00069 CubeViewport::CubeViewport(Cube *cube, CubeDataThread * cubeData, 00070 QWidget *parent) : QAbstractScrollArea(parent) { 00071 // Is the cube usable? 00072 if(cube == NULL) { 00073 throw IException(IException::Programmer, 00074 "Can not view NULL cube pointer", 00075 _FILEINFO_); 00076 } 00077 else if(!cube->isOpen()) { 00078 throw IException(IException::Programmer, 00079 "Can not view unopened cube", 00080 _FILEINFO_); 00081 } 00082 00083 p_cube = cube; 00084 p_cubeData = NULL; 00085 00086 if (cubeData) 00087 { 00088 p_cubeData = cubeData; 00089 p_thisOwnsCubeData = false; 00090 p_cubeId = p_cubeData->FindCubeId(cube); 00091 } 00092 else 00093 { 00094 p_cubeData = new CubeDataThread(); 00095 p_thisOwnsCubeData = true; 00096 p_cubeId = p_cubeData->AddCube(p_cube); 00097 } 00098 00099 00100 connect(p_cubeData, SIGNAL(BrickChanged(int, const Isis::Brick *)), 00101 this, SLOT(cubeDataChanged(int, const Isis::Brick *))); 00102 connect(this, SIGNAL(doneWithData(int, const Isis::Brick *)), 00103 p_cubeData, SLOT(DoneWithData(int, const Isis::Brick *))); 00104 00105 p_cubeData->AddChangeListener(); 00106 00107 void doneWithData(int, const Brick *); 00108 00109 // Set up the scroll area 00110 setAttribute(Qt::WA_DeleteOnClose); 00111 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 00112 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 00113 viewport()->setObjectName("viewport"); 00114 viewport()->setCursor(QCursor(Qt::CrossCursor)); 00115 viewport()->installEventFilter(this); 00116 viewport()->setAttribute(Qt::WA_OpaquePaintEvent); 00117 00118 setAttribute(Qt::WA_NoSystemBackground); 00119 setFrameShadow(QFrame::Plain); 00120 setFrameShape(QFrame::NoFrame); 00121 setAutoFillBackground(false); 00122 00123 // viewport()->setAttribute(Qt::WA_NoSystemBackground); 00124 // viewport()->setAttribute(Qt::WA_PaintOnScreen,false); 00125 00126 p_saveEnabled = false; 00127 // Save off info about the cube 00128 p_scale = -1.0; 00129 p_color = false; 00130 00131 00132 setCaption(); 00133 00134 p_redBrick = new Brick(4, 1, 1, cube->pixelType()); 00135 p_grnBrick = new Brick(4, 1, 1, cube->pixelType()); 00136 p_bluBrick = new Brick(4, 1, 1, cube->pixelType()); 00137 p_gryBrick = new Brick(4, 1, 1, cube->pixelType()); 00138 p_pntBrick = new Brick(4, 1, 1, cube->pixelType()); 00139 00140 p_paintPixmap = false; 00141 p_image = NULL; 00142 p_cubeShown = true; 00143 p_updatingBuffers = false; 00144 00145 //updateScrollBars(1,1); 00146 00147 p_groundMap = NULL; 00148 p_projection = NULL; 00149 p_camera = NULL; 00150 00151 // Setup a universal ground map 00152 try { 00153 p_groundMap = new UniversalGroundMap(*p_cube); 00154 } 00155 catch(IException &) { 00156 } 00157 00158 if(p_groundMap != NULL) { 00159 // Setup the camera or the projection 00160 if(p_groundMap->Camera() != NULL) { 00161 p_camera = p_groundMap->Camera(); 00162 if(p_camera->HasProjection()) { 00163 try { 00164 p_projection = cube->projection(); 00165 } 00166 catch(IException &) { 00167 } 00168 } 00169 } 00170 else { 00171 p_projection = p_groundMap->Projection(); 00172 } 00173 } 00174 00175 00176 // Setup context sensitive help 00177 QString cubeFileName = p_cube->fileName(); 00178 p_whatsThisText = QString("<b>Function: </b>Viewport to ") + cubeFileName; 00179 00180 p_cubeWhatsThisText = 00181 "<p><b>Cube Dimensions:</b> \ 00182 <blockQuote>Samples = " + 00183 QString::number(cube->sampleCount()) + "<br>" + 00184 "Lines = " + 00185 QString::number(cube->lineCount()) + "<br>" + 00186 "Bands = " + 00187 QString::number(cube->bandCount()) + "</blockquote></p>"; 00188 00189 /*setting up the qlist of CubeBandsStretch objs. 00190 for( int b = 0; b < p_cube->bandCount(); b++) { 00191 CubeBandsStretch *stretch = new CubeBandsStretch(); 00192 p_bandsStretchList.push_back(stretch); 00193 }*/ 00194 00195 p_grayBuffer = new ViewportBuffer(this, p_cubeData, p_cubeId); 00196 p_grayBuffer->enable(false); 00197 p_grayBuffer->setBand(1); 00198 00199 p_redBuffer = NULL; 00200 p_greenBuffer = NULL; 00201 p_blueBuffer = NULL; 00202 p_pixmapPaintRects = NULL; 00203 00204 p_pixmapPaintRects = new QList<QRect *>(); 00205 p_progressTimer = new QTimer(); 00206 p_progressTimer->setInterval(250); 00207 00208 p_knownStretches = new QVector< Stretch * >(); 00209 p_globalStretches = new QVector< Stretch * >(); 00210 00211 while(p_cube->bandCount() > p_knownStretches->size()) { 00212 p_knownStretches->push_back(NULL); 00213 p_globalStretches->push_back(NULL); 00214 } 00215 00216 connect(p_progressTimer, SIGNAL(timeout()), this, SLOT(onProgressTimer())); 00217 00218 p_bgColor = Qt::black; 00219 } 00220 00221 00227 void CubeViewport::showEvent(QShowEvent *event) { 00228 if(p_scale == -1) { 00229 // This doesn't equal fitScale() ... causes misalignment in qview initial 00230 // view versus zoomFit 00231 //double sampScale = (double) sizeHint().width() / (double) cubeSamples(); 00232 //double lineScale = (double) sizeHint().height() / (double) cubeLines(); 00233 //double scale = sampScale < lineScale ? sampScale : lineScale; 00234 00235 setScale(fitScale(), cubeSamples() / 2.0, cubeLines() / 2.0); 00236 } 00237 00238 if(p_grayBuffer && !p_grayBuffer->enabled()) { 00239 p_grayBuffer->enable(true); 00240 00241 // gives a proper initial stretch (entire cube) 00242 p_grayBuffer->addStretchAction(); 00243 } 00244 00245 QAbstractScrollArea::show(); 00246 00247 p_paintPixmap = true; 00248 00249 paintPixmap(); 00250 } 00251 00252 00257 void CubeViewport::onProgressTimer() { 00258 double progress = 0.0; 00259 bool completed = false; 00260 00261 if(p_grayBuffer) { 00262 progress += p_grayBuffer->currentProgress(); 00263 completed = !p_grayBuffer->working(); 00264 } 00265 00266 if(p_redBuffer) { 00267 progress += p_redBuffer->currentProgress() / 3.0; 00268 completed = !p_redBuffer->working(); 00269 } 00270 00271 if(p_greenBuffer) { 00272 progress += p_greenBuffer->currentProgress() / 3.0; 00273 completed = completed && !p_greenBuffer->working(); 00274 } 00275 00276 if(p_blueBuffer) { 00277 progress += p_blueBuffer->currentProgress() / 3.0; 00278 completed = completed && !p_blueBuffer->working(); 00279 } 00280 00281 int realProgress = (int)(progress * 100.0); 00282 00283 if(completed) { 00284 realProgress = 100; 00285 p_progressTimer->stop(); 00286 emit screenPixelsChanged(); 00287 } 00288 else if(realProgress == 100) { 00289 realProgress = 99; 00290 } 00291 00292 emit progressChanged(realProgress); 00293 } 00294 00295 00300 CubeViewport::~CubeViewport() { 00301 if(p_redBrick) { 00302 delete p_redBrick; 00303 p_redBrick = NULL; 00304 } 00305 00306 if(p_grnBrick) { 00307 delete p_grnBrick; 00308 p_grnBrick = NULL; 00309 } 00310 00311 if(p_bluBrick) { 00312 delete p_bluBrick; 00313 p_bluBrick = NULL; 00314 } 00315 00316 if(p_gryBrick) { 00317 delete p_gryBrick; 00318 p_gryBrick = NULL; 00319 } 00320 00321 if(p_pntBrick) { 00322 delete p_pntBrick; 00323 p_pntBrick = NULL; 00324 } 00325 00326 if(p_groundMap) { 00327 delete p_groundMap; 00328 p_groundMap = NULL; 00329 } 00330 00331 if(p_grayBuffer) { 00332 delete p_grayBuffer; 00333 p_grayBuffer = NULL; 00334 } 00335 00336 if(p_redBuffer) { 00337 delete p_redBuffer; 00338 p_redBuffer = NULL; 00339 } 00340 00341 if(p_greenBuffer) { 00342 delete p_greenBuffer; 00343 p_greenBuffer = NULL; 00344 } 00345 00346 if(p_blueBuffer) { 00347 delete p_blueBuffer; 00348 p_blueBuffer = NULL; 00349 } 00350 00351 // p_cubeData MUST be deleted AFTER all viewport buffers!!! 00352 if(p_cubeData) { 00353 p_cubeData->RemoveChangeListener(); 00354 00355 if(p_thisOwnsCubeData) 00356 delete p_cubeData; 00357 00358 p_cubeData = NULL; 00359 } 00360 00361 p_cube = NULL; 00362 00363 if(p_progressTimer) { 00364 delete p_progressTimer; 00365 p_progressTimer = NULL; 00366 } 00367 00368 if(p_image) { 00369 delete p_image; 00370 p_image = NULL; 00371 } 00372 00373 if(p_pixmapPaintRects) { 00374 for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) { 00375 delete(*p_pixmapPaintRects)[rect]; 00376 } 00377 00378 delete p_pixmapPaintRects; 00379 p_pixmapPaintRects = NULL; 00380 } 00381 00382 if(p_knownStretches) { 00383 for(int stretch = 0; stretch < p_knownStretches->size(); stretch ++) { 00384 if((*p_knownStretches)[stretch] != NULL) { 00385 delete(*p_knownStretches)[stretch]; 00386 (*p_knownStretches)[stretch] = NULL; 00387 } 00388 } 00389 00390 p_knownStretches->clear(); 00391 00392 delete p_knownStretches; 00393 p_knownStretches = NULL; 00394 } 00395 00396 if(p_globalStretches) { 00397 for(int stretch = 0; stretch < p_globalStretches->size(); stretch ++) { 00398 if((*p_globalStretches)[stretch] != NULL) { 00399 delete(*p_globalStretches)[stretch]; 00400 (*p_globalStretches)[stretch] = NULL; 00401 } 00402 } 00403 00404 p_globalStretches->clear(); 00405 00406 delete p_globalStretches; 00407 p_globalStretches = NULL; 00408 } 00409 } 00410 00416 void CubeViewport::setCube(Cube *cube) { 00417 p_cube = cube; 00418 setCaption(); 00419 } 00420 00421 00423 int CubeViewport::cubeSamples() const { 00424 return p_cube->sampleCount(); 00425 } 00426 00427 00429 int CubeViewport::cubeLines() const { 00430 return p_cube->lineCount(); 00431 } 00432 00433 00435 int CubeViewport::cubeBands() const { 00436 return p_cube->bandCount(); 00437 } 00438 00439 00447 void CubeViewport::cubeDataChanged(int cubeId, const Brick *data) { 00448 if(cubeId == p_cubeId) { 00449 double ss, sl, es, el; 00450 ss = data->Sample(); 00451 sl = data->Line(); 00452 es = data->Sample() + data->SampleDimension(); 00453 el = data->Line() + data->LineDimension(); 00454 if(ss < 0.5){ 00455 ss = 0.5; 00456 } 00457 if(sl < 0.5){ 00458 sl = 0.5; 00459 } 00460 if(es > cube()->sampleCount() + 0.5){ 00461 es = cube()->sampleCount() + 0.5; 00462 } 00463 if(el > cube()->lineCount() + 0.5){ 00464 el = cube()->lineCount() + 0.5; 00465 } 00466 00467 int sx, sy, ex, ey; 00468 00469 cubeToViewport(ss, sl, sx, sy); 00470 cubeToViewport(es, el, ex, ey); 00471 if(sx < 0){ 00472 sx = 0; 00473 } 00474 if(sy < 0){ 00475 sy = 0; 00476 } 00477 if(ex > viewport()->width()){ 00478 ex = viewport()->width(); 00479 } 00480 if(ey > viewport()->height()){ 00481 ey = viewport()->height(); 00482 } 00483 QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1); 00484 00485 p_updatingBuffers = true; 00486 if(p_grayBuffer){ 00487 p_grayBuffer->fillBuffer(vpRect, data); 00488 } 00489 if(p_redBuffer){ 00490 p_redBuffer->fillBuffer(vpRect, data); 00491 } 00492 if(p_greenBuffer){ 00493 p_greenBuffer->fillBuffer(vpRect, data); 00494 } 00495 if(p_blueBuffer){ 00496 p_blueBuffer->fillBuffer(vpRect, data); 00497 } 00498 p_updatingBuffers = false; 00499 00500 paintPixmapRects(); 00501 } 00502 00503 emit doneWithData(cubeId, data); 00504 } 00505 00506 00515 bool CubeViewport::confirmClose() { 00516 bool canClose = true; 00517 if(p_saveEnabled) { 00518 // Enter == button 0, Escape == button 2 00519 switch(QMessageBox::information(this, tr("Confirm Save"), 00520 tr("The cube [<font color='red'>%1</font>] contains unsaved changes. " 00521 "Do you want to save the changes before exiting?").arg(cube()->fileName()), 00522 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) { 00523 //Save changes and close viewport 00524 case QMessageBox::Save: 00525 emit saveChanges(this); 00526 break; 00527 00528 //Discard changes and close viewport 00529 case QMessageBox::Discard: 00530 emit discardChanges(this); 00531 break; 00532 00533 //Cancel, don't close viewport 00534 case QMessageBox::Cancel: 00535 default: 00536 canClose = false; 00537 break; 00538 } 00539 } 00540 00541 // if (canClose) emit viewportClosed(this); 00542 return canClose; 00543 } 00544 00551 void CubeViewport::cubeChanged(bool changed) { 00552 p_saveEnabled = changed; 00553 } 00554 00561 QSize CubeViewport::sizeHint() const { 00562 QSize s(512, 512); 00563 return s; 00564 } 00565 00566 00578 void CubeViewport::setScale(double scale) { 00579 // Sanitize the scale value 00580 if(scale == p_scale){ 00581 return; 00582 } 00583 00584 if (viewport()->width() && viewport()->height()) { 00585 // don't let zoom scale be larger than the viewport size 00586 double maxScale = max(viewport()->width(),viewport()->height()); 00587 if (scale > maxScale) { 00588 scale = maxScale; 00589 } 00590 // don't let zoom scale be smaller than one pixel high/wide showing 00591 double minScale = 1.0 / (min(cubeSamples(),cubeLines())); 00592 if (scale < minScale) { 00593 scale = minScale; 00594 } 00595 } 00596 00597 // Resize the scrollbars to reflect the new scale 00598 double samp, line; 00599 contentsToCube(horizontalScrollBar()->value(), verticalScrollBar()->value(), 00600 samp, line); 00601 p_scale = scale; 00602 updateScrollBars(1, 1); // Setting to 1,1 make sure we don't have bad values 00603 00604 // Now update the scroll bar value to the old line/sample 00605 int x, y; 00606 cubeToContents(samp, line, x, y); 00607 updateScrollBars(x, y); 00608 00609 p_updatingBuffers = true; 00610 if(p_grayBuffer){ 00611 p_grayBuffer->scaleChanged(); 00612 } 00613 if(p_redBuffer){ 00614 p_redBuffer->scaleChanged(); 00615 } 00616 if(p_greenBuffer){ 00617 p_greenBuffer->scaleChanged(); 00618 } 00619 if(p_blueBuffer){ 00620 p_blueBuffer->scaleChanged(); 00621 } 00622 p_updatingBuffers = false; 00623 00624 paintPixmapRects(); 00625 00626 // Notify other tools about the scale change 00627 emit scaleChanged(); 00628 00629 // Update the display 00630 setCaption(); 00631 paintPixmap(); // Will get rid of old data in the display 00632 00633 viewport()->repaint(); 00634 emit screenPixelsChanged(); 00635 } 00636 00645 void CubeViewport::setScale(double scale, int x, int y) { 00646 double samp, line; 00647 viewportToCube(x, y, samp, line); 00648 setScale(scale, samp, line); 00649 } 00650 00651 00661 void CubeViewport::setScale(double scale, double sample, double line) { 00662 viewport()->setUpdatesEnabled(false); 00663 00664 bool wasEnabled = false; 00665 00666 if((p_grayBuffer && p_grayBuffer->enabled()) || 00667 (p_redBuffer && p_redBuffer->enabled())) { 00668 wasEnabled = true; 00669 } 00670 00671 if(p_grayBuffer){ 00672 p_grayBuffer->enable(false); 00673 } 00674 if(p_redBuffer){ 00675 p_redBuffer->enable(false); 00676 } 00677 if(p_greenBuffer){ 00678 p_greenBuffer->enable(false); 00679 } 00680 if(p_blueBuffer){ 00681 p_blueBuffer->enable(false); 00682 } 00683 if(p_paintPixmap) { 00684 p_paintPixmap = false; 00685 setScale(scale); 00686 p_paintPixmap = true; 00687 } 00688 else { 00689 setScale(scale); 00690 } 00691 00692 center(sample, line); 00693 00694 if(p_grayBuffer){ 00695 p_grayBuffer->enable(wasEnabled); 00696 } 00697 if(p_redBuffer){ 00698 p_redBuffer->enable(wasEnabled); 00699 } 00700 if(p_greenBuffer){ 00701 p_greenBuffer->enable(wasEnabled); 00702 } 00703 if(p_blueBuffer){ 00704 p_blueBuffer->enable(wasEnabled); 00705 } 00706 00707 paintPixmap(); 00708 viewport()->setUpdatesEnabled(true); 00709 viewport()->update(); 00710 emit screenPixelsChanged(); 00711 } 00712 00713 00721 void CubeViewport::center(int x, int y) { 00722 double sample, line; 00723 viewportToCube(x, y, sample, line); 00724 center(sample, line); 00725 } 00726 00727 00735 void CubeViewport::center(double sample, double line) { 00736 int x, y; 00737 cubeToContents(sample, line, x, y); 00738 00739 x ++; 00740 y ++; 00741 00742 int panX = horizontalScrollBar()->value() - x; 00743 int panY = verticalScrollBar()->value() - y; 00744 00745 updateScrollBars(x, y); 00746 00747 p_updatingBuffers = true; 00748 if(p_grayBuffer){ 00749 p_grayBuffer->pan(panX, panY); 00750 } 00751 if(p_redBuffer){ 00752 p_redBuffer->pan(panX, panY); 00753 } 00754 if(p_greenBuffer){ 00755 p_greenBuffer->pan(panX, panY); 00756 } 00757 if(p_blueBuffer){ 00758 p_blueBuffer->pan(panX, panY); 00759 } 00760 p_updatingBuffers = false; 00761 00762 paintPixmapRects(); 00763 00764 shiftPixmap(panX, panY); 00765 00766 emit screenPixelsChanged(); 00767 } 00768 00769 00774 void CubeViewport::paintPixmapRects() { 00775 for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) { 00776 paintPixmap(*(*p_pixmapPaintRects)[rect]); 00777 } 00778 00779 p_pixmapPaintRects->clear(); 00780 } 00781 00782 00793 void CubeViewport::contentsToCube(int x, int y, 00794 double &sample, double &line) const { 00795 sample = x / p_scale; 00796 line = y / p_scale; 00797 } 00798 00799 00810 void CubeViewport::viewportToCube(int x, int y, 00811 double &sample, double &line) const { 00812 x += horizontalScrollBar()->value(); 00813 x -= viewport()->width() / 2; 00814 y += verticalScrollBar()->value(); 00815 y -= viewport()->height() / 2; 00816 contentsToCube(x, y, sample, line); 00817 } 00818 00819 00830 void CubeViewport::cubeToContents(double sample, double line, 00831 int &x, int &y) const { 00832 x = (int)(sample * p_scale + 0.5); 00833 y = (int)(line * p_scale + 0.5); 00834 } 00835 00836 00847 void CubeViewport::cubeToViewport(double sample, double line, 00848 int &x, int &y) const { 00849 cubeToContents(sample, line, x, y); 00850 x -= horizontalScrollBar()->value(); 00851 x += viewport()->width() / 2; 00852 y -= verticalScrollBar()->value(); 00853 y += viewport()->height() / 2; 00854 } 00855 00856 00864 void CubeViewport::scrollBy(int dx, int dy) { 00865 // Make sure we don't generate bad values outside of the scroll range 00866 int x = horizontalScrollBar()->value() + dx; 00867 if(x <= 1) { 00868 dx = 1 - horizontalScrollBar()->value(); 00869 } 00870 else if(x >= horizontalScrollBar()->maximum()) { 00871 dx = horizontalScrollBar()->maximum() - horizontalScrollBar()->value(); 00872 } 00873 00874 // Make sure we don't generate bad values outside of the scroll range 00875 int y = verticalScrollBar()->value() + dy; 00876 if(y <= 1) { 00877 dy = 1 - verticalScrollBar()->value(); 00878 } 00879 else if(y >= verticalScrollBar()->maximum()) { 00880 dy = verticalScrollBar()->maximum() - verticalScrollBar()->value(); 00881 } 00882 00883 // Do we do anything? 00884 if((dx == 0) && (dy == 0)){ 00885 return; 00886 } 00887 00888 // We do so update the scroll bars 00889 updateScrollBars(horizontalScrollBar()->value() + dx, 00890 verticalScrollBar()->value() + dy); 00891 00892 // Scroll the the pixmap 00893 scrollContentsBy(-dx, -dy); 00894 } 00895 00896 00904 void CubeViewport::scrollContentsBy(int dx, int dy) { 00905 00906 // We shouldn't do anything if scrollbars are being updated 00907 if(viewport()->signalsBlocked()) { 00908 return; 00909 } 00910 00911 // Tell the buffers to update appropriate for the pan and upon completion 00912 // they will call bufferUpdated. We don't want bufferUpdated to happen 00913 // until afterwards. If only shrinking and no new data then the viewport 00914 // buffers will complete immediately. When all buffers don't have their 00915 // appropriate actions queued bufferUpdated can't succeed. 00916 00917 // Also block paints because we'll repaint it all when we're done 00918 // telling each buffer about the pan. 00919 bool panQueued = false; 00920 QRect bufferXYRect; 00921 00922 p_updatingBuffers = true; 00923 00924 if(p_grayBuffer) { 00925 p_grayBuffer->pan(dx, dy); 00926 panQueued |= p_grayBuffer->working(); 00927 bufferXYRect = p_grayBuffer->bufferXYRect(); 00928 } 00929 00930 if(p_redBuffer) { 00931 p_redBuffer->pan(dx, dy); 00932 panQueued |= p_redBuffer->working(); 00933 bufferXYRect = p_redBuffer->bufferXYRect(); 00934 } 00935 00936 if(p_greenBuffer) { 00937 p_greenBuffer->pan(dx, dy); 00938 panQueued |= p_greenBuffer->working(); 00939 } 00940 00941 if(p_blueBuffer) { 00942 p_blueBuffer->pan(dx, dy); 00943 panQueued |= p_blueBuffer->working(); 00944 } 00945 00946 p_updatingBuffers = false; 00947 00948 // shift the pixmap by x,y if the viewport buffer didn't do it immediately 00949 if(panQueued) { 00950 shiftPixmap(dx, dy); 00951 } 00952 else { 00953 // Need to do this to clear area outside of cube 00954 p_pixmapPaintRects->clear(); 00955 paintPixmap(); 00956 } 00957 00958 viewport()->update(); 00959 emit screenPixelsChanged(); 00960 } 00961 00962 00967 void CubeViewport::enableProgress() { 00968 if(!p_progressTimer->isActive()) { 00969 p_progressTimer->start(); 00970 00971 emit progressChanged(0); 00972 } 00973 } 00974 00975 00980 void CubeViewport::setCaption() { 00981 QString cubeFileName = p_cube->fileName(); 00982 QString str = QFileInfo(cubeFileName).fileName(); 00983 str += QString(" @ "); 00984 str += QString::number(p_scale * 100.0); 00985 str += QString("% "); 00986 00987 if(p_color) { 00988 str += QString("(RGB = "); 00989 str += QString::number(p_red.band); 00990 str += QString(","); 00991 str += QString::number(p_green.band); 00992 str += QString(","); 00993 str += QString::number(p_blue.band); 00994 str += QString(")"); 00995 } 00996 else { 00997 str += QString("(Gray = "); 00998 str += QString::number(p_gray.band); 00999 str += QString(")"); 01000 } 01001 01002 //If changes have been made make sure to add '*' to the end 01003 if(p_saveEnabled) { 01004 str += "*"; 01005 } 01006 01007 parentWidget()->setWindowTitle(str); 01008 emit windowTitleChanged(); 01009 } 01010 01011 01018 void CubeViewport::resizeEvent(QResizeEvent *e) { 01019 p_paintPixmap = false; 01020 01021 // Tell the buffers to update their coefficients to reinitialize 01022 // and have their immediate paint events happen afterwards. Should not 01023 // happen, but if buffers have actions complete immediately and call 01024 // bufferUpdated. We don't want to have bufferUpdated ever when all 01025 // buffers don't have their appropriate actions queued. It can't succeed. 01026 p_updatingBuffers = true; 01027 if(p_grayBuffer){ 01028 p_grayBuffer->resizedViewport(); 01029 } 01030 if(p_redBuffer){ 01031 p_redBuffer->resizedViewport(); 01032 } 01033 if(p_greenBuffer){ 01034 p_greenBuffer->resizedViewport(); 01035 } 01036 if(p_blueBuffer){ 01037 p_blueBuffer->resizedViewport(); 01038 } 01039 p_updatingBuffers = false; 01040 01041 paintPixmapRects(); 01042 01043 // Change the size of the image and pixmap 01044 if(p_image) { 01045 delete p_image; 01046 p_image = NULL; 01047 } 01048 01049 p_image = new QImage(viewport()->size(), QImage::Format_RGB32); 01050 p_pixmap = QPixmap(viewport()->size()); 01051 01052 p_paintPixmap = true; 01053 01054 // Fixup the scroll bars 01055 updateScrollBars(horizontalScrollBar()->value(), 01056 verticalScrollBar()->value()); 01057 01058 p_viewportWhatsThisText = 01059 "<p><b>Viewport Dimensions:</b> \ 01060 <blockQuote>Samples = " + 01061 QString::number(viewport()->width()) + "<br>" + 01062 "Lines = " + 01063 QString::number(viewport()->height()) + "</blockquote></p>"; 01064 01065 // Repaint the pixmap 01066 paintPixmap(); 01067 01068 // Repaint the internal viewport and scroll bars 01069 viewport()->update(); 01070 emit screenPixelsChanged(); 01071 } 01072 01073 01084 void CubeViewport::paintEvent(QPaintEvent *e) { 01085 if(!p_cubeShown || !viewport()->isVisible()){ 01086 return; 01087 } 01088 } 01089 01090 01099 void CubeViewport::bufferUpdated(QRect rect) { 01100 paintPixmap(rect); 01101 01102 // Don't repaint from buffer updates if any buffers are working... 01103 // This set of statements fixes a flash of black when in RGB mode 01104 // and a pan (or other operation?) completes. What would happen is 01105 // the first would reset to black then other buffers still working so 01106 // not restored to DN values. 01107 if(p_grayBuffer && p_grayBuffer->working()){ 01108 return; 01109 } 01110 if(p_redBuffer && p_redBuffer->working()){ 01111 return; 01112 } 01113 if(p_greenBuffer && p_greenBuffer->working()){ 01114 return; 01115 } 01116 if(p_blueBuffer && p_blueBuffer->working()){ 01117 return; 01118 } 01119 01120 viewport()->repaint(rect); 01121 } 01122 01124 void CubeViewport::paintPixmap() { 01125 QRect rect(0, 0, p_image->width(), p_image->height()); 01126 paintPixmap(rect); 01127 } 01128 01129 01136 void CubeViewport::paintPixmap(QRect rect) { 01137 if(!p_paintPixmap) { 01138 return; 01139 } 01140 01141 if(p_updatingBuffers) { 01142 p_pixmapPaintRects->push_back(new QRect(rect)); 01143 return; 01144 } 01145 01146 if(p_pixmap.isNull()){ 01147 return; 01148 } 01149 01150 QPainter p(&p_pixmap); 01151 01152 p.fillRect(rect, QBrush(p_bgColor)); 01153 01154 QRect dataArea; 01155 01156 if(p_grayBuffer && p_grayBuffer->enabled()) { 01157 if(p_grayBuffer->working()){ 01158 return; 01159 } 01160 01161 dataArea = QRect(p_grayBuffer->bufferXYRect().intersected(rect)); 01162 01163 for(int y = dataArea.top(); 01164 !dataArea.isNull() && y <= dataArea.bottom(); 01165 y++) { 01166 const vector< double > & line = 01167 p_grayBuffer->getLine(y - p_grayBuffer->bufferXYRect().top()); 01168 01169 if(line.size() == 0) { 01170 break; 01171 } 01172 01173 if(y >= p_image->height()) { 01174 throw IException(IException::Programmer, "y too big", _FILEINFO_); 01175 } 01176 01177 QRgb *rgb = (QRgb *) p_image->scanLine(y); 01178 01179 for(int x = dataArea.left(); x <= dataArea.right(); x++) { 01180 int bufferLeft = p_grayBuffer->bufferXYRect().left(); 01181 int bufferX = x - bufferLeft; 01182 01183 if(bufferX >= (int)line.size()){ 01184 break; 01185 } 01186 01187 if(bufferX < 0) { 01188 throw IException(IException::Programmer, "bufferX < 0", _FILEINFO_); 01189 } 01190 01191 if(x >= p_image->width()) { 01192 throw IException(IException::Programmer, "x too big", _FILEINFO_); 01193 } 01194 01195 double bufferVal = line.at(bufferX); 01196 01197 // This is still RGB; the pairs are identical but the boundary 01198 // conditions are different. Display saturations cause this. 01199 int redPix = (int)(p_red.getStretch().Map(bufferVal) + 0.5); 01200 int greenPix = (int)(p_green.getStretch().Map(bufferVal) + 0.5); 01201 int bluePix = (int)(p_blue.getStretch().Map(bufferVal) + 0.5); 01202 rgb[x] = qRgb(redPix, greenPix, bluePix); 01203 } 01204 } 01205 } 01206 else { 01207 if(p_redBuffer && p_redBuffer->enabled()) { 01208 if(p_redBuffer->working() || p_greenBuffer->working() || 01209 p_blueBuffer->working()) { 01210 return; 01211 } 01212 01213 01214 if((p_greenBuffer->bufferXYRect().top() != 01215 p_redBuffer->bufferXYRect().top()) || 01216 (p_greenBuffer->bufferXYRect().top() != 01217 p_blueBuffer->bufferXYRect().top())) { 01218 throw IException(IException::Programmer, 01219 "Buffer rects mismatched", 01220 _FILEINFO_); 01221 } 01222 01223 if((p_greenBuffer->bufferXYRect().left() != 01224 p_redBuffer->bufferXYRect().left()) || 01225 (p_greenBuffer->bufferXYRect().left() != 01226 p_blueBuffer->bufferXYRect().left())) { 01227 throw IException(IException::Programmer, 01228 "Buffer rects mismatched", 01229 _FILEINFO_); 01230 } 01231 01232 dataArea = QRect(p_redBuffer->bufferXYRect().intersected(rect)); 01233 01234 for(int y = dataArea.top(); 01235 !dataArea.isNull() && y <= dataArea.bottom(); 01236 y++) { 01237 int bufferLine = y - p_redBuffer->bufferXYRect().top(); 01238 01239 const vector<double> &redLine = p_redBuffer->getLine(bufferLine); 01240 const vector<double> &greenLine = p_greenBuffer->getLine(bufferLine); 01241 const vector<double> &blueLine = p_blueBuffer->getLine(bufferLine); 01242 01243 if((int)redLine.size() < dataArea.width() || 01244 (int)greenLine.size() < dataArea.width() || 01245 (int)blueLine.size() < dataArea.width()) { 01246 throw IException(IException::Programmer, 01247 "Empty buffer line", 01248 _FILEINFO_); 01249 } 01250 01251 QRgb *rgb = (QRgb *) p_image->scanLine(y); 01252 01253 for(int x = dataArea.left(); x <= dataArea.right(); x++) { 01254 int redPix = (int)(p_red.getStretch().Map(redLine[ x - p_redBuffer->bufferXYRect().left()]) + 0.5); 01255 int greenPix = (int)(p_green.getStretch().Map(greenLine[ x - p_greenBuffer->bufferXYRect().left()]) + 0.5); 01256 int bluePix = (int)(p_blue.getStretch().Map(blueLine[ x - p_blueBuffer->bufferXYRect().left()]) + 0.5); 01257 01258 rgb[x] = qRgb(redPix, greenPix, bluePix); 01259 } 01260 } 01261 } 01262 } 01263 01264 if(!dataArea.isNull()){ 01265 p.drawImage(dataArea.topLeft(), *p_image, dataArea); 01266 } 01267 01268 // Change whats this info 01269 updateWhatsThis(); 01270 } 01271 01272 01279 void CubeViewport::shiftPixmap(int dx, int dy) { 01280 if(!p_paintPixmap || !p_pixmap){ 01281 return; 01282 } 01283 01284 // Prep to scroll the pixmap 01285 int drawStartX = dx; 01286 int pixmapStartX = 0; 01287 if(drawStartX < 0) { 01288 drawStartX = 0; 01289 pixmapStartX = -dx; 01290 } 01291 01292 int drawStartY = dy; 01293 int pixmapStartY = 0; 01294 if(dy < 0) { 01295 drawStartY = 0; 01296 pixmapStartY = -dy; 01297 } 01298 01299 // Ok we can shift the pixmap and filling 01300 int pixmapDrawWidth = p_pixmap.width() - pixmapStartX + 1; 01301 int pixmapDrawHeight = p_pixmap.height() - pixmapStartY + 1; 01302 01303 QRect rect(0, 0, p_pixmap.width(), p_pixmap.height()); 01304 QPixmap pixmapCopy = p_pixmap.copy(); 01305 01306 QPainter painter(&p_pixmap); 01307 painter.fillRect(rect, QBrush(p_bgColor)); 01308 painter.drawPixmap(drawStartX, drawStartY, 01309 pixmapCopy, 01310 pixmapStartX, pixmapStartY, 01311 pixmapDrawWidth, pixmapDrawHeight); 01312 painter.end(); 01313 01314 // Now fill in the left or right side 01315 QRect xFillRect; 01316 QRect yFillRect; 01317 01318 if(dx > 0) { 01319 xFillRect = QRect(QPoint(0, 0), 01320 QPoint(dx, p_pixmap.height())); 01321 } 01322 else { 01323 if(dx < 0){ 01324 xFillRect = QRect(QPoint(p_pixmap.width() + dx, 0), 01325 QPoint(p_pixmap.width(), p_pixmap.height())); 01326 } 01327 } 01328 01329 // Fill in the top or bottom side 01330 if(dy > 0) { 01331 yFillRect = QRect(QPoint(0, 0), 01332 QPoint(p_pixmap.width(), dy)); 01333 } 01334 else { 01335 if(dy < 0){ 01336 yFillRect = QRect(QPoint(0, p_pixmap.height() + dy), 01337 QPoint(p_pixmap.width(), p_pixmap.height())); 01338 } 01339 } 01340 01341 if(dx != 0) { 01342 paintPixmap(xFillRect); 01343 } 01344 01345 if(dy != 0) { 01346 paintPixmap(yFillRect); 01347 } 01348 01349 viewport()->update(); 01350 } 01351 01359 void CubeViewport::getAllWhatsThisInfo(Pvl & pWhatsThisPvl) 01360 { 01361 // Get Cube Info 01362 PvlObject whatsThisObj = PvlObject("WhatsThis"); 01363 whatsThisObj += PvlKeyword("Cube", p_cube->fileName()); 01364 01365 PvlGroup cubeGrp("CubeDimensions"); 01366 cubeGrp += PvlKeyword("Samples", toString(p_cube->sampleCount())); 01367 cubeGrp += PvlKeyword("Lines", toString(p_cube->lineCount())); 01368 cubeGrp += PvlKeyword("Bands", toString(p_cube->bandCount())); 01369 whatsThisObj += cubeGrp; 01370 01371 // Get Viewport Info 01372 PvlGroup viewportGrp("ViewportDimensions"); 01373 viewportGrp += PvlKeyword("Samples", toString(viewport()->width())); 01374 viewportGrp += PvlKeyword("Lines", toString(viewport()->height())); 01375 whatsThisObj += viewportGrp; 01376 01377 // Get Cube area Info 01378 PvlObject cubeAreaPvl("CubeArea"); 01379 PvlGroup bandGrp("Bands"); 01380 01381 PvlKeyword filterName; 01382 getBandFilterName(filterName); 01383 int iFilterSize = filterName.Size(); 01384 01385 // color 01386 if(p_color ) { 01387 PvlKeyword virtualKey("Virtual"), physicalKey("Physical"), filterNameKey; 01388 int iRedBand = p_redBuffer->getBand(); 01389 int iGreenBand = p_greenBuffer->getBand(); 01390 int iBlueBand = p_blueBuffer->getBand(); 01391 01392 bandGrp += PvlKeyword("Color", "RGB"); 01393 01394 virtualKey = toString(iRedBand); 01395 virtualKey += toString(iGreenBand); 01396 virtualKey += toString(iBlueBand); 01397 bandGrp += virtualKey; 01398 01399 physicalKey = toString(p_cube->physicalBand(iRedBand)); 01400 physicalKey += toString(p_cube->physicalBand(iGreenBand)); 01401 physicalKey += toString(p_cube->physicalBand(iBlueBand)); 01402 bandGrp += physicalKey; 01403 01404 if(iFilterSize) { 01405 if(iRedBand <= iFilterSize) { 01406 filterNameKey += filterName[iRedBand-1]; 01407 } 01408 else { 01409 filterNameKey += "None"; 01410 } 01411 01412 if(iGreenBand <= iFilterSize) { 01413 filterNameKey += filterName[iGreenBand-1]; 01414 } 01415 else { 01416 filterNameKey += "None"; 01417 } 01418 01419 if(iBlueBand <= iFilterSize) { 01420 filterNameKey += filterName[iBlueBand-1]; 01421 } 01422 else { 01423 filterNameKey += "None"; 01424 } 01425 bandGrp += filterNameKey; 01426 } 01427 } 01428 else { // gray 01429 int iGrayBand = p_grayBuffer->getBand(); 01430 01431 bandGrp += PvlKeyword("Color", "Gray"); 01432 01433 bandGrp += PvlKeyword("Virtual", toString(iGrayBand)); 01434 bandGrp += PvlKeyword("Physical", toString(p_cube->physicalBand(iGrayBand))); 01435 01436 if(iFilterSize && iGrayBand <= iFilterSize) { 01437 bandGrp += PvlKeyword("FilterName", filterName[iGrayBand-1]); 01438 } 01439 } 01440 01441 //start, end line and sample 01442 double sl, ss, es, el; 01443 getCubeArea(ss, es, sl, el); 01444 cubeAreaPvl += PvlKeyword("StartSample", toString(int(ss + 0.5))); 01445 cubeAreaPvl += PvlKeyword("EndSample", toString(int(es + 0.5))); 01446 cubeAreaPvl += PvlKeyword("StartLine", toString(int(sl + 0.5))); 01447 cubeAreaPvl += PvlKeyword("EndLine", toString(int(el + 0.5))); 01448 cubeAreaPvl += bandGrp; 01449 whatsThisObj += cubeAreaPvl; 01450 pWhatsThisPvl += whatsThisObj; 01451 } 01452 01461 void CubeViewport::getBandFilterName(PvlKeyword & pFilterNameKey) 01462 { 01463 // get the band info 01464 Pvl* cubeLbl = p_cube->label(); 01465 PvlObject isisObj = cubeLbl->FindObject("IsisCube"); 01466 if (isisObj.HasGroup("BandBin")) { 01467 PvlGroup bandBinGrp = isisObj.FindGroup("BandBin"); 01468 if(bandBinGrp.HasKeyword("FilterName")) { 01469 pFilterNameKey =bandBinGrp.FindKeyword("FilterName") ; 01470 } 01471 } 01472 } 01473 01482 void CubeViewport::getCubeArea(double & pdStartSample, double & pdEndSample, 01483 double & pdStartLine, double & pdEndLine) 01484 { 01485 viewportToCube(0, 0, pdStartSample, pdStartLine); 01486 if(pdStartSample < 1.0){ 01487 pdStartSample = 1.0; 01488 } 01489 if(pdStartLine < 1.0){ 01490 pdStartLine = 1.0; 01491 } 01492 01493 //end line and samples 01494 viewportToCube(viewport()->width() - 1, viewport()->height() - 1, pdEndSample, pdEndLine); 01495 if(pdEndSample > cubeSamples()){ 01496 pdEndSample = cubeSamples(); 01497 } 01498 if(pdEndLine > cubeLines()){ 01499 pdEndLine = cubeLines(); 01500 } 01501 } 01502 01507 void CubeViewport::updateWhatsThis() { 01508 //start, end line and sample 01509 double sl, ss, es, el; 01510 getCubeArea(ss, es, sl, el); 01511 01512 QString sBandInfo ; 01513 PvlKeyword filterNameKey; 01514 getBandFilterName(filterNameKey); 01515 int iFilterSize = filterNameKey.Size(); 01516 01517 // color 01518 if(p_color ) { 01519 int iRedBand = p_redBuffer->getBand(); 01520 int iGreenBand = p_greenBuffer->getBand(); 01521 int iBlueBand = p_blueBuffer->getBand(); 01522 01523 sBandInfo = "Bands(RGB) Virtual = " + 01524 QString::number(iRedBand) + ", "; 01525 sBandInfo += QString::number(iGreenBand) + ", "; 01526 sBandInfo += QString::number(iBlueBand) + " "; 01527 01528 sBandInfo += "Physical = " + 01529 QString::number(p_cube->physicalBand(iRedBand)) + ", "; 01530 sBandInfo += QString::number(p_cube->physicalBand(iGreenBand)) + ", "; 01531 sBandInfo += QString::number(p_cube->physicalBand(iBlueBand)); 01532 01533 if(iFilterSize) { 01534 sBandInfo += "<br>FilterName = "; 01535 if(iRedBand <= iFilterSize) { 01536 sBandInfo += QString(filterNameKey[iRedBand-1]); 01537 } 01538 else { 01539 sBandInfo += "None"; 01540 } 01541 sBandInfo += ", "; 01542 01543 if(iGreenBand <= iFilterSize) { 01544 sBandInfo += QString(filterNameKey[iGreenBand-1]); 01545 } 01546 else { 01547 sBandInfo += "None"; 01548 } 01549 sBandInfo += ", "; 01550 01551 if(iBlueBand <= iFilterSize) { 01552 sBandInfo += QString(filterNameKey[iBlueBand-1]); 01553 } 01554 else { 01555 sBandInfo += "None"; 01556 } 01557 } 01558 } 01559 else { // gray 01560 int iGrayBand = p_grayBuffer->getBand(); 01561 01562 sBandInfo = "Band(Gray) Virtual = " + QString::number(iGrayBand) + " "; 01563 01564 sBandInfo += "Physical = " + QString::number(p_cube->physicalBand(iGrayBand)); 01565 01566 if(iFilterSize && iGrayBand <= iFilterSize) { 01567 sBandInfo += "<br>FilterName = " + QString(filterNameKey[iGrayBand-1]); 01568 } 01569 } 01570 01571 QString area = 01572 "<p><b>Visible Cube Area:</b><blockQuote> \ 01573 Samples = " + QString::number(int(ss + 0.5)) + "-" + 01574 QString::number(int(es + 0.5)) + "<br> \ 01575 Lines = " + QString::number(int(sl + 0.5)) + "-" + 01576 QString::number(int(el + 0.5)) + "<br> " + 01577 sBandInfo + "</blockQuote></p>"; 01578 01579 viewport()->setWhatsThis(p_whatsThisText + area + p_cubeWhatsThisText + 01580 p_viewportWhatsThisText); 01581 } 01582 01592 double CubeViewport::redPixel(int sample, int line) { 01593 p_pntBrick->SetBasePosition(sample, line, p_red.band); 01594 p_cube->read(*p_pntBrick); 01595 return (*p_pntBrick)[0]; 01596 } 01597 01598 01608 double CubeViewport::greenPixel(int sample, int line) { 01609 p_pntBrick->SetBasePosition(sample, line, p_green.band); 01610 p_cube->read(*p_pntBrick); 01611 return (*p_pntBrick)[0]; 01612 } 01613 01614 01624 double CubeViewport::bluePixel(int sample, int line) { 01625 p_pntBrick->SetBasePosition(sample, line, p_blue.band); 01626 p_cube->read(*p_pntBrick); 01627 return (*p_pntBrick)[0]; 01628 } 01629 01630 01640 double CubeViewport::grayPixel(int sample, int line) { 01641 p_pntBrick->SetBasePosition(sample, line, p_gray.band); 01642 p_cube->read(*p_pntBrick); 01643 return (*p_pntBrick)[0]; 01644 } 01645 01646 01648 Stretch CubeViewport::grayStretch() const { 01649 return p_gray.getStretch(); 01650 } 01651 01652 01654 Stretch CubeViewport::redStretch() const { 01655 return p_red.getStretch(); 01656 }; 01657 01658 01660 Stretch CubeViewport::greenStretch() const { 01661 return p_green.getStretch(); 01662 }; 01663 01664 01666 Stretch CubeViewport::blueStretch() const { 01667 return p_blue.getStretch(); 01668 }; 01669 01670 01680 bool CubeViewport::eventFilter(QObject *o, QEvent *e) { 01681 // Handle standard mouse tracking on the viewport 01682 if(o == viewport()) { 01683 switch(e->type()) { 01684 case QEvent::Enter: { 01685 viewport()->setMouseTracking(true); 01686 emit mouseEnter(); 01687 return true; 01688 } 01689 01690 case QEvent::MouseMove: { 01691 QMouseEvent *m = (QMouseEvent *) e; 01692 emit mouseMove(m->pos()); 01693 emit mouseMove(m->pos(), (Qt::MouseButton)(m->button() + 01694 m->modifiers())); 01695 return true; 01696 } 01697 01698 case QEvent::Leave: { 01699 viewport()->setMouseTracking(false); 01700 emit mouseLeave(); 01701 return true; 01702 } 01703 01704 case QEvent::MouseButtonPress: { 01705 QMouseEvent *m = (QMouseEvent *) e; 01706 emit mouseButtonPress(m->pos(), 01707 (Qt::MouseButton)(m->button() + m->modifiers())); 01708 return true; 01709 } 01710 01711 case QEvent::MouseButtonRelease: { 01712 QMouseEvent *m = (QMouseEvent *) e; 01713 emit mouseButtonRelease(m->pos(), 01714 (Qt::MouseButton)(m->button() + m->modifiers())); 01715 return true; 01716 } 01717 01718 case QEvent::MouseButtonDblClick: { 01719 QMouseEvent *m = (QMouseEvent *) e; 01720 emit mouseDoubleClick(m->pos()); 01721 return true; 01722 } 01723 01724 default: { 01725 return false; 01726 } 01727 } 01728 } 01729 else { 01730 return QAbstractScrollArea::eventFilter(o, e); 01731 } 01732 } 01733 01734 01741 void CubeViewport::keyPressEvent(QKeyEvent *e) { 01742 if(e->key() == Qt::Key_Plus) { 01743 double scale = p_scale * 2.0; 01744 setScale(scale); 01745 e->accept(); 01746 } 01747 else if(e->key() == Qt::Key_Minus) { 01748 double scale = p_scale / 2.0; 01749 setScale(scale); 01750 e->accept(); 01751 } 01752 else if(e->key() == Qt::Key_Up) { 01753 moveCursor(0, -1); 01754 e->accept(); 01755 } 01756 else if(e->key() == Qt::Key_Down) { 01757 moveCursor(0, 1); 01758 e->accept(); 01759 } 01760 else if(e->key() == Qt::Key_Left) { 01761 moveCursor(-1, 0); 01762 e->accept(); 01763 } 01764 else if(e->key() == Qt::Key_Right) { 01765 moveCursor(1, 0); 01766 e->accept(); 01767 } 01768 else { 01769 QAbstractScrollArea::keyPressEvent(e); 01770 } 01771 } 01772 01773 01780 bool CubeViewport::cursorInside() const { 01781 QPoint g = QCursor::pos(); 01782 QPoint v = viewport()->mapFromGlobal(g); 01783 if(v.x() < 0){ 01784 return false; 01785 } 01786 if(v.y() < 0){ 01787 return false; 01788 } 01789 if(v.x() >= viewport()->width()){ 01790 return false; 01791 } 01792 if(v.y() >= viewport()->height()){ 01793 return false; 01794 } 01795 return true; 01796 } 01797 01798 01805 QPoint CubeViewport::cursorPosition() const { 01806 QPoint g = QCursor::pos(); 01807 return viewport()->mapFromGlobal(g); 01808 } 01809 01810 01818 void CubeViewport::moveCursor(int x, int y) { 01819 QPoint g = QCursor::pos(); 01820 g += QPoint(x, y); 01821 QPoint v = viewport()->mapFromGlobal(g); 01822 if(v.x() < 0){ 01823 return; 01824 } 01825 if(v.y() < 0){ 01826 return; 01827 } 01828 if(v.x() >= viewport()->width()){ 01829 return; 01830 } 01831 if(v.y() >= viewport()->height()){ 01832 return; 01833 } 01834 QCursor::setPos(g); 01835 } 01836 01837 01845 void CubeViewport::setCursorPosition(int x, int y) { 01846 QPoint g(x, y); 01847 QPoint v = viewport()->mapToGlobal(g); 01848 QCursor::setPos(v); 01849 } 01850 01851 01859 void CubeViewport::updateScrollBars(int x, int y) { 01860 viewport()->blockSignals(true); 01861 01862 verticalScrollBar()->setValue(1); 01863 verticalScrollBar()->setMinimum(1); 01864 verticalScrollBar()->setMaximum((int)(ceil(cubeLines() * p_scale) + 0.5)); 01865 verticalScrollBar()->setPageStep(viewport()->height() / 2); 01866 01867 horizontalScrollBar()->setValue(1); 01868 horizontalScrollBar()->setMinimum(1); 01869 horizontalScrollBar()->setMaximum((int)(ceil(cubeSamples() * p_scale) + 0.5)); 01870 horizontalScrollBar()->setPageStep(viewport()->width() / 2); 01871 01872 if(horizontalScrollBar()->value() != x || verticalScrollBar()->value() != y) { 01873 horizontalScrollBar()->setValue(x); 01874 verticalScrollBar()->setValue(y); 01875 emit scaleChanged(); 01876 } 01877 01878 QApplication::sendPostedEvents(viewport(), 0); 01879 viewport()->blockSignals(false); 01880 } 01881 01882 01889 void CubeViewport::viewGray(int band) { 01890 p_gray.band = band; 01891 p_color = false; 01892 setCaption(); 01893 01894 if(!p_grayBuffer){ 01895 p_grayBuffer = new ViewportBuffer(this, p_cubeData, 01896 p_cubeId); 01897 } 01898 01899 if(p_redBuffer){ 01900 delete p_redBuffer; 01901 } 01902 p_redBuffer = NULL; 01903 01904 if(p_greenBuffer){ 01905 delete p_greenBuffer; 01906 } 01907 p_greenBuffer = NULL; 01908 01909 if(p_blueBuffer){ 01910 delete p_blueBuffer; 01911 } 01912 p_blueBuffer = NULL; 01913 01914 if(p_grayBuffer->getBand() != band) { 01915 int oldBand = p_grayBuffer->getBand(); 01916 01917 if(oldBand >= 0) { 01918 if((*p_knownStretches)[oldBand - 1]) { 01919 delete(*p_knownStretches)[oldBand - 1]; 01920 } 01921 01922 (*p_knownStretches)[oldBand - 1] = new Stretch(p_gray.getStretch()); 01923 } 01924 01925 p_grayBuffer->setBand(band); 01926 p_gray.band = band; 01927 01928 if((*p_knownStretches)[band - 1]) { 01929 stretchGray(*(*p_knownStretches)[band - 1]); 01930 } 01931 else { 01932 p_grayBuffer->addStretchAction(); 01933 } 01934 } 01935 01936 01937 if(p_camera) { 01938 p_camera->SetBand(band); 01939 } 01940 01941 viewport()->repaint(); 01942 } 01943 01944 void CubeViewport::forgetStretches() { 01945 for(int stretch = 0; stretch < p_knownStretches->size(); stretch++) { 01946 if((*p_knownStretches)[stretch]) { 01947 delete(*p_knownStretches)[stretch]; 01948 (*p_knownStretches)[stretch] = NULL; 01949 } 01950 } 01951 } 01952 01953 01954 void CubeViewport::setAllBandStretches(Stretch stretch) { 01955 for(int index = 0; index < p_knownStretches->size(); index ++) { 01956 if((*p_knownStretches)[index]) { 01957 delete(*p_knownStretches)[index]; 01958 } 01959 01960 (*p_knownStretches)[index] = new Stretch(stretch); 01961 } 01962 } 01963 01964 01973 void CubeViewport::viewRGB(int rband, int gband, int bband) { 01974 p_red.band = rband; 01975 p_green.band = gband; 01976 p_blue.band = bband; 01977 p_color = true; 01978 setCaption(); 01979 01980 if(!p_redBuffer) { 01981 p_redBuffer = new ViewportBuffer(this, p_cubeData, p_cubeId); 01982 } 01983 01984 if(!p_greenBuffer) { 01985 p_greenBuffer = new ViewportBuffer(this, p_cubeData, p_cubeId); 01986 } 01987 01988 if(!p_blueBuffer) { 01989 p_blueBuffer = new ViewportBuffer(this, p_cubeData, p_cubeId); 01990 } 01991 01992 if(p_redBuffer->getBand() != rband) { 01993 int oldBand = p_redBuffer->getBand(); 01994 01995 // Remember current stretch for future band changes 01996 if(oldBand >= 0) { 01997 if((*p_knownStretches)[oldBand - 1]) { 01998 delete(*p_knownStretches)[oldBand - 1]; 01999 } 02000 02001 (*p_knownStretches)[oldBand - 1] = new Stretch(p_red.getStretch()); 02002 } 02003 02004 p_redBuffer->setBand(rband); 02005 p_red.band = rband; 02006 02007 if((*p_knownStretches)[rband - 1]) { 02008 p_red.setStretch(*(*p_knownStretches)[rband - 1]); 02009 } 02010 else { 02011 p_redBuffer->addStretchAction(); 02012 } 02013 } 02014 02015 if(p_greenBuffer->getBand() != gband) { 02016 int oldBand = p_greenBuffer->getBand(); 02017 02018 // Remember current stretch for future band changes 02019 if(oldBand >= 0) { 02020 if((*p_knownStretches)[oldBand - 1]) { 02021 delete(*p_knownStretches)[oldBand - 1]; 02022 } 02023 02024 (*p_knownStretches)[oldBand - 1] = new Stretch(p_green.getStretch()); 02025 } 02026 02027 p_greenBuffer->setBand(gband); 02028 p_green.band = gband; 02029 02030 if((*p_knownStretches)[gband - 1]) { 02031 p_green.setStretch(*(*p_knownStretches)[gband - 1]); 02032 } 02033 else { 02034 p_greenBuffer->addStretchAction(); 02035 } 02036 } 02037 02038 if(p_blueBuffer->getBand() != bband) { 02039 int oldBand = p_blueBuffer->getBand(); 02040 02041 // Remember current stretch for future band changes 02042 if(oldBand >= 0) { 02043 if((*p_knownStretches)[oldBand - 1]) { 02044 delete(*p_knownStretches)[oldBand - 1]; 02045 } 02046 02047 (*p_knownStretches)[oldBand - 1] = new Stretch(p_blue.getStretch()); 02048 } 02049 02050 p_blueBuffer->setBand(bband); 02051 p_blue.band = bband; 02052 02053 if((*p_knownStretches)[bband - 1]) { 02054 p_blue.setStretch(*(*p_knownStretches)[bband - 1]); 02055 } 02056 else { 02057 p_blueBuffer->addStretchAction(); 02058 } 02059 } 02060 02061 if(p_grayBuffer){ 02062 delete p_grayBuffer; 02063 } 02064 p_grayBuffer = NULL; 02065 02066 if(p_camera) { 02067 p_camera->SetBand(rband); 02068 } 02069 } 02070 02071 02078 void CubeViewport::stretchGray(const QString &string) { 02079 Stretch stretch; 02080 stretch.Parse(string); 02081 stretchGray(stretch); 02082 } 02083 02084 02090 void CubeViewport::stretchRed(const QString &string) { 02091 Stretch stretch; 02092 stretch.Parse(string); 02093 stretchRed(stretch); 02094 } 02095 02096 02102 void CubeViewport::stretchGreen(const QString &string) { 02103 Stretch stretch; 02104 stretch.Parse(string); 02105 stretchGreen(stretch); 02106 } 02107 02108 02114 void CubeViewport::stretchBlue(const QString &string) { 02115 Stretch stretch; 02116 stretch.Parse(string); 02117 stretchBlue(stretch); 02118 } 02119 02120 02124 void CubeViewport::stretchKnownGlobal() { 02125 if(!p_globalStretches){ 02126 return; 02127 } 02128 02129 if(isGray()) { 02130 if((*p_globalStretches)[grayBand() - 1]) { 02131 stretchGray(*(*p_globalStretches)[grayBand() - 1]); 02132 } 02133 } 02134 else { 02135 if((*p_globalStretches)[redBand() - 1]) { 02136 stretchRed(*(*p_globalStretches)[redBand() - 1]); 02137 } 02138 02139 if((*p_globalStretches)[greenBand() - 1]) { 02140 stretchGreen(*(*p_globalStretches)[greenBand() - 1]); 02141 } 02142 02143 if((*p_globalStretches)[blueBand() - 1]) { 02144 stretchBlue(*(*p_globalStretches)[blueBand() - 1]); 02145 } 02146 } 02147 } 02148 02149 02155 void CubeViewport::stretchGray(const Stretch &stretch) { 02156 // Assume first stretch is always the global stretch (and it should be) 02157 if((*p_globalStretches)[grayBand() - 1] == NULL && stretch.Pairs()) { 02158 (*p_globalStretches)[grayBand() - 1] = new Stretch(stretch); 02159 } 02160 02161 p_gray.setStretch(stretch); 02162 02163 Stretch newRed(p_red.getStretch()); 02164 newRed.CopyPairs(stretch); 02165 p_red.setStretch(newRed); 02166 02167 Stretch newGreen(p_green.getStretch()); 02168 newGreen.CopyPairs(stretch); 02169 p_green.setStretch(newGreen); 02170 02171 Stretch newBlue(p_blue.getStretch()); 02172 newBlue.CopyPairs(stretch); 02173 p_blue.setStretch(newBlue); 02174 02175 paintPixmap(); 02176 viewport()->update(); 02177 } 02178 02179 02185 void CubeViewport::stretchRed(const Stretch &stretch) { 02186 p_red.setStretch(stretch); 02187 02188 // Assume first stretch is always the global stretch (and it should be) 02189 if((*p_globalStretches)[redBand() - 1] == NULL && stretch.Pairs()) { 02190 (*p_globalStretches)[redBand() - 1] = new Stretch(p_red.getStretch()); 02191 } 02192 02193 paintPixmap(); 02194 viewport()->update(); 02195 } 02196 02197 02203 void CubeViewport::stretchGreen(const Stretch &stretch) { 02204 p_green.setStretch(stretch); 02205 02206 // Assume first stretch is always the global stretch (and it should be) 02207 if((*p_globalStretches)[greenBand() - 1] == NULL && stretch.Pairs()) { 02208 (*p_globalStretches)[greenBand() - 1] = new Stretch(p_green.getStretch()); 02209 } 02210 02211 paintPixmap(); 02212 viewport()->update(); 02213 } 02214 02215 02221 void CubeViewport::stretchBlue(const Stretch &stretch) { 02222 p_blue.setStretch(stretch); 02223 02224 // Assume first stretch is always the global stretch (and it should be) 02225 if((*p_globalStretches)[blueBand() - 1] == NULL && stretch.Pairs()) { 02226 (*p_globalStretches)[blueBand() - 1] = new Stretch(p_blue.getStretch()); 02227 } 02228 02229 paintPixmap(); 02230 viewport()->update(); 02231 } 02232 02233 02241 double CubeViewport::fitScale() const { 02242 double sampScale = (double) viewport()->width() / (double) cubeSamples(); 02243 double lineScale = (double) viewport()->height() / (double) cubeLines(); 02244 double scale = sampScale < lineScale ? sampScale : lineScale; 02245 // scale = floor(scale * 100.0) / 100.0; 02246 return scale; 02247 } 02248 02249 02256 double CubeViewport::fitScaleWidth() const { 02257 double scale = (double) viewport()->width() / (double) cubeSamples(); 02258 02259 // scale = floor(scale * 100.0) / 100.0; 02260 return scale; 02261 } 02262 02269 double CubeViewport::fitScaleHeight() const { 02270 double scale = (double) viewport()->height() / (double) cubeLines(); 02271 02272 // scale = floor(scale * 100.0) / 100.0; 02273 return scale; 02274 } 02275 02283 void CubeViewport::cubeContentsChanged(QRect cubeRect) { 02284 //start sample/line and end sample/line 02285 double ss, sl, es, el; 02286 ss = (double)(cubeRect.left()) - 1.; 02287 sl = (double)(cubeRect.top()) - 1.; 02288 es = (double)(cubeRect.right()) + 1.; 02289 el = (double)(cubeRect.bottom()) + 1.; 02290 if(ss < 1){ 02291 ss = 0.5; 02292 } 02293 if(sl < 1){ 02294 sl = 0.5; 02295 } 02296 if(es > cube()->sampleCount()){ 02297 es = cube()->sampleCount() + 0.5; 02298 } 02299 if(el > cube()->lineCount()){ 02300 el = cube()->lineCount() + 0.5; 02301 } 02302 02303 //start x/y and end x/y 02304 int sx, sy, ex, ey; 02305 02306 cubeToViewport(ss, sl, sx, sy); 02307 cubeToViewport(es, el, ex, ey); 02308 if(sx < 0){ 02309 sx = 0; 02310 } 02311 if(sy < 0){ 02312 sy = 0; 02313 } 02314 if(ex > viewport()->width()){ 02315 ex = viewport()->width(); 02316 } 02317 if(ey > viewport()->height()){ 02318 ey = viewport()->height(); 02319 } 02320 QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1); 02321 02322 p_updatingBuffers = true; 02323 if(p_grayBuffer){ 02324 p_grayBuffer->fillBuffer(vpRect); 02325 } 02326 if(p_redBuffer){ 02327 p_redBuffer->fillBuffer(vpRect); 02328 } 02329 if(p_greenBuffer){ 02330 p_greenBuffer->fillBuffer(vpRect); 02331 } 02332 if(p_blueBuffer){ 02333 p_blueBuffer->fillBuffer(vpRect); 02334 } 02335 p_updatingBuffers = false; 02336 02337 paintPixmapRects(); 02338 } 02339 02340 02347 void CubeViewport::changeCursor(QCursor cursor) { 02348 viewport()->setCursor(cursor); 02349 } 02350 02351 02352 CubeViewport::BandInfo::BandInfo() : band(1), stretch(NULL) { 02353 stretch = new Stretch; 02354 stretch->SetNull(0.0); 02355 stretch->SetLis(0.0); 02356 stretch->SetLrs(0.0); 02357 stretch->SetHis(255.0); 02358 stretch->SetHrs(255.0); 02359 stretch->SetMinimum(0.0); 02360 stretch->SetMaximum(255.0); 02361 }; 02362 02363 02364 CubeViewport::BandInfo::BandInfo(const CubeViewport::BandInfo &other) : 02365 band(other.band) { 02366 stretch = NULL; 02367 stretch = new Stretch(*other.stretch); 02368 } 02369 02370 02371 CubeViewport::BandInfo::~BandInfo() { 02372 if(stretch) { 02373 delete stretch; 02374 stretch = NULL; 02375 } 02376 } 02377 02378 02379 Stretch CubeViewport::BandInfo::getStretch() const { 02380 ASSERT_PTR(stretch); 02381 02382 return *stretch; 02383 } 02384 02385 02386 void CubeViewport::BandInfo::setStretch(const Stretch &newStretch) { 02387 *stretch = newStretch; 02388 } 02389 02390 02391 const CubeViewport::BandInfo &CubeViewport::BandInfo::operator=( 02392 CubeViewport::BandInfo other) { 02393 ASSERT_PTR(other.stretch); 02394 02395 stretch = NULL; 02396 stretch = new Stretch; 02397 *stretch = *other.stretch; 02398 band = other.band; 02399 02400 return *this; 02401 } 02402 02403 }