//=========================================================
//  MusE
//  Linux Music Editor
//    $Id: sconfig.cpp,v 1.1.1.1 2003/10/29 10:05:24 wschweer Exp $
//  (C) Copyright 1999,2000 Werner Schweer (ws@seh.de)
//=========================================================

#include <stdio.h>
#include "score.h"
#include "sconfig.h"
#include <qgroupbox.h>
#include <qscrollbar.h>
#include <qlayout.h>
#include "symbols.h"
#include <qcombobox.h>
#include <qcheckbox.h>
#include <qlistbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qvbox.h>
#include <qhbox.h>
#include <qradiobutton.h>
#include <qpushbutton.h>
#include <qbuttongroup.h>
#include <qtabwidget.h>
#include "pitchedit.h"
#include "ncanvas.h"
#include "layout.h"

//---------------------------------------------------------
//   tick2quant
//---------------------------------------------------------

static int tick2quant(int tick)
      {
      switch(tick) {
            case 16:    return 0;
            case 32:    return 1;
            case 64:    return 2;
            case 128:   return 3;
            case 256:   return 4;
            case 24:    return 5;
            case 48:    return 6;
            case 96:    return 7;
            case 192:   return 8;
            case 384:   return 9;
            default:
                  printf("illeagal quant value\n");
                  break;
            }
      return 0;
      }

//---------------------------------------------------------
//   quant2tick
//---------------------------------------------------------

static int quant2tick(int q)
      {
      int tab[] = {
            16, 32,  64, 128, 256,
            24, 48,  96, 192, 384
            };
      return tab[q];
      }

//---------------------------------------------------------
//   createQuantCombo
//---------------------------------------------------------

QComboBox* createQuantCombo(QWidget* parent)
      {
      const char* quantval[] = {
            "64T", "32T", "16T", "8T", "4T",
            "64",  "32",  "16",  "8",  "4"
            };
      QComboBox* quant  = new QComboBox(false, parent);
      quant->setFixedHeight(20);
      quant->setFixedWidth(60);
      QListBox* qlist   = new QListBox(parent);
      qlist->setColumnMode(2);
      quant->setListBox(qlist);
      for (unsigned i = 0; i < sizeof(quantval)/sizeof(*quantval); i++)
            qlist->insertItem(QString(quantval[i]), i);
      quant->setCurrentItem(9);   // 4'tel
      return quant;
      }

//---------------------------------------------------------
//   ScoreLabel
//---------------------------------------------------------

ScoreLabel::ScoreLabel(QWidget* parent, const char* name)
   : QWidget(parent, name), key(0), scale(0)
      {
      setMinimumSize(50, 76);
      }

//---------------------------------------------------------
//   setKey
//---------------------------------------------------------

void ScoreLabel::setKey(int k)
      {
      key.set(k);
      update();
      }

//---------------------------------------------------------
//   setScale
//---------------------------------------------------------

void ScoreLabel::setScale(int s)
      {
      scale.set(s);
      update();
      }

//---------------------------------------------------------
//   paintEvent
//---------------------------------------------------------

void ScoreLabel::paintEvent(QPaintEvent*)
      {
      int xoff = 10;
      int yoff = 30;
      int w = width() - 2*xoff;
      int lineD = 6;
      QPainter p(this);
#if 0
      const char* keynames[] = {
            "Violinschlüssel",
            "",
            "",
            "",
            "Baßschlüssel (F-Schlüssel)",
            "",
            "",
            "",
            "",
            "Sopranschlüssel",
            "Mezzosopranschlüssel",
            "Altschlüssel",
            "Tenorschlüssel",
            "",
            };
#endif
      const char* keynames[] = {
            "Treble Clef (G Clef)",
            "",
            "",
            "",
            "Bass Clef (F Clef)",
            "",
            "",
            "",
            "",
            "Soprano Clef",
            "Mezzo-soprano Clef",
            "Alto Clef",
            "Tenor Clef",
            "",
            };
      const char* name = keynames[key.idx()];
      p.drawText(5, 15, QString(name));
      for (int i = 0; i < 5; ++i)
            p.drawLine(xoff, yoff+i*lineD, xoff+w, yoff+i*lineD);
      key.draw(p, QPoint(xoff, yoff));
      scale.draw(key, p, QPoint(xoff + 30, yoff));
      }

//---------------------------------------------------------
//   setKey
//---------------------------------------------------------

void ScoreConfig::setKey(int k)
      {
      canvas->setKey(k);
      if (bg->id(bg->selected()))
            track->keyL.set(k);
      else
            track->key.set(k);
      }

//---------------------------------------------------------
//   setScale
//---------------------------------------------------------

void ScoreConfig::setScale(int s)
      {
      canvas->setScale(s);
      if (bg->id(bg->selected()))
            track->scaleL.set(s);
      else
            track->scale.set(s);
      }

//---------------------------------------------------------
//   selectStaff
//---------------------------------------------------------

void ScoreConfig::selectStaff(int val)
      {
      int ki, si;
      if (val) {
            si = track->scaleL.idx();
            ki = track->keyL.idx();
            }
      else {
            si = track->scale.idx();
            ki = track->key.idx();
            }
      canvas->setScale(si);
      canvas->setKey(ki);
      sb1->setValue(ki);
      sb2->setValue(si);
      }

//---------------------------------------------------------
//   setSplit
//---------------------------------------------------------

void ScoreConfig::setSplit(bool flag)
      {
      splitpoint->setEnabled(flag);
      upper->setEnabled(flag);
      lower->setEnabled(flag);
      if (!flag)
            bg->setButton(0);
      track->mode = flag ? Split : Single;
      }

//---------------------------------------------------------
//   setSplitpoint
//---------------------------------------------------------

void ScoreConfig::setSplitpoint(int val)
      {
      track->splitpoint = val;
      }

//---------------------------------------------------------
//   setTrack
//---------------------------------------------------------

void ScoreConfig::setTrack(PTrack* t)
      {
      track  = t;

      quant1->setCurrentItem(tick2quant(track->noteQuant));
      quant2->setCurrentItem(tick2quant(track->restQuant));

      if ((track->mode == Split) && (bg->id(bg->selected()))) {
            canvas->setScale(track->scaleL.idx());
            canvas->setKey(track->keyL.idx());
            }
      else {
            canvas->setScale(track->scale.idx());
            canvas->setKey(track->key.idx());
            }

      cb1->setChecked(track->mode == Split);
      splitpoint->setEnabled(track->mode == Split);
      upper->setEnabled(track->mode == Split);
      lower->setEnabled(track->mode == Split);
      splitpoint->setValue(track->splitpoint);
      QString s(tr("Staff Settings: "));
      s += track->track->name();
      setCaption(s);
      }

//---------------------------------------------------------
//   trackSelected
//    track selected in listbox
//---------------------------------------------------------

void ScoreConfig::trackSelected(QListBoxItem* item)
      {
      int idx = tl->index(item);
      typedef std::list<MidiTrack*>::iterator iTrack;
      int k = 0;
      for (iPTrack i = tracks.begin(); i != tracks.end(); ++i, ++k) {
            if (k == idx) {
                  updateCurrentTrack();
                  setTrack(&*i);
                  break;
                  }
            }
      }

//---------------------------------------------------------
//   showScoreConfig
//---------------------------------------------------------

void Score::showScoreConfig()
      {
      if (!scoreConfig) {
            scoreConfig = new ScoreConfig(this, "scoreConfig");
            connect(scoreConfig, SIGNAL(trackChanged(int)), canvas, SLOT(songChanged(int)));
            }
      scoreConfig->show();
      scoreConfig->setTracklist(canvas->getSystem()->tracks());
      }

//---------------------------------------------------------
//   setTracklist
//---------------------------------------------------------

void ScoreConfig::setTracklist(TrackList* t)
      {
      int idx = 0;
      tracks.clear();
      tl->clear();
      for (iTrack i = t->begin(); i != t->end(); ++i, ++idx) {
            MidiTrack* mt = (MidiTrack*)(*i);
            tl->insertItem(mt->name(), idx);
            PTrack pt;
            pt.track = mt;
            pt.noteQuant = mt->noteQuant;
            pt.restQuant = mt->restQuant;
            pt.scale     = mt->scale;
            pt.key       = mt->key;
            pt.scaleL    = mt->scaleL;
            pt.keyL      = mt->keyL;
            pt.splitpoint = mt->splitpoint;
            pt.mode      = mt->mode;
            tracks.push_back(pt);
            }
      setTrack(&tracks.front());
      tl->setSelected(0, true);
      }

//---------------------------------------------------------
//   ScoreConfig
//---------------------------------------------------------

ScoreConfig::ScoreConfig(QWidget* parent, const char* name)
   : QDialog(parent, name)
      {
      QGridLayout* grid = new QGridLayout(this);

      //---------------------------------------------------
      //    Tracklist
      //---------------------------------------------------

      QVBoxLayout* vb = new QVBoxLayout;
      vb->addWidget(new QLabel(tr("Track List"), this));
      tl = new QListBox(this);
      tl->setSelectionMode(QListBox::Single);
      vb->addWidget(tl);
      connect(tl, SIGNAL(clicked(QListBoxItem*)), SLOT(trackSelected(QListBoxItem*)));

      //---------------------------------------------------
      //    Key/Clef
      //---------------------------------------------------

      w1     = new QGroupBox(1, Horizontal, tr("Key/Clef"), this);

      QHBox* hb1 = new QHBox(w1);
      sb1    = new QScrollBar(0, NUM_KEYS-1, 1, 1, 0, Vertical, hb1, "sb1");
      canvas = new ScoreLabel(hb1, "canvas");
      hb1->setStretchFactor(canvas, 100);
      sb2    = new QScrollBar(-7, 7, 1, 1, 0, Vertical, hb1, "sb2");

      QHBox* hb2 = new QHBox(w1);
      upper  = new QRadioButton(tr("Upper Staff"), hb2);
      lower  = new QRadioButton(tr("Lower Staff"), hb2);

      bg     = new QButtonGroup(hb2);
      bg->hide();
      bg->insert(upper, 0);
      bg->insert(lower, 1);
      bg->setButton(0);

      connect(bg,  SIGNAL(clicked(int)), SLOT(selectStaff(int)));
      connect(sb1, SIGNAL(valueChanged(int)), SLOT(setKey(int)));
      connect(sb2, SIGNAL(valueChanged(int)), SLOT(setScale(int)));

      //---------------------------------------------------
      //    Raster
      //---------------------------------------------------

      w2 = new QGroupBox(2, Horizontal, tr("Raster"), this);
      new QLabel(tr("Note Quantize"), w2);
      quant1 = createQuantCombo(w2);
      new QLabel(tr("Rest Quantize"), w2);
      quant2 = createQuantCombo(w2);

      //---------------------------------------------------
      //    Split Mode
      //---------------------------------------------------

      QWidget* w3 = new QGroupBox(1, Vertical, tr("Mode"), this);
      cb1 = new QCheckBox(tr("Split System"), w3);
      new QLabel(tr("Splitpoint"), w3);
      splitpoint = new PitchEdit(w3);
      splitpoint->setValue(60);
//      splitpoint->setFrame(true);
      connect(cb1, SIGNAL(toggled(bool)), SLOT(setSplit(bool)));
      connect(splitpoint, SIGNAL(valueChanged(int)), SLOT(setSplitpoint(int)));

      //---------------------------------------------------
      //    Cancel & Apply & OK Buttons
      //---------------------------------------------------

      QHBoxLayout* l4 = new QHBoxLayout();
      QPushButton* b1 = new QPushButton(tr("Ok"), this);
      b1->setDefault(true);
      QPushButton* b2 = new QPushButton(tr("Apply"), this);
      QPushButton* b3 = new QPushButton(tr("Cancel"), this);
      b1->setFixedWidth(80);
      b2->setFixedWidth(80);
      b3->setFixedWidth(80);
      l4->addWidget(b1);
      l4->addSpacing(12);
      l4->addWidget(b2);
      l4->addSpacing(12);
      l4->addWidget(b3);
      l4->addStretch(1);
      connect(b1, SIGNAL(clicked()), SLOT(ok()));
      connect(b2, SIGNAL(clicked()), SLOT(apply()));
      connect(b3, SIGNAL(clicked()), SLOT(abort()));

      grid->addWidget(w1, 0, 1);
      grid->addWidget(w2, 1, 1);
      grid->addWidget(w3, 2, 1);
      grid->addLayout(l4, 3, 1);
      grid->addMultiCell(vb, 0, 3, 0, 0);
      }

//---------------------------------------------------------
//   ScoreConfig::apply
//---------------------------------------------------------

void ScoreConfig::apply()
      {
      updateCurrentTrack();
      for (iPTrack i = tracks.begin(); i != tracks.end(); ++i) {
            MidiTrack* mtrack = i->track;
            mtrack->restQuant = i->restQuant;
            mtrack->noteQuant = i->noteQuant;
            mtrack->scale     = i->scale;
            mtrack->key       = i->key;
            mtrack->scaleL    = i->scaleL;
            mtrack->keyL      = i->keyL;
            mtrack->splitpoint = i->splitpoint;
            mtrack->mode      = i->mode;
printf("split %d  mode %d\n", mtrack->splitpoint, mtrack->mode);
            }
      emit trackChanged(-1);
      }

//---------------------------------------------------------
//   updateCurrentTrack
//---------------------------------------------------------

void ScoreConfig::updateCurrentTrack()
      {
      track->noteQuant = quant2tick(quant1->currentItem());
      track->restQuant = quant2tick(quant2->currentItem());
      track->mode      = cb1->isOn() ? Split : Single;
      }

//---------------------------------------------------------
//   ok
//---------------------------------------------------------

void ScoreConfig::ok()
      {
      apply();
      abort();
      }

//---------------------------------------------------------
//   abort
//---------------------------------------------------------

void ScoreConfig::abort()
      {
      close();
      }

