/***************************************************************************
 * songview.cpp: implementation of SongView class
 *
 * This file is part of KTabEdit, a KDE tabulature editor
 *
 * copyright (C) 2003-2006 the KTabEdit development team <mrgwen@gmail.com>
 * copyright (C) 2002-2003 the KGuitar development team <mrgwen@gmail.com>
 ***************************************************************************/

/***************************************************************************
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * See the file COPYING for more information.
 ***************************************************************************/

#include "songview.h"
#include "util/assert.h"

#include <QSplitter>
#include <QUndoStack>
#include <QVBoxLayout>

#include <KAction>
#include <KMessageBox>

#include "bendDialog/bendeditor.h"
#include "chord/chord.h"
#include "tablature/tabtrack.h"
#include "tablature/tabnote.h"
#include "tablature/tabtimes.h"
#include "tablature/tabbar.h"
#include "tablature/tabsong.h"
#include "tablature/trackmode.h"
#include "tablatureModel/tabsongmodel.h"
#include "tablatureplayer/tabsongplayer.h"
#include "track/trackeditview.h"
#include "track/tracklist.h"
#include "track/trackpane.h"
#include "track/trackdrag.h"
#include "melodyeditor.h"
#include "playbacktracker.h"
#include "settrack.h"
#include "songprint.h"
#include "songpropertiesdialog.h"
#include "songviewcommands.h"
#include "timesigdialog.h"

SongView::SongView(TSE3::MidiScheduler* midiScheduler, QUndoStack* commandHistory)
: QWidget(),
  mSplitter(0),
  mSplitterHorizontal(0),
  mLayout(0),
  mMidiScheduler(midiScheduler),
  mCommandHistory(commandHistory),
  mCurrentTrack(0),
  mSong(0),
  mPlaybackTracker(0),
  mSongPrint(0),
  mMelodyEditor(0),
  mTrackEditView(0),
  mTrackList(0),
  mTrackPane(0),
  mTabSongPlayer(0),
  mReadOnly(false)
{
	initSong();
	initUI();
	initActions();
	
	selectTrack(mCurrentTrack);
	mTrackEditView->songPropertiesChanged(mSong->properties());
}

SongView::~SongView()
{
	delete mTrackEditView;
	delete mPlaybackTracker;
	delete mSongPrint;
	delete mMelodyEditor;
	delete mTrackList;
	delete mSong;
}

void SongView::setReadOnly(bool b)
{
	mReadOnly = b;
	mTrackEditView->setReadOnly(b);
}


bool SongView::isReadOnly() const
{
	return mReadOnly;
}


void SongView::propertyChanged()
{
	mTrackEditView->songPropertiesChanged(mSong->properties());
}


void SongView::initSong()
{
	mSong = new TabSongModel(i18n("Unnamed"), 120);
	mCurrentTrack = new TabTrack(FretTab, i18n("Guitar"), 1, 0, 25, 6, 24),
	mCurrentTrack->insertEmptyBar(0);
	mSong->push_front(mCurrentTrack);
	mPlaybackTracker = new PlaybackTracker(this, mSong);
}


void SongView::initLayouts()
{
	mSplitter = new QSplitter(Qt::Vertical, this);
	mSplitterHorizontal = new QSplitter(Qt::Horizontal, mSplitter);
	mLayout = new QVBoxLayout(this);
}


void SongView::initWidgets()
{
	mTrackEditView = new TrackEditView(mCommandHistory, mSplitter);
	mSongPrint = new SongPrint();
	mTrackList = new TrackList(mSong);
	mTrackPane = new TrackPane(mSong, 30, 30);
	mMelodyEditor = new MelodyEditor(mCurrentTrack->properties(), mSplitter);
}

void SongView::buildLayouts()
{
	mLayout->addWidget(mSplitter);
	
	mSplitterHorizontal->addWidget(mTrackPane);
	mSplitterHorizontal->addWidget(mTrackList);
	
	mSplitter->addWidget(mTrackEditView);
	mSplitter->addWidget(mSplitterHorizontal);
	mSplitter->addWidget(mMelodyEditor);
}

void SongView::initUI()
{
	initLayouts();
	initWidgets();
	buildLayouts();
	
	mTrackEditView->songPropertiesChanged(mSong->properties());
	
	connectObjects();
}

void SongView::connectTrackEditView() const
{
	connect(mTrackEditView, SIGNAL(isAccentuated(bool)), this, SIGNAL(isAccentuated(bool)));
	connect(mTrackEditView, SIGNAL(isGhostNote(bool)), this, SIGNAL(isGhostNote(bool)));
	connect(mTrackEditView, SIGNAL(isTieNote(bool)), this, SIGNAL(isTieNote(bool)));
	connect(mTrackEditView, SIGNAL(isHammerOnPullOff(bool)), this, SIGNAL(isHammerOnPullOff(bool)));
	connect(mTrackEditView, SIGNAL(isSlide(bool)), this, SIGNAL(isSlide(bool)));
	connect(mTrackEditView, SIGNAL(isLetRing(bool)), this, SIGNAL(isLetRing(bool)));
	connect(mTrackEditView, SIGNAL(isDynamic(bool)), this, SIGNAL(isDynamic(bool)));
	connect(mTrackEditView, SIGNAL(isFingeringLeft(bool)), this, SIGNAL(isFingeringLeft(bool)));
	connect(mTrackEditView, SIGNAL(isFingeringRight(bool)), this, SIGNAL(isFingeringRight(bool)));
	connect(mTrackEditView, SIGNAL(isLeftHandVibrato(bool)), this, SIGNAL(isLeftHandVibrato(bool)));
	connect(mTrackEditView, SIGNAL(isPalmMute(bool)), this, SIGNAL(isPalmMute(bool)));
	connect(mTrackEditView, SIGNAL(isStaccato(bool)), this, SIGNAL(isStaccato(bool)));
	connect(mTrackEditView, SIGNAL(isTremoloPicking(bool)), this, SIGNAL(isTremoloPicking(bool)));
	connect(mTrackEditView, SIGNAL(isHarmonic(bool)), this, SIGNAL(isHarmonic(bool)));
	connect(mTrackEditView, SIGNAL(isBend(bool)), this, SIGNAL(isBend(bool)));
	connect(mTrackEditView, SIGNAL(isGraceNote(bool)), this, SIGNAL(isGraceNote(bool)));
	connect(mTrackEditView, SIGNAL(isTrill(bool)), this, SIGNAL(isTrill(bool)));
	connect(mTrackEditView, SIGNAL(isRasgueado(bool)), this, SIGNAL(isRasgueado(bool)));
	connect(mTrackEditView, SIGNAL(isPickStroke(bool)), this, SIGNAL(isPickStroke(bool)));
	connect(mTrackEditView, SIGNAL(isTremolo(bool)), this, SIGNAL(isTremolo(bool)));
	connect(mTrackEditView, SIGNAL(isTapping(bool)), this, SIGNAL(isTapping(bool)));
	connect(mTrackEditView, SIGNAL(isPopping(bool)), this, SIGNAL(isPopping(bool)));
	connect(mTrackEditView, SIGNAL(isSlapping(bool)), this, SIGNAL(isSlapping(bool)));
	connect(mTrackEditView, SIGNAL(isStroke(bool)), this, SIGNAL(isStroke(bool)));
	connect(mTrackEditView, SIGNAL(isVibrato(bool)), this, SIGNAL(isVibrato(bool)));
	connect(mTrackEditView, SIGNAL(isFadeIn(bool)), this, SIGNAL(isFadeIn(bool)));
}

void SongView::connectTabSong() const
{
/*	connect(mSong, SIGNAL(songPropertiesChanged(TabProperties*)), mTrackEditView, SLOT(songPropertiesChanged(TabProperties*)));
	connect(mSong, SIGNAL(songPropertyChanged()), mTrackEditView, SLOT(songPropertyChanged()));
	connect(mSong, SIGNAL(trackAdded()), mTrackList, SLOT(updateTrackList()));
	connect(mSong, SIGNAL(trackAdded()), mTrackPane, SLOT(updateTrackList()));
	connect(mSong, SIGNAL(trackDeleted()), mTrackList, SLOT(updateTrackList()));
	connect(mSong, SIGNAL(trackDeleted()), mTrackPane, SLOT(updateTrackList()));
	connect(mSong, SIGNAL(songDeleted()), mTrackList, SLOT(clearView()));*/
}

