/* flip - pageflipper for TIFF animations * Copyright (C) 1999 Mark B. Allan (mba@reptilelabour.com) * * "flip" is free software; you can redistribute it and/or use * it and/or modify it under the terms of the "Artistic License" */ #include "MainWindow.h" #include #include #include #include #include #include #include "define.h" #include "Config.h" #include "InputLCD.h" #include "FileDialog.h" #include "TiffFlip.h" #include "InputLCD.h" #include "FileDialog.h" #include "FlipPreferences.h" #include "RenderMPEGDialog.h" #include "Pixmaps/f_clr_ff.xpm" #include "Pixmaps/f_clr_ping.xpm" #include "Pixmaps/f_clr_play.xpm" #include "Pixmaps/f_clr_rew.xpm" #include "Pixmaps/f_clr_stop.xpm" #include "Pixmaps/f_gry_ff.xpm" #include "Pixmaps/f_gry_ping.xpm" #include "Pixmaps/f_gry_play.xpm" #include "Pixmaps/f_gry_rew.xpm" #include "Pixmaps/f_gry_stop.xpm" extern int e_fontM; extern int e_fontS; extern const char* e_fontFace; double MainWindow::fpsVal[NumFPS]; //============================================================================== MainWindow::MainWindow( QWidget *parent, const char* name ) : QWidget (parent, name) { Config *cfg = Config::getInstance(); setCaption(APP_NAME); //-- we need to set this before creating FlipPreferences fpsVal[F60] = 60.0; fpsVal[F48] = 48.0; fpsVal[F30] = 30.0; fpsVal[F24] = 24.0; fpsVal[F20] = 20.0; fpsVal[F15] = 15.0; fpsVal[F12] = 12.0; fpsVal[F10] = 10.0; minFrameInput = maxFrameInput = 0; curFrame = 0; pingpong = frameStep = 1; //-- create TiffFlip object tiffFlip = new TiffFlip(0); //-- create file dialog fileDialog = new FileDialog(this); fileDialog->hide(); //-- create preferences dialog preferences = new FlipPreferences(this); preferences->hide(); mpegID = 999; //-- menuBar QFont::setDefaultFont(QFont(e_fontFace, e_fontM, QFont::Bold, false)); filePopup = new QPopupMenu; filePopup->insertItem ("&open", this, SLOT(LoadSequence()), CTRL+Key_O); filePopup->insertItem ("&clear", this, SLOT(Clear()), CTRL+Key_C); filePopup->insertSeparator(); filePopup->insertItem( "&preferences", this, SLOT(PreferencesDialog()), CTRL+Key_P ); filePopup->insertSeparator(); filePopup->insertItem( "e&xit", this, SLOT(quit()), CTRL+Key_Q ); utilPopup = new QPopupMenu; utilPopup->insertItem( "encode &mpeg...", this, SLOT(renderMPEG()), CTRL+Key_M, mpegID ); utilPopup->setItemEnabled(mpegID, Config::hasMpeg()); fpsPopup = new QPopupMenu; fpsID[F60] = fpsPopup->insertItem( " 60 ", this, SLOT(Fps60()) ); fpsID[F48] = fpsPopup->insertItem( " 48 ", this, SLOT(Fps48()) ); fpsID[F30] = fpsPopup->insertItem( " 30 ", this, SLOT(Fps30()) ); fpsID[F24] = fpsPopup->insertItem( " 24 ", this, SLOT(Fps24()) ); fpsID[F20] = fpsPopup->insertItem( " 20 ", this, SLOT(Fps20()) ); fpsID[F15] = fpsPopup->insertItem( " 15 ", this, SLOT(Fps15()) ); fpsID[F12] = fpsPopup->insertItem( " 12 ", this, SLOT(Fps12()) ); fpsID[F10] = fpsPopup->insertItem( " 10 ", this, SLOT(Fps10()) ); fpsPopup->setCheckable(true); FPS curFPS = cfg->flipFPS; fpsPopup->setItemChecked(fpsID[(int)curFPS], true); currentSpeed = fpsVal[curFPS]; stepPopup = new QPopupMenu; step1_ID = stepPopup->insertItem( "1 ", this, SLOT(Step1()) ); step2_ID = stepPopup->insertItem( "2 ", this, SLOT(Step2()) ); step3_ID = stepPopup->insertItem( "3 ", this, SLOT(Step3()) ); step4_ID = stepPopup->insertItem( "4 ", this, SLOT(Step4()) ); step5_ID = stepPopup->insertItem( "5 ", this, SLOT(Step5()) ); step6_ID = stepPopup->insertItem( "6 ", this, SLOT(Step6()) ); stepPopup->setCheckable(true); stepPopup->setItemChecked(step1_ID, true); zoomPopup = new QPopupMenu; zoom1_ID = zoomPopup->insertItem( "1x ", this, SLOT(Zoom1()) ); zoom2_ID = zoomPopup->insertItem( "2x ", this, SLOT(Zoom2()) ); zoomPopup->setItemChecked(zoom1_ID, true); zoomPopup->setCheckable(true); zoomPopup->setItemChecked(zoom1_ID, true); menuBar = new QMenuBar (this); menuBar->insertItem ("&file", filePopup); menuBar->insertItem ("&util", utilPopup); menuBar->insertItem ("&zoom", zoomPopup); menuBar->insertItem ("&step", stepPopup); menuBar->insertItem ("f&ps", fpsPopup); menuBar->insertSeparator(); QFont::setDefaultFont(QFont(e_fontFace, e_fontM, QFont::Bold, false)); //-- status line statusline = new QLabel(this); statusline->setText("no frames loaded."); statusline->setFrameStyle(QFrame::Sunken | QFrame::Box); statusline->setAlignment( AlignCenter ); statusline->setFont ( QFont(e_fontFace, e_fontS, QFont::Bold) ); int numWidth = (int)(statusline->sizeHint().height()*2.5); frameNum = new QLabel(this); frameNum->setText(""); frameNum->setFrameStyle(QFrame::Sunken | QFrame::Box); frameNum->setAlignment( AlignCenter ); frameNum->setFixedWidth(numWidth); actualFps = new QLabel(this); actualFps->setText(" "); actualFps->setFrameStyle(QFrame::Sunken | QFrame::Box); actualFps->setAlignment( AlignCenter ); actualFps->setFixedWidth(numWidth); //-- frame jog frameScroll = new QScrollBar (QScrollBar::Horizontal, this); frameScroll->setRange(0, tiffFlip->GetNumFrames() ); //-- LCD Inputs minFrameInput = new InputLCD(this); minFrameInput->setFixedSize(50, 25); maxFrameInput = new InputLCD(this); maxFrameInput->setFixedSize(50, 25); //-- Buttons rew = new MToolButton(this); rew->setFixedSize(32, 32); rew->setUsesBigPixmap(true); rew->setAutoRaise(true); ping = new MToolButton(this); ping->setToggleButton(true); ping->setFixedSize(32, 32); ping->setUsesBigPixmap(true); ping->setAutoRaise(true); stop = new MToolButton(this); stop->setFixedSize(32, 32); stop->setUsesBigPixmap(true); stop->setAutoRaise(true); play = new MToolButton(this); play->setToggleButton(true); play->setFixedSize(32, 32); play->setUsesBigPixmap(true); play->setAutoRaise(true); ff = new MToolButton(this); ff->setFixedSize(32, 32); ff->setUsesBigPixmap(true); ff->setAutoRaise(true); //----------------------------------Buttons QIconSet *icoSet; icoSet = new QIconSet(QPixmap((const char**)f_gry_rew_xpm) ); icoSet->setPixmap(QPixmap((const char**)f_clr_rew_xpm), QIconSet::Large, QIconSet::Active); icoSet->setPixmap(QPixmap((const char**)f_gry_rew_xpm), QIconSet::Large, QIconSet::Disabled); rew->setIconSet(*icoSet); delete icoSet; icoSet = new QIconSet(QPixmap((const char**)f_gry_ping_xpm) ); icoSet->setPixmap(QPixmap((const char**)f_clr_ping_xpm), QIconSet::Large, QIconSet::Active); icoSet->setPixmap(QPixmap((const char**)f_gry_ping_xpm), QIconSet::Large, QIconSet::Disabled); ping->setIconSet(*icoSet); delete icoSet; icoSet = new QIconSet(QPixmap((const char**)f_gry_stop_xpm) ); icoSet->setPixmap(QPixmap((const char**)f_clr_stop_xpm), QIconSet::Large, QIconSet::Active); icoSet->setPixmap(QPixmap((const char**)f_gry_stop_xpm), QIconSet::Large, QIconSet::Disabled); stop->setIconSet(*icoSet); delete icoSet; icoSet = new QIconSet(QPixmap((const char**)f_gry_play_xpm) ); icoSet->setPixmap(QPixmap((const char**)f_clr_play_xpm), QIconSet::Large, QIconSet::Active); icoSet->setPixmap(QPixmap((const char**)f_gry_play_xpm), QIconSet::Large, QIconSet::Disabled); play->setIconSet(*icoSet); delete icoSet; icoSet = new QIconSet(QPixmap((const char**)f_gry_ff_xpm) ); icoSet->setPixmap(QPixmap((const char**)f_clr_ff_xpm), QIconSet::Large, QIconSet::Active); icoSet->setPixmap(QPixmap((const char**)f_gry_ff_xpm), QIconSet::Large, QIconSet::Disabled); ff->setIconSet(*icoSet); delete icoSet; //----------------------------------TIMER timer = new QTimer(this); //----------------------------------Connect QObject::connect(tiffFlip, SIGNAL(LoadingFrame(int)), SLOT(UpdateLoadStatus(int)) ); QObject::connect(tiffFlip, SIGNAL(Done(int, bool)), SLOT(LoadSequenceCompleted(int, bool)) ); QObject::connect(frameScroll, SIGNAL(valueChanged(int)), SLOT(SetFrameNumber(int)) ); QObject::connect(play, SIGNAL(clicked()), SLOT( LoopForward()) ); QObject::connect(ping , SIGNAL(clicked()), SLOT( PingPong()) ); QObject::connect(stop , SIGNAL(clicked()), SLOT( Stop()) ); QObject::connect(ff , SIGNAL(clicked()), SLOT( FastForward()) ); QObject::connect(rew , SIGNAL(clicked()), SLOT( Rewind()) ); QObject::connect(minFrameInput, SIGNAL(valueChanged(int)), SLOT(SetMinFrame(int)) ); QObject::connect(maxFrameInput, SIGNAL(valueChanged(int)), SLOT(SetMaxFrame(int)) ); QObject::connect(timer, SIGNAL(timeout()), SLOT(Action()) ); //----------------------------------Layout topLayout = new QVBoxLayout(this, 5, 1); status = new QHBoxLayout(2); buttons = new QHBoxLayout(2); middle = new QHBoxLayout(5); midR = new QVBoxLayout(0); midM = new QVBoxLayout(0); midL = new QVBoxLayout(0); topLayout->addSpacing(menuBar->heightForWidth(400)); topLayout->addStretch(1); topLayout->addWidget(frameScroll, 0); topLayout->addLayout(middle, 0); middle->addLayout(midR); midR->addWidget(minFrameInput); midR->addStretch(1); middle->addStretch(1); middle->addLayout(midM); midM->addSpacing(2); midM->addLayout(buttons, 0); buttons->addSpacing(5); buttons->addStretch(); buttons->addWidget(rew); buttons->addWidget(ping); buttons->addWidget(stop); buttons->addWidget(play); buttons->addWidget(ff); buttons->addStretch(); buttons->addSpacing(5); middle->addStretch(1); middle->addLayout(midL); midL->addWidget(maxFrameInput); midL->addStretch(1); topLayout->addSpacing(2); topLayout->addLayout(status, 0); status->addWidget(frameNum); status->addWidget(statusline); status->addWidget(actualFps); resize(10,10); } //-------------------------------------------------------------------- MainWindow::~MainWindow() { } //-------------------------------------------------------------------- void MainWindow::DUMMYslot() { } //-------------------------------------------------------------------- void MainWindow::quit() { Config::commit(); qApp->quit(); } //-------------------------------------------------------------------- void MainWindow::PreferencesDialog() { Config *cfg = Config::getInstance(); preferences->exec(); if (preferences->result() == QDialog::Accepted) { fileDialog->setNumHistory(cfg->fileHist); utilPopup->setItemEnabled(mpegID, Config::hasMpeg()); } } //-------------------------------------------------------------------- void MainWindow::Fps60() { SetFPS(F60); } void MainWindow::Fps48() { SetFPS(F48); } void MainWindow::Fps30() { SetFPS(F30); } void MainWindow::Fps24() { SetFPS(F24); } void MainWindow::Fps20() { SetFPS(F20); } void MainWindow::Fps15() { SetFPS(F15); } void MainWindow::Fps12() { SetFPS(F12); } void MainWindow::Fps10() { SetFPS(F10); } //-------------------------------------------------------------------- void MainWindow::SetFPS(FPS index) { for(int i = 0; i < NumFPS; i++) fpsPopup->setItemChecked(fpsID[i], false); fpsPopup->setItemChecked(fpsID[index], true); currentSpeed = fpsVal[index]; if (timer->isActive()) { timer->changeInterval((int)(1000.0/currentSpeed)); } } //-------------------------------------------------------------------- void MainWindow::Step1() { SetStep(1); } void MainWindow::Step2() { SetStep(2); } void MainWindow::Step3() { SetStep(3); } void MainWindow::Step4() { SetStep(4); } void MainWindow::Step5() { SetStep(5); } void MainWindow::Step6() { SetStep(6); } void MainWindow::SetStep(int index) { stepPopup->setItemChecked(step1_ID, false); stepPopup->setItemChecked(step2_ID, false); stepPopup->setItemChecked(step3_ID, false); stepPopup->setItemChecked(step4_ID, false); stepPopup->setItemChecked(step5_ID, false); stepPopup->setItemChecked(step6_ID, false); switch(index) { case 1: stepPopup->setItemChecked(step1_ID, true); frameStep = 1; break; case 2: stepPopup->setItemChecked(step2_ID, true); frameStep = 2; break; case 3: stepPopup->setItemChecked(step3_ID, true); frameStep = 3; break; case 4: stepPopup->setItemChecked(step4_ID, true); frameStep = 4; break; case 5: stepPopup->setItemChecked(step5_ID, true); frameStep = 5; break; case 6: stepPopup->setItemChecked(step6_ID, true); frameStep = 6; break; } if(pingpong < 0) pingpong = -frameStep; else pingpong = frameStep; } //-------------------------------------------------------------------- void MainWindow::Zoom1() { SetZoom(1); } void MainWindow::Zoom2() { SetZoom(2); } void MainWindow::SetZoom(int index) { zoomPopup->setItemChecked(zoom1_ID, false); zoomPopup->setItemChecked(zoom2_ID, false); switch(index) { case 1: zoomPopup->setItemChecked(zoom1_ID, true); tiffFlip->SetDisplayZoom(index); break; case 2: zoomPopup->setItemChecked(zoom2_ID, true); break; } tiffFlip->SetDisplayZoom(index); } //-------------------------------------------------------------------- void MainWindow::SetFrameNumber(int i) { // This slot tells tiffFlip to draw a certain frame // and updates the frame number label curFrame = i; //frameNumString.setNum(curFrame-startFrame+1); frameNumString.setNum(curFrame-minFrame+1); frameNum->setText(frameNumString); tiffFlip->SetFrame(curFrame-startFrame); } //-------------------------------------------------------------------- void MainWindow::Clear() { Stop(); frameScroll->setRange (0, 0); minFrameInput->setActive(false); maxFrameInput->setActive(false); tiffFlip->Reset(); statusline->setText("no frames loaded."); frameNum->setText(""); actualFps->setText(" "); } //-------------------------------------------------------------------- void MainWindow::LoadSequence() { Stop(); if(tiffFlip->isLoading()) tiffFlip->abortLoad(); fileDialog->exec(); if (fileDialog->result() == QDialog::Accepted) { frameScroll->setRange (0, 0); minFrameInput->setActive(false); maxFrameInput->setActive(false); tiffFlip->Reset(); statusline->setText("no frames loaded."); frameNum->setText(""); actualFps->setText(" "); QObject::connect(stop, SIGNAL(clicked()), tiffFlip, SLOT(abortLoad()) ); frameScroll->setRange (0, 0); minFrameInput->display(" "); maxFrameInput->display(" "); startFrame = tiffFlip->LoadImages(fileDialog->getFileName(), fileDialog->getMaxFrames(), fileDialog->getLoadSize()); //LoopForward(); } } //-------------------------------------------------------------------- void MainWindow::UpdateLoadStatus(int i) { static char message[128]; sprintf(message, "loading frame %d of %d", i+1, tiffFlip->GetMaxFrames() ); statusline->setText(message); } //-------------------------------------------------------------------- void MainWindow::LoadSequenceCompleted(int sf, bool aborted) { startFrame = sf; minFrame = startFrame; maxFrame = tiffFlip->GetNumFrames()-1+startFrame; frameScroll->setRange (minFrame, maxFrame); tiffFlip->setCurMinFrame(minFrame); tiffFlip->setCurMaxFrame(maxFrame); // minFrameInput->SetValue (0); // minFrameInput->SetMinMaxInt (minFrame, maxFrame-1); // maxFrameInput->SetMinMaxInt (minFrame+1, maxFrame); // maxFrameInput->SetValue (maxFrame); // minFrameInput->setValue (minFrame); minFrameInput->setMinMaxInt (minFrame, maxFrame-1); maxFrameInput->setMinMaxInt (minFrame+1, maxFrame); maxFrameInput->setValue (maxFrame); curFrame = 0; frameScroll->setValue(curFrame); SetFrameNumber(minFrame); char message[128]; sprintf(message, "loaded %d frames at %dx%d.", tiffFlip->GetNumFrames(), tiffFlip->GetWidth(), tiffFlip->GetHeight() ); statusline->setText(message); QObject::disconnect(stop, SIGNAL(clicked()), tiffFlip, SLOT(abortLoad()) ); if(!aborted) LoopForward(); } //-------------------------------------------------------------------- void MainWindow::SetMinFrame(int val) { maxFrameInput->setMinInt( (minFrame = val) + 1 ); frameScroll->setRange(minFrame, maxFrame); tiffFlip->setCurMinFrame(minFrame); tiffFlip->setCurMaxFrame(maxFrame); frameScroll->setValue(minFrame); } void MainWindow::SetMaxFrame(int val) { minFrameInput->setMaxInt( (maxFrame = val) - 1 ); frameScroll->setRange(minFrame, maxFrame); tiffFlip->setCurMinFrame(minFrame); tiffFlip->setCurMaxFrame(maxFrame); frameScroll->setValue(maxFrame); } //-------------------------------------------------------------------- void MainWindow::LoopForward() { if (timer->isActive()) timer->stop(); play->setOn(true); ping->setOn(false); gettimeofday(&oldTime, 0); playMode = LOOP_FORWARD; timer->start((int)(1000.0/currentSpeed)); } //-------------------------------------------------------------------- void MainWindow::PingPong() { if (timer->isActive()) timer->stop(); play->setOn(false); ping->setOn(true); gettimeofday(&oldTime, 0); playMode = PING_PONG; pingpong = -pingpong; timer->start((int)(1000.0/currentSpeed)); } //-------------------------------------------------------------------- void MainWindow::Stop() { if (timer->isActive()) timer->stop(); play->setOn(false); ping->setOn(false); actualFps->setText(" "); pingpong = 1; } //-------------------------------------------------------------------- void MainWindow::FastForward() { frameScroll->setValue( curFrame = maxFrame ); } //-------------------------------------------------------------------- void MainWindow::Rewind() { frameScroll->setValue( curFrame = minFrame ); } //-------------------------------------------------------------------- void MainWindow::Action() { static int counter = 1; static int elapsed; static int accumulated; static double framesPerSec; static char labelText[64]; switch(playMode) { case LOOP_FORWARD: ActionLoopForward(); break; case PING_PONG: ActionPingPong(); break; default: warning ("MainWindow::playMode is set incorrectly.\nplayMode = %d", playMode); timer->stop(); } gettimeofday(&curTime, 0); elapsed = (int)curTime.tv_usec - (int)oldTime.tv_usec; oldTime.tv_usec = curTime.tv_usec; if(elapsed < 0) elapsed += 1000000; accumulated += elapsed; if (counter >= 10) { framesPerSec = 1000*(1.0/((double)accumulated*0.0001)); counter = 0; accumulated = 0; sprintf(labelText, "%3.2f", framesPerSec); actualFps->setText(labelText); } counter++; } //- - - - - - - - - - - - - - - - - - - - - - - void MainWindow::ActionLoopForward() { curFrame += frameStep; if (curFrame > maxFrame) curFrame = minFrame; frameScroll->setValue(curFrame); qApp->processEvents(); } void MainWindow::ActionPingPong() { curFrame += pingpong; if (curFrame > maxFrame) { curFrame = maxFrame; pingpong = -frameStep; } else if (curFrame < minFrame) { curFrame = minFrame; pingpong = frameStep; } frameScroll->setValue(curFrame); qApp->processEvents(); } //---------------------------------------------------------- void MainWindow::renderMPEG() { Stop(); if(tiffFlip->GetNumFrames() <= 0) { QMessageBox::warning(this, APP_NAME, "No Frames Loaded"); } else { RenderMPEGDialog mpegDialog(*tiffFlip, this); mpegDialog.exec(); } }