// KreateCD - CD recording software for the K desktop environment
//
// 1999 by Alexander Feigl <Alexander.Feigl@gmx.de>
//
// This file is subject to the terms and conditions of the GNU General      
// Public License.  See the file COPYING in the main directory of the       
// KreateCD distribution for more details.                                     

#include "MainWindow.h"
#include "CDTrack.h"
#include "TrackWindow.h"
#include "ConfSCSI.h"
#include "ConfPath.h"
#include "WriteDialog.h"
#include "AudioFile.h"

#include <qwidget.h>
#include <qpushbutton.h>
#include <qlistview.h>
#include <qkeycode.h>
#include <qpopupmenu.h>
#include <qlayout.h>


#include <kmenubar.h>
#include <kconfig.h>
#include <kapp.h>
#include <klocale.h>
#include <kfiledialog.h>
#include <kmsgbox.h>




#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>


extern KLocale *locale;

extern void showAbout(void);

MainWindow::~MainWindow(void)
 {
  KConfig *config;  
  QRect SaveRect(this->pos(),this->size());

  readColWidth();
  config=kapp->getConfig();
  config->setGroup("Geometry");
  config->writeEntry("MainWindowGeo",SaveRect);
  config->writeEntry("MainWindowTrackWidth",Colwidth[0]);
  config->writeEntry("MainWindowDescriptionWidth",Colwidth[1]);
  config->writeEntry("MainWindowSizeWidth",Colwidth[2]);
  config->writeEntry("MainWindowModeWidth",Colwidth[3]);

  if (TrackEdit!=0) delete (TrackEdit);
  TrackEdit=0;
   {
    int i;
    for (i=0;i<MAX_TRACKS_PER_PROJECT;++i)
     {
      if (ProjectTracks[i]!=0) delete(ProjectTracks[i]);
     }
   }

  if (SCSIWindow!=0) delete(SCSIWindow);
  if (PathWindow!=0) delete(PathWindow);

 }