void SongView::connectObjects()
{
	mSong->attach(this);
	mSong->attach(mTrackList);
	mSong->attach(mTrackPane);
	
	connect(mTrackList, SIGNAL(trackChanged(TabTrack*)), this, SLOT(selectTrack(TabTrack*)));
	connect(mTrackList, SIGNAL(trackChanged(TabTrack*)), mTrackEditView, SLOT(setTabTrack(TabTrack*)));
	connect(mTrackList, SIGNAL(trackChanged(TabTrack*)), mTrackPane, SLOT(setTabTrack(TabTrack*)));
	
	connect(mTrackList, SIGNAL(addTrack()), this, SLOT(trackNew()));
	connect(mTrackList, SIGNAL(deleteTrack(TabTrack*)), this, SLOT(trackDelete(TabTrack*)));
	connect(mTrackList, SIGNAL(trackProperties()), this, SLOT(trackProperties()));
	
	connect(mTrackPane, SIGNAL(trackChanged(TabTrack*)), this, SLOT(selectTrack(TabTrack*)));
	connect(mTrackPane, SIGNAL(trackChanged(TabTrack*)), mTrackEditView, SLOT(setTabTrack(TabTrack*)));
	connect(mTrackPane, SIGNAL(trackChanged(TabTrack*)), mTrackList, SLOT(setTabTrack(TabTrack*)));
	connect(this, SIGNAL(trackPropertiesChanged(const TrackProperties*)), mMelodyEditor, SLOT(setTrackProperties(const TrackProperties*)));
	
	//TODO Following 2 connects wrong: no such signals undo() and redo(). They are slots!
	connect(mCommandHistory, SIGNAL(undo()), this, SLOT(refreshCommand()));
	connect(mCommandHistory, SIGNAL(redo()), this, SLOT(refreshCommand()));
	
	connectTrackEditView();
	connectTabSong();
	
	mTrackList->updateTrackList();
}

void SongView::initActions()
{
	KAction* mainAccel;
	
	// Setup accel
	//
	mainAccel = new KAction(this);
	
	new KAction(i18n("Move cursor to the beginning of bar"),this); //i18n("Home"), Qt::Key_Home, this, SLOT(keyHome()));
	new KAction(i18n("Move cursor to the end of bar"), this); //, Qt::Key_End, this, SLOT(keyEnd()));
	new KAction(i18n("Move cursor to the beginning of track"), this); // i18n("Ctrl+Home"), KKeySequence("Ctrl+Home").keyCodeQt(), this, 
			//SLOT(keyCtrlHome()));
	new KAction(i18n("Move cursor to the end of track"), this); //i18n("Ctrl+End"), KKeySequence("Ctrl+End").keyCodeQt(), this, 
			//SLOT(keyCtrlEnd()));
	new KAction(i18n("Move and select left"), this); //i18n("Shift+Left"), Qt::Key_Shift + Qt::Key_Left, this, SLOT(selectLeft()));
	new KAction(i18n("Move and select right"), this); //i18n("Shift+Right"), Qt::Key_Shift + Qt::Key_Right, this, SLOT(selectRight()));
	new KAction(i18n("Transpose up"), this); //i18n("Ctrl+Up"), Qt::Key_Control + Qt::Key_Up, this, SLOT(transposeUp()));
	new KAction(i18n("Transpose down"),this); //i18n( "Ctrl+Down"), Qt::Key_Control + Qt::Key_Down, this, SLOT(transposeDown()));
	
	new KAction(i18n("Dead note"), this); //i18n("X"), Qt::Key_X, this, SLOT(deadNote()));
	new KAction(i18n("Delete note"), this); //i18n("Delete"), Qt::Key_Delete, this, SLOT(deleteNote()));
	new KAction(i18n("Delete column"), this); //i18n("Ctrl+Delete"), Qt::Key_Control + Qt::Key_Delete, this, SLOT(deleteColumn()));
	new KAction(i18n("Insert column"), this); //i18n("Insert"), Qt::Key_Insert, this, SLOT(insertColumn()));
	new KAction(i18n("Dotted note"), this); //i18n("Period"), Qt::Key_Period, this, SLOT(dotNote()));
	new KAction(i18n("Triplet note"), this); //i18n("T"), Qt::Key_T, this, SLOT(ntuplet()));
	
/*	mViewMelodyEditorAction->setChecked(Settings::config->readBoolEntry("Visible", TRUE));
	mViewScoreAction->setChecked(true);*/
}

void SongView::setTabSong(TabSong* tabSong)
{
	PRECONDITION( tabSong != 0x0 );
	
	mTrackEditView->songChanged(tabSong->properties(), tabSong->front());
	mSong->setTabSong(tabSong);
}

TabSong* SongView::tabSong() const
{
	return mSong->tabSong();
}

void SongView::setMidiScheduler(TSE3::MidiScheduler* midiScheduler)
{
	mMidiScheduler = midiScheduler;
}

uint SongView::trackSelected() const
{
	return 0;
}

/***************************************************************************
 *                                                                         *
 * Track actions                                                           *
 *                                                                         *
 ***************************************************************************/

void SongView::refreshCommand()
{
	//mTrackList->updateList();
	mTrackPane->updateTrackList();
}


void SongView::selectTrack(TabTrack* tabTrack)
{
	PRECONDITION(tabTrack != 0);
	
	mCurrentTrack = tabTrack;
	emit trackPropertiesChanged(mCurrentTrack->properties());
}


bool SongView::setTrackProperties(TrackProperties* trackProperties)
{
	bool result;
	SetTrack* setTrack = new SetTrack(trackProperties, mSong);
	
	if (setTrack->exec() == QDialog::Accepted) {
		trackProperties->setName(setTrack->title());
		trackProperties->setChannel(setTrack->channel());
		trackProperties->setBank(setTrack->bank());
		trackProperties->setPatch(setTrack->patch());
		trackProperties->setMode(setTrack->mode());
		
		trackProperties->setVolume(setTrack->volume());
		trackProperties->setBalance(setTrack->balance());
		trackProperties->setChorus(setTrack->chorus());
		trackProperties->setReverb(setTrack->reverb());
		
		trackProperties->setNbStrings(setTrack->strings());
		trackProperties->setNbFrets(setTrack->frets());
		
		for (int i = 0; i < trackProperties->nbStrings(); i++)
			trackProperties->setTune(i, setTrack->tune(i));
		
		result = true;
	} else
		result = false;
	
	delete setTrack;
	return result;
}


void SongView::trackNew()
{
	TabTrack* tabTrack = new TabTrack(FretTab, "", 0, 0, 25, 6, 24);
	tabTrack->insertEmptyBar(0);
	
	if (setTrackProperties(tabTrack->properties()) == true) {
		mCommandHistory->push(new AddTrackCommand(mSong, tabTrack));
		emit statusBar("Track added");
	}
}


void SongView::trackDelete(TabTrack* track)
{
	qDebug() << "[SongView::trackDelete] : " << mCurrentTrack <<  " \n";
	mCommandHistory->push(new DeleteTrackCommand(mSong, mCurrentTrack));
	emit statusBar("Track deleted");
}


void SongView::trackDelete()
{
	trackDelete(mCurrentTrack);
}


void SongView::trackProperties()
{
	TrackProperties* trackProperties = new TrackProperties();
	SetTrack* setTrack = new SetTrack(mCurrentTrack->properties(), mSong);
	
	if (setTrack->exec() == QDialog::Accepted) {
		trackProperties->setName(setTrack->title());
		trackProperties->setChannel(setTrack->channel());
		trackProperties->setBank(setTrack->bank());
		trackProperties->setPatch(setTrack->patch());
		trackProperties->setMode(setTrack->mode());
		
		trackProperties->setVolume(setTrack->volume());
		trackProperties->setBalance(setTrack->balance());
		trackProperties->setChorus(setTrack->chorus());
		trackProperties->setReverb(setTrack->reverb());
		
		trackProperties->setNbStrings(setTrack->strings());
		trackProperties->setNbFrets(setTrack->frets());
		
		for (int i = 0; i < trackProperties->nbStrings(); i++)
			trackProperties->setTune(i, setTrack->tune(i));
		
		mCommandHistory->push(new SetTrackPropCommand(trackProperties, mCurrentTrack));
		emit statusBar("Track properties changed");
	}
	
	delete setTrack;
}