MainWindow::MainWindow(QWidget *parent, const char *name):QWidget(parent,name)
 {
  KConfig *config;  
  QRect DefaultRect(100,100,500,300);

  QVBoxLayout *mainlayout;
  QGridLayout *trackbuttons;
  QHBoxLayout *projectbuttons;


 
  TrackEdit=0;
  SCSIWindow=0;
  PathWindow=0;
  ProjectPath[0]=0;

  CurrentTrack=-1;
   {
    int i;
    for (i=0;i<MAX_TRACKS_PER_PROJECT;++i)
     {
      ProjectTracks[i]=0;
      TrackItems[i]=0;
     }
   }  

  config=kapp->getConfig();

  this->setCaption(locale->translate("KreateCD - project window"));


  MWMenu=new KMenuBar(this,"kreatecd menu");
  QPopupMenu *filemenu=new QPopupMenu;
  filemenu->insertItem(locale->translate("New project ..."),this,SLOT(newProject()));
  filemenu->insertItem(locale->translate("Open project ..."),this,SLOT(openProject()));
  filemenu->insertSeparator();
  filemenu->insertItem(locale->translate("Save project"),this,SLOT(saveProject()));
  filemenu->insertItem(locale->translate("Save project as ..."),this,SLOT(saveProjectAs()));
  filemenu->insertSeparator();
  filemenu->insertItem(locale->translate("Quit"),kapp,SLOT(quit()));
  MWMenu->insertItem(locale->translate("File"),filemenu);
  QPopupMenu *toolsmenu=new QPopupMenu;
  toolsmenu->insertItem(locale->translate("&Copy CDROM ..."),this,SLOT(setupCopy()));
  toolsmenu->insertSeparator();
  toolsmenu->insertItem(locale->translate("Normalize to maximum"),this,SLOT(normalizeMax()));
  toolsmenu->insertItem(locale->translate("Normalize all to same"),this,SLOT(normalizeAllSame()));

  MWMenu->insertItem(locale->translate("&Tools"),toolsmenu);
  QPopupMenu *configmenu=new QPopupMenu;
  configmenu->insertItem(locale->translate("SCSI ..."),this,SLOT(configSCSI()));
  configmenu->insertItem(locale->translate("Paths ..."),this,SLOT(configPath()));
  MWMenu->insertItem(locale->translate("Configure"),configmenu);
  MWMenu->insertSeparator();
  QPopupMenu *helpmenu=new QPopupMenu;
  helpmenu->insertItem(locale->translate("Contents"),this,SLOT(helpContents()),Key_F1,-1);
  helpmenu->insertSeparator();
  helpmenu->insertItem(locale->translate("About KreateCD ..."),this,SLOT(helpAboutMe()));
  MWMenu->insertItem(locale->translate("Help"),helpmenu);
  

  MainWidget=new QWidget(this);

  mainlayout=new QVBoxLayout(MainWidget);
  config->setGroup("Geometry");  
  Colwidth[0]=config->readNumEntry("MainWindowTrackWidth",8);
  Colwidth[1]=config->readNumEntry("MainWindowDescriptionWidth",60);
  Colwidth[2]=config->readNumEntry("MainWindowSizeWidth",16);
  Colwidth[3]=config->readNumEntry("MainWindowModeWidth",16);
  FirstInvoke=1;
  


  MWTracklist=new QListView(MainWidget,"Track selection list");
  MWTracklist->addColumn(locale->translate("Track"),-1);
  MWTracklist->addColumn(locale->translate("Description"),-1);
  MWTracklist->addColumn(locale->translate("Size"),-1);
  MWTracklist->addColumn(locale->translate("Mode"),-1);
  MWTracklist->setAllColumnsShowFocus(TRUE);
  MWTracklist->setMinimumSize(MWTracklist->sizeHint());
  mainlayout->addWidget(MWTracklist,10);

  SumLabel=new QLabel("-",MainWidget);
  SumLabel->setFrameStyle(QFrame::Box|QFrame::Sunken);
  SumLabel->setMinimumSize(SumLabel->sizeHint());
  SumLabel->setFixedHeight(SumLabel->sizeHint().height()); 
  mainlayout->addWidget(SumLabel);
 
  trackbuttons=new QGridLayout(2,3);
  mainlayout->addLayout(trackbuttons,0);

  MWAddTrack=new QPushButton(locale->translate("Add track"),MainWidget,"add track");
  MWAddTrack->setMinimumSize(MWAddTrack->sizeHint());
  trackbuttons->addWidget(MWAddTrack,0,0);
  MWEditTrack=new QPushButton(locale->translate("Edit track"),MainWidget,"edit track");
  MWEditTrack->setMinimumSize(MWEditTrack->sizeHint());
  trackbuttons->addWidget(MWEditTrack,0,1);
  MWDeleteTrack=new QPushButton(locale->translate("Delete track"),MainWidget,"delete track");
  MWDeleteTrack->setMinimumSize(MWDeleteTrack->sizeHint());
  trackbuttons->addWidget(MWDeleteTrack,0,2);
  MWTrackUp=new QPushButton(locale->translate("Track up"),MainWidget,"track up");
  MWTrackUp->setMinimumSize(MWTrackUp->sizeHint());
  trackbuttons->addWidget(MWTrackUp,1,0);
  MWTrackUpdate=new QPushButton(locale->translate("Track update"),MainWidget,"track update");
  MWTrackUpdate->setMinimumSize(MWTrackUpdate->sizeHint());
  trackbuttons->addWidget(MWTrackUpdate,1,1);
  MWTrackDown=new QPushButton(locale->translate("Track down"),MainWidget,"track down");
  MWTrackDown->setMinimumSize(MWTrackDown->sizeHint());
  trackbuttons->addWidget(MWTrackDown,1,2);
  trackbuttons->setColStretch(0,1);
  trackbuttons->setColStretch(1,1);
  trackbuttons->setColStretch(2,1);


  mainlayout->addStretch(2);


  projectbuttons=new QHBoxLayout();
  mainlayout->addLayout(projectbuttons,0);

  projectbuttons->addStretch(1);
  MWWriteCD=new QPushButton(locale->translate("Write CD!!"),MainWidget,"write cd");
  MWWriteCD->setFixedSize(MWWriteCD->sizeHint());
  projectbuttons->addWidget(MWWriteCD,0);
  projectbuttons->addStretch(1);

  checkWidgetEnable();

  connect(kapp,SIGNAL(saveYourself()),this,SLOT(saveSession()));
  connect(MWAddTrack,SIGNAL(clicked()),this,SLOT(addTrack()));
  connect(MWEditTrack,SIGNAL(clicked()),this,SLOT(editTrack()));
  connect(MWDeleteTrack,SIGNAL(clicked()),this,SLOT(deleteTrack()));
  connect(MWTrackUp,SIGNAL(clicked()),this,SLOT(moveUp()));
  connect(MWTrackUpdate,SIGNAL(clicked()),this,SLOT(updateTrack()));
  connect(MWTrackDown,SIGNAL(clicked()),this,SLOT(moveDown()));
  connect(MWMenu,SIGNAL(moved(menuPosition)),this,SLOT(menuMoved()));
  connect(MWTracklist,SIGNAL(selectionChanged(QListViewItem *)),this,SLOT(changeCurrent(QListViewItem *)));
  connect(MWTracklist,SIGNAL(doubleClicked(QListViewItem *)),this,SLOT(editTrack()));

  connect(MWWriteCD,SIGNAL(clicked()),this,SLOT(writeCD()));


  mainlayout->activate();

  config->setGroup("Geometry");
  this->setGeometry(config->readRectEntry("MainWindowGeo",&DefaultRect));


  if (kapp->isRestored())
   {
    KConfig *kc;
    kc=kapp->getSessionConfig();
    if (kc!=0) loadProjectFromConfig(kc);
   }
 
  updateTrackItem();
  updateTrackSum();
 }

void MainWindow::resizeEvent(QResizeEvent *)
 {
  QSize minsize;

  int WindowH,BaseY;

  int MenuPos;

  WindowH=height();

  MenuPos=MWMenu->menuBarPos();

  switch (MenuPos)
   {
    case KMenuBar::Top:
      BaseY=MWMenu->height();
      WindowH-=BaseY;
      MWMenu->setGeometry(0,0,this->width(),MWMenu->height());
      break;
    case KMenuBar::Bottom:
      BaseY=0;
      WindowH-=MWMenu->height();
      MWMenu->setGeometry(0,WindowH,this->width(),MWMenu->height());
      break;
    case KMenuBar::Floating:
      BaseY=0;
      break;
    default:
      BaseY=0;
      break;
   }
  
  if (FirstInvoke)
   {
    FirstInvoke=0;
   }
   else
   {
    readColWidth();
   }
  MainWidget->setGeometry(0,BaseY,this->width(),WindowH);
  minsize=MainWidget->minimumSize();
  if (MenuPos!=KMenuBar::Floating) minsize.rheight()+=MWMenu->height();
  this->setMinimumSize(minsize);
  writeColWidth();
 }


void MainWindow::checkWidgetEnable()
 {
  int tracks;
  MWEditTrack->setEnabled(CurrentTrack!=-1?TRUE:FALSE);
  MWDeleteTrack->setEnabled(CurrentTrack!=-1?TRUE:FALSE);
  for (tracks=0;tracks<MAX_TRACKS_PER_PROJECT;++tracks)
   {
    if (ProjectTracks[tracks]==0) break;
   }
  MWAddTrack->setEnabled(tracks==MAX_TRACKS_PER_PROJECT?FALSE:TRUE);
  MWTrackUp->setEnabled( ( (tracks>1) && (CurrentTrack>0))?TRUE:FALSE);
  MWTrackDown->setEnabled( ( (tracks>1) && (CurrentTrack!=-1) && (CurrentTrack<(tracks-1)) )? TRUE:FALSE);
  MWTrackUpdate->setEnabled(CurrentTrack!=-1?TRUE:FALSE);
 }