void SongView::songProperties()
{
	SongPropertiesDialog propertiesDlg(mSong->properties());
	
	if(propertiesDlg.exec() == QDialog::Accepted) {
		mCommandHistory->push(new SetSongPropCommand(mSong, propertiesDlg.properties()));
		emit statusBar("Song properties changed");
	}
}


/***************************************************************************
 *                                                                         *
 * Length actions                                                          *
 *                                                                         *
 ***************************************************************************/

void SongView::refreshView()
{
	//mTrackList->updateList();
}

void SongView::drawBackground()
{
	mMelodyEditor->drawBackground();
}

void SongView::zoomIn()
{
	mTrackEditView->zoomIn(1.25);
}

void SongView::zoomOut()
{
	mTrackEditView->zoomOut(0.80);
}

void SongView::showScore(bool b)
{
 	mTrackEditView->viewScore(b);
}

void SongView::showMelodyEditor(bool b)
{
	if (b == true)
		mMelodyEditor->show();
	else
		mMelodyEditor->hide();
}

// Generates a new track with a basic bass line, derived from current
// track's rhythm
//
void SongView::trackBassLine()
{
/*	const TabTrack& currentTrack = *trackEditView->getTrack();
	
	if (currentTrack.mode() == DrumTab) {
		KMessageBox::sorry(this, i18n("Can not generate a bass line from drum track"));
		return;
	}
	
	if (trackNew() == true) {
		TabTrack& newTrack = *trackEditView->getTrack();
// 		newTrack.tabColumnResize(currentTrack.getTabColumnSize());
		ChordSelector cs(currentTrack);
		
		int note;
		
		for (uint i = 0; i < currentTrack.getTabColumnSize(); i++) {
			for (uint k = 0; k < currentTrack.nbStrings(); k++)
				cs.setApp(k, currentTrack.getVectTabColumn(i).getNbFret(k));
				
				cs.detectChord();
				
				if ((ChordListItem *)cs.getChordList().item(0)) {
					note = ((ChordListItem *)cs.getChordList().item(0))->tonic();
					qDebug() << "Column " << i << ", detected tonic " << Settings::noteName(note) << endl;
				} else {
					note = -1;
					qDebug() << "Column " << i << ", EMPTY " << endl;
				}
				
				TabColumn tab = newTrack.getVectTabColumn(i);
				
				for (uint k = 0; k < MAX_STRINGS; k++) {
					tab.setNbFret(k, -1);
					tab.setEffect(k, 0);
				}
	
				tab.setDuration(currentTrack.getVectTabColumn(i).getDuration());
				tab.setFlags(currentTrack.getVectTabColumn(i).getFlags());
				
				// GREYFIX: make a better way of choosing a fret. This way
				// it can, for example, be over max frets number.
				if (note >= 0) {
					tab.setNbFret(0, note - newTrack.tune(0) % 12);
	
					if (newTrack.getVectTabColumn(i).getNbFret(0) < 0)
						tab.setNbFret(0, tab.getNbFret(0) + 12);
				}
				
				newTrack.setVectTabColumn(i, tab);
		}
	}
	
	trackEditView->arrangeTracks();*/
}

void SongView::addBar()
{
	mTrackEditView->insertBar();
}

void SongView::deleteBar()
{
	mTrackEditView->deleteBar();
}

void SongView::keySignature()
{
}

void SongView::timeSignature()
{
}

void SongView::addTime()
{
	mTrackEditView->insertTime();
}

void SongView::deleteTime()
{
	mTrackEditView->deleteTime();
}

void SongView::addChord()
{
	ChordSelector *chord = new ChordSelector(mMidiScheduler, *mCurrentTrack);
	chord->exec();
}

void SongView::setDefaultDuration(Duration d)
{
}

void SongView::setLengthWhole()
{
	mTrackEditView->setDuration(Whole);
}

void SongView::setLengthHalf()
{
	mTrackEditView->setDuration(Half);
}

void SongView::setLengthQuarter()
{
	mTrackEditView->setDuration(Quarter);
}

void SongView::setLengthEighth()
{
	mTrackEditView->setDuration(Eighth);
}

void SongView::setLengthSixteenth()
{
	mTrackEditView->setDuration(Sixteenth);
}

void SongView::setLengthThirtySecond()
{
	mTrackEditView->setDuration(ThirthSecond);
}

void SongView::setLengthSixtyFourth()
{
	mTrackEditView->setDuration(SixtyFourth);
}

void SongView::setDotted()
{
	mTrackEditView->switchDotted();
}

void SongView::setRest()
{
	mTrackEditView->setRest();
}

void SongView::setLinkPrev()
{
	mTrackEditView->setTieNote(true);
}

void SongView::setLegato()
{
	mTrackEditView->setHammerOnPullOff(true);
}

void SongView::setSlide()
{
	mTrackEditView->setSlide(ShiftSlide);
}

void SongView::setLetRing()
{
	mTrackEditView->setLetRing(true);
}

void SongView::setHarmonic()
{
	mTrackEditView->setHarmonic(Natural);
}

void SongView::setPalmMuting()
{
	mTrackEditView->setPalmMute(true);
}

void SongView::setBend()
{
	BendEditor bendEditor;
	
	if (bendEditor.exec() == QDialog::Accepted)
		mTrackEditView->setBend(bendEditor.bend());
}

void SongView::setVibrato()
{
}

void SongView::setTrill()
{
}

void SongView::setTapping()
{
}

void SongView::setTremolo()
{
}

void SongView::playSong()
{
	qDebug() << "playTheSong\n";
	
	if (!mMidiScheduler) {
		qDebug() << "unable to find a midi scheduler\n";
		return ;
	}
	
// 	mTrackEditView->beginPlaying();
// 	mTrackEditView->stopPlaying();
	
	if (mTabSongPlayer) {
		mTabSongPlayer->stopPlaying();
		
		while (mTabSongPlayer->running())
			;
		
		delete mTabSongPlayer;
	}
	
	mTabSongPlayer = new TabSongPlayer(mSong, mPlaybackTracker);
	
	mTabSongPlayer->setScheduler(mMidiScheduler);
	mTabSongPlayer->start();
}


void SongView::stopPlay()
{
	qDebug() << "stopTheSong\n";
	
// 	mTrackEditView->stopPlaying();
	
	if (mTabSongPlayer) {
		mTabSongPlayer->stopPlaying();
		
		while (mTabSongPlayer->running())
			;
		
		delete mTabSongPlayer;
		
		mTabSongPlayer = 0;
	}
}


void SongView::cut()
{
// 	if (!trackEditView->getTrack()->getSel()) {
// 		KMessageBox::error(this, i18n("There is no selection!"));
// 		return;
// 	}

// 	QApplication::clipboard()->setData(new TrackDrag(highlightedTabs()));
// 	trackEditView->deleteColumn(i18n("Cut to clipboard"));
}


void SongView::copy()
{
	mTrackEditView->copy();
/*	Clipboard clipDlg(mTrackEditView->getBarPosition() + 1, mTrackEditView->getBarNumber(), this, "clipboard copy");
	
	if (clipDlg.exec() == QDialog::Accepted) {
		TabTrack tempTrack;
		TabTrack* currentTrack;
		uint from;
		uint to;
		
		currentTrack = mTrackEditView->getTrack();
		from = clipDlg.getFrom() - 1;
		to = clipDlg.getTo();
		
		for (uint i = from; i < to; i++) {
			TabBar tempBar = currentTrack->bar(i);
			
			tempTrack.addBar(tempBar);
		}
		
		*dynamic_cast<TrackProperties*>(&tempTrack) = *dynamic_cast<TrackProperties*>(currentTrack);
		
		QApplication::clipboard()->setData(new TrackDrag(tempTrack));
		emit statusBar("Bar(s) copy");
	}*/
}


void SongView::paste()
{
	mTrackEditView->paste();
	
// 	mTrackEditView->update();
}


void SongView::selectAll()
{
/*	trackEditView->getTrack()->setXSel(0);
	trackEditView->getTrack()->setTabColumn(trackEditView->getTrack()->getTabColumnSize() - 1);
	trackEditView->getTrack()->setSel(TRUE);

	trackEditView->update();*/
}