void MainWindow::addTrack()
 {
  int freetrack=-1,i;
  if (TrackEdit!=0)
   {
    delete(TrackEdit);
    TrackEdit=0;
   }

  for (i=0;i<MAX_TRACKS_PER_PROJECT;++i)
   {
    if (ProjectTracks[i]==0)
     {
      freetrack=i;
      break;
     }
   }
  
  if (freetrack==-1) return;

  ProjectTracks[freetrack]=new CDTrack();
  if (ProjectTracks[freetrack]==0) return;

  TrackItems[freetrack]=new QListViewItem(MWTracklist);
  if (TrackItems[freetrack]==0)
   {
    delete(ProjectTracks[freetrack]);
    ProjectTracks[freetrack]=0;
    return;
   }

  CurrentTrack=freetrack;

  checkWidgetEnable();
  updateTrackItem();
  updateTrackSum();

  MWTracklist->ensureItemVisible(TrackItems[CurrentTrack]);
  MWTracklist->setSelected(TrackItems[CurrentTrack],TRUE);

  TrackEdit=new TrackWindow(0,"track window",ProjectTracks[CurrentTrack]);
  if (TrackEdit==0) return;
  connect(TrackEdit,SIGNAL(closed()),this,SLOT(notifyCloseTWin()));
  connect(TrackEdit,SIGNAL(updateTrack()),this,SLOT(updateTrackItem()));
  connect(TrackEdit,SIGNAL(updateTrack()),this,SLOT(updateTrackSum()));

  TrackEdit->show();
 }

void MainWindow::editTrack()
 
 {
  if (TrackEdit!=0) return;
  if (CurrentTrack==-1) return;

  MWTracklist->ensureItemVisible(TrackItems[CurrentTrack]);
  TrackEdit=new TrackWindow(0,"track window",ProjectTracks[CurrentTrack]);
  if (TrackEdit==0) return;
  connect(TrackEdit,SIGNAL(closed()),this,SLOT(notifyCloseTWin()));
  connect(TrackEdit,SIGNAL(updateTrack()),this,SLOT(updateTrackItem()));
  connect(TrackEdit,SIGNAL(updateTrack()),this,SLOT(updateTrackSum()));

  TrackEdit->show();
 }

void MainWindow::deleteTrack()
 {
  int i;
  if (CurrentTrack==-1) return;
  if (TrackEdit!=0)
   {
    delete(TrackEdit);
    TrackEdit=0;
   }
  
  MWTracklist->setSelected(TrackItems[CurrentTrack],FALSE);

  delete(TrackItems[CurrentTrack]);
  delete(ProjectTracks[CurrentTrack]);
  for (i=CurrentTrack;i<(MAX_TRACKS_PER_PROJECT-1);++i)
   {
    TrackItems[i]=TrackItems[i+1];
    ProjectTracks[i]=ProjectTracks[i+1];
   }
  TrackItems[MAX_TRACKS_PER_PROJECT-1]=0;
  ProjectTracks[MAX_TRACKS_PER_PROJECT-1]=0;
  while ((CurrentTrack<MAX_TRACKS_PER_PROJECT) && (ProjectTracks[CurrentTrack]!=0))
   {
    updateTrackItem();
    ++CurrentTrack;
   }
  CurrentTrack=-1;
  checkWidgetEnable();
  updateTrackSum();
 }