TabTrack *SongView::highlightedTabs()
{
/*	if (!trackEditView->getTrack()->getSel())  return NULL;

	TabTrack* trk = trackEditView->getTrack();
	TabTrack* newtrk = new TabTrack(trk->mode(), "ClipboardTrack", trk->getChannel(),
									trk->getBank(), trk->getPatch(), trk->nbStrings(), trk->nbFrets());
									
	for (int i = 0; i < trk->nbStrings(); i++)
		newtrk->setTune(i,trk->tune(i));

	uint pdelta, pstart, pend;

	if (trk->getTabColumn() <= trk->getXSel()) {
		pend = trk->getXSel();
		pstart = trk->getTabColumn();
	} else {
		pend = trk->getTabColumn();
		pstart = trk->getXSel();
	}

	pdelta = pend - pstart + 1;

	newtrk->tabColumnResize(pdelta);
	int _s = pstart;

	for (uint i = 0; i < pdelta; i++) {
		TabColumn tab = newtrk->getVectTabColumn(i);
		
		for (uint k = 0; k < MAX_STRINGS; k++) {
				tab.setNbFret(k, -1);
				tab.setEffect(k, 0);
		}

		tab.setDuration(trk->getVectTabColumn(_s).getDuration());
		tab.setFlags(trk->getVectTabColumn(_s).getFlags());

		for (uint k = 0; k < newtrk->nbStrings(); k++) {
			tab.setNbFret(k, trk->getVectTabColumn(_s).getNbFret(k));
			tab.setEffect(k, trk->getVectTabColumn(_s).getEffect(k));
		}

		newtrk->setVectTabColumn(i, tab);

		_s++;
	}
*/
	return NULL;
}

void SongView::insertTabs(TabTrack& tempTrack)
{
// // /*	QString msg;
// // 	bool err = false, errtune = false;
// // 	TabTrack* currentTrack = mTrackEditView->getTrack();
// // 	
// // 	if (currentTrack->mode() != tempTrack.mode()) {
// // 		msg += i18n("The clipboard data does not have the same track mode.\n");
// // 		err = true;
// // 	}
// // 	
// // 	if (currentTrack->nbStrings() != tempTrack.nbStrings()) {
// // 		msg += i18n("The clipboard data does not have the same number of strings.\n");
// // 		err = true;
// // 	} else {
// // 		for (int i = 0; i < currentTrack->nbStrings(); i++) {
// // 			if (currentTrack->tune(i) != tempTrack.tune(i))  errtune = true;
// // 			if (errtune) break;
// // 		}
// // 		
// // 		if (errtune) {
// // 			msg += i18n("The clipboard data does not have the same tuneing.\n");
// // 			err = true;
// // 		}
// // 	}
// // 	
// // 	if (currentTrack->nbFrets() != tempTrack.nbFrets()) {
// // 		msg += i18n("The clipboard data does not have the same number of frets.\n");
// // 		err = true;
// // 	}
// // 	
// // 	if (err) {
// // 		msg += i18n("\n\nI'll improve this code. So some of these problems\n");
// // 		msg += i18n("will be solved in the future.");
// // 		KMessageBox::error(this, msg);
// // 		return;
// // 	}
// // 	
// // 	mCommandHistory->push(new InsertTabsCommand(*mTrackEditView, *currentTrack, tempTrack, mTrackEditView->getBarPosition()));
// // 	emit statusBar("Bar(s) paste");*/
}


void SongView::print(QPrinter* printer)
{
	//printer->setFullPage(true);
	
	KMessageBox::information( this, "KTabEdit",
	"The printing support is not yet finished.\n"
	"Do not print a document in your printer but in a pdf or ps file instead !" );
	
	//if (printer->setup(this))
	//	mSongPrint->printSong(printer, mSong);
}


void SongView::playbackCursor(int track, const TrackPos& position)
{
// 	TabTrack* trk = mTabSong->at(track);
	
/*	if (mTrackEditView->getTrack() == trk) {
		mTrackEditView->setCursor(position);
		kapp->postEvent(mTrackEditView, new QKeyEvent(QEvent::KeyRelease, 0, 0, 0));
	}*/
}


/**
\brief Insert an full bend effect.
*/
void SongView::fullBend()
{
}