void MainWindow::changeCurrent(QListViewItem *item)
 {
  int strack=-1,isopen,i;
  if (item==0)
   {
    CurrentTrack=-1;
    checkWidgetEnable();
    if (TrackEdit!=0)
     {
      delete(TrackEdit);
      TrackEdit=0;
      return;
     }
    return;
   }

  for (i=0;i<MAX_TRACKS_PER_PROJECT;++i)
   {
    if ( (TrackItems[i]!=0) && (TrackItems[i]==item))
     {
      strack=i;
      break;
     }
   }
  if (strack==-1) return;
  if (CurrentTrack==strack) return;  

  isopen=(TrackEdit!=0)?TRUE:FALSE;
  if (TrackEdit!=0)
   {
    delete(TrackEdit);
    TrackEdit=0;
   }  
  CurrentTrack=strack;
  checkWidgetEnable();

  if (isopen)
   {
     TrackEdit=new TrackWindow(0,"track window",ProjectTracks[CurrentTrack]);
     if (TrackEdit==0) return;
     connect(TrackEdit,SIGNAL(closed()),this,SLOT(notifyCloseTWin()));
     connect(TrackEdit,SIGNAL(updateTrack()),this,SLOT(updateTrackItem())); 
     connect(TrackEdit,SIGNAL(updateTrack()),this,SLOT(updateTrackSum()));

     TrackEdit->show();
   }
  
 }

void MainWindow::notifyCloseTWin(void)
 {
  delete TrackEdit;
  TrackEdit=0;
 }

void MainWindow::notifyCloseSCSIWin(void)
 {
  delete SCSIWindow;
  SCSIWindow=0;
 }

void MainWindow::notifyClosePathWin(void)
 {
  delete PathWindow;
  PathWindow=0;
 }

void MainWindow::menuMoved()
 {
  resizeEvent(0);
 }

void MainWindow::updateTrackSum(void)
 {
  long int dura;
  int tr,i;
  dura=0;
  tr=0;
  for (i=0;i<MAX_TRACKS_PER_PROJECT;++i)
   {
    if (ProjectTracks[i]==0) continue;
    tr++;
    dura+=ProjectTracks[i]->getRealDuration();
    dura+=2*75;
   }
   {
    char format1[80],format2[20];
    CDTrack::getDurationHMSB(format2,dura);
    sprintf(format1,locale->translate("Tracks in project : %d ( duration %s )"),
            tr,format2);
    SumLabel->setText(format1);
   }

 }

void MainWindow::updateTrackItem(void)
 {
  QListViewItem *lvi;
  CDTrack *ctr;
  char col[80];

  if (CurrentTrack==-1) return;
  
  lvi=TrackItems[CurrentTrack];
  ctr=ProjectTracks[CurrentTrack];

  if ( (lvi==0) || (ctr==0) ) return;

  sprintf(col,"%3d",CurrentTrack+1);
  lvi->setText(0,col);
  ctr->getTrackDescription(col);
  lvi->setText(1,col);
  ctr->getTrackDurationHMSB(col);
  lvi->setText(2,col);
  ctr->getTrackTypeText(col);
  lvi->setText(3,locale->translate(col));
 
 }


void MainWindow::helpContents()
 {
  kapp->invokeHTMLHelp("","");
 }

void MainWindow::helpAboutMe()
 {
  showAbout();
 }

void MainWindow::configSCSI()
 {
  if (SCSIWindow==0) SCSIWindow=new ConfSCSI(0,"scsi window");
  SCSIWindow->show();
  connect(SCSIWindow,SIGNAL(closed()),this,SLOT(notifyCloseSCSIWin()));

 }

void MainWindow::configPath()
 {
  if (PathWindow==0) PathWindow=new ConfPath(0,"path window");
  PathWindow->show();
  connect(PathWindow,SIGNAL(closed()),this,SLOT(notifyClosePathWin()));

 }


void MainWindow::saveSession()
 {
  KConfig *kc;
  kc=kapp->getSessionConfig();
  if (kc!=0) saveProjectToConfig(kc);
 }