/**
\brief Insert an half bend and release effect.
*/
void SongView::halfBendRelease()
{
}

/**
\brief Insert an full bend and release effect.
*/
void SongView::fullBendRelease()
{
}

/**
\brief Insert an half pre bend effect.
*/
void SongView::halfPreBend()
{
}

/**
\brief Insert an full pre bend effect.
*/
void SongView::fullPreBend()
{
}

/**
\brief Insert an half pre bend and release effect.
*/
void SongView::halfPreBendRelease()
{
}

/**
\brief Insert an full pre bend and release effect.
*/
void SongView::fullPreBendRelease()
{
}

/**
\brief Insert an unison bend effect.
*/
void SongView::unisonBend()
{
}

/**
\brief Insert a wide vibrato effect.
*/
void SongView::wideVibrato()
{
}

/**
\brief Insert a muffled strings effect.
*/
void SongView::muffledStrings()
{
}


/**
\brief Insert a tremolo picking effect.
*/
void SongView::tremoloPicking()
{
}


/**
\brief Sets the key signature
*/
void SongView::keySig()
{
	kDebug() << "SongView::keySig() called" << "\n";
}


/**
\brief Sets the time signature
*/
void SongView::timeSig()
{
	kDebug() << "SongView::timeSig() called" << "\n";
	
	TimeSigDialog tsd;
	tsd.exec();
}

/**
	Insert an artificial harmonic effect.
*/
void SongView::addArtHarm()
{
}


/**
	Insert a slide effect.
*/
void SongView::addSlide()
{
}


/**
	Insert a rythmer effect.
*/
void SongView::rhythmer()
{
}


/**
	move the cursor to an high string.
*/
void SongView::transposeUp()
{
}

/**
	move the cursor to an high string.
*/
void SongView::transposeDown()
{
}

/**
	move the cursor to an high string.
*/
void SongView::selectLeft()
{
}

/**
	move the cursor to an high string.
*/
void SongView::selectRight()
{
}

/**
	move the cursor to an high string.
*/
void SongView::deadNote()
{
}

/**
	Insert a palm mute effect.
*/
void SongView::palmMute()
{
}

/**
	Insert a dot note effect.
*/
void SongView::dotNote()
{
}

/**
	Select a n-tuplet number.
*/
void SongView::ntupletSelected(int n)
{
}

/**
	Insert a n-tuplet effect.
*/
void SongView::ntuplet()
{
}

/**
	Set the length of a note.
*/
void SongView::arrangeTracks()
{
}

/**
	Actions of the melody editor
*/
void SongView::melodyEditorPress(int, int, Qt::ButtonState)
{
}

/**
	I DON'T KNOW
*/
void SongView::melodyEditorRelease(Qt::ButtonState)
{
}

/**
	I DON'T KNOW
*/
void SongView::setPlaybackCursor(bool)
{
}

/**
	I DON'T KNOW
*/
void SongView::viewScore(bool)
{
}

/**
	Number of bar.
	\return return the number of bar.
*/
uint SongView::getBarNumber()
{
}


/**
\brief Returns the Bar number, where the cursor is
*/
uint SongView::getBarPosition()
{
}


/**
\brief Set the string position of the cursor
This function is used by songviewcommand when the user change the number of strings
*/
void SongView::setString(uint i)
{
}


/**
\brief Return the string position of the cursor 
This function is used by songviewcommand when the user change the number of strings
*/
uint SongView::string()
{
}


void SongView::mousePressEvent(QMouseEvent* event)
{
	// RightButton pressed
	//
	/*if (event->button() == Qt::RightButton) {
		QWidget* widget = 0;
		KMenu* popupMenu = 0;
		
		widget = mXmlGuiClient->factory()->container("trackviewpopup", mXmlGuiClient);
		
		if (!widget || !widget->inherits("KPopupMenu")) {
			kDebug() << "SongView::mousePressEvent => wrong container widget" << endl;
			return;
		}
		
		popupMenu = static_cast<KMenu*>(widget);
		popupMenu->popup(QCursor::pos());
	}*/
	
	// LeftButton pressed
	//
	if (event->button() == Qt::LeftButton) {
	}
}

#include "songview.moc"