void MainWindow::moveUp()
 {
  CDTrack *ttrack;

  if ( (CurrentTrack==0) || (CurrentTrack==-1) ) return;

  ttrack=ProjectTracks[CurrentTrack];
  ProjectTracks[CurrentTrack]=ProjectTracks[CurrentTrack-1];
  ProjectTracks[CurrentTrack-1]=ttrack;
  updateTrackItem();
  CurrentTrack--;
  updateTrackItem();
  MWTracklist->setSelected(TrackItems[CurrentTrack],TRUE);
  MWTracklist->ensureItemVisible(TrackItems[CurrentTrack]);
  checkWidgetEnable();
 }

void MainWindow::moveDown()
 {
  CDTrack *ttrack;

  if ( (CurrentTrack==-1) || (CurrentTrack==MAX_TRACKS_PER_PROJECT) ) return;
  if (ProjectTracks[CurrentTrack+1]==0) return;

  ttrack=ProjectTracks[CurrentTrack];
  ProjectTracks[CurrentTrack]=ProjectTracks[CurrentTrack+1];
  ProjectTracks[CurrentTrack+1]=ttrack;
  updateTrackItem();
  CurrentTrack++;
  updateTrackItem();
  MWTracklist->setSelected(TrackItems[CurrentTrack],TRUE);
  MWTracklist->ensureItemVisible(TrackItems[CurrentTrack]);
  checkWidgetEnable();
 }

void MainWindow::updateTrack()
 {
  if (CurrentTrack==-1) return;

  MWTracklist->ensureItemVisible(TrackItems[CurrentTrack]);
  ProjectTracks[CurrentTrack]->updateTrack();
  ProjectTracks[CurrentTrack]->validateTrack();
  updateTrackItem();
  if (TrackEdit!=0) TrackEdit->updateWindowContents();
  updateTrackSum();
 }

void MainWindow::writeCD()
 {
  int i,t,tracks=0;

  for (i=0;i<MAX_TRACKS_PER_PROJECT;++i)
   {
    if (ProjectTracks[i]!=0)
     {
      if (!ProjectTracks[i]->validateTrack())
       {
        if ( (i==CurrentTrack) && TrackEdit!=0) TrackEdit->updateWindowContents();
        t=CurrentTrack;
        CurrentTrack=i;
        updateTrackItem();
        updateTrackSum();
        CurrentTrack=t;
#if QT_VERSION >= 200
        KMsgBox::message(0,QString::null,locale->translate("Cannot create image files!"),KMsgBox::EXCLAMATION);
#else
        KMsgBox::message(0,0,locale->translate("Cannot create image files!"),KMsgBox::EXCLAMATION);
#endif
        return;
       }
      if ( (i==CurrentTrack) && TrackEdit!=0) TrackEdit->updateWindowContents();
      t=CurrentTrack;
      CurrentTrack=i;
      updateTrackItem();
      updateTrackSum();
      CurrentTrack=t;

      ++tracks;
     }
   }
  if (tracks==0)
    {
#if QT_VERSION >= 200
     KMsgBox::message(0,QString::null,locale->translate("Nothing to write on CD!"),KMsgBox::EXCLAMATION);
#else
     KMsgBox::message(0,0,locale->translate("Nothing to write on CD!"),KMsgBox::EXCLAMATION);
#endif
     return;
    }
   {
    WriteDialog *wd;
    wd=new WriteDialog(this,(const char *) 0,tracks,ProjectTracks);
    wd->exec();
    delete (wd);
   }
 }


void MainWindow::readColWidth()
 {
  int sum=0,i;
  for (i=0;i<TRACK_COLUMNS;++i)
   {
    sum+=MWTracklist->columnWidth(i);
   }
  if (sum==0) return;
  for (i=0;i<TRACK_COLUMNS;++i)
   {
    Colwidth[i]=MWTracklist->columnWidth(i)*100/sum;
    } 
 }

void MainWindow::writeColWidth()
 {
  int sum=0,i;
  sum=MainWidget->width();
  if (sum==0) return;
  for (i=0;i<TRACK_COLUMNS;++i)
   {
    MWTracklist->setColumnWidth(i,Colwidth[i]*sum/100);
   }
 }


