/*****************************************************************************
 *
 *  x264partitionsdialog.cpp -- Control to select x264 partiions parameter.
 *
 *  Copyright (C) 2010 Starbuck <starbuck@labdv.com>
 *  All rights reserved.
 *
 *  This file is part of the Gui4 module of the DVDx 4 application.
 *
 *  GNU Lesser General Public License Usage
 *  This file may be used under the terms of the GNU Lesser General
 *  Public License version 2.1 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.LGPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU Lesser General Public License version 2.1 requirements
 *  will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 *
 *  GNU General Public License Usage
 *  Alternatively, this file may be used under the terms of the GNU
 *  General Public License version 3.0 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.GPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU General Public License version 3.0 requirements will be
 *  met: http://www.gnu.org/copyleft/gpl.html.
 *
 *****************************************************************************/

#include "x264partitionsdialog.h"
#include <QtGui>
#include <QString>

x264PartitionsDialog::x264PartitionsDialog(QString *partitions, 
		const QString &defaults,
		QWidget *parent)
	: QDialog(parent)
{
	setWindowTitle( tr("H.264 macroblock partitioning") );
	setMinimumWidth( 280 );

	QVBoxLayout *mainLayout = new QVBoxLayout(this);

	QGridLayout *macroblockGLayout = new QGridLayout(this);
	macroblockGLayout->setContentsMargins(-1, 8, -1, -1);

	QLabel *iframesLabel = new QLabel(tr("I-Frames:"), this);
	QLabel *pframesLabel = new QLabel(tr("P-Frames:"), this);
	QLabel *bframesLabel = new QLabel(tr("B-Frames:"), this);

	i8x8CheckBox = new QCheckBox(tr("i8x8"), this);
	i4x4CheckBox = new QCheckBox(tr("i4x4"), this);
	p8x8CheckBox = new QCheckBox(tr("p8x8"), this);
	p4x4CheckBox = new QCheckBox(tr("p4x4"), this);
	b8x8CheckBox = new QCheckBox(tr("b8x8"), this);

	macroblockGLayout->addWidget(iframesLabel, 0, 0, 1, 1);
	macroblockGLayout->addWidget(i8x8CheckBox, 0, 1, 1, 1);
	macroblockGLayout->addWidget(i4x4CheckBox, 1, 1, 1, 1);
	macroblockGLayout->addWidget(pframesLabel, 2, 0, 1, 1);
	macroblockGLayout->addWidget(p8x8CheckBox, 2, 1, 1, 1);
	macroblockGLayout->addWidget(p4x4CheckBox, 3, 1, 1, 1);
	macroblockGLayout->addWidget(bframesLabel, 4, 0, 1, 1);
	macroblockGLayout->addWidget(b8x8CheckBox, 4, 1, 1, 1);

	// Add an empty 3rd column
	QSpacerItem *columnSpacer = new QSpacerItem(60, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
	macroblockGLayout->addItem(columnSpacer, 0, 2, 1, 1);

	QGroupBox *choiceGroupBox = new QGroupBox(tr("Choose a partinioning"), this);
	QVBoxLayout *chooseVLayout = new QVBoxLayout(choiceGroupBox);

	allRadioButton = new QRadioButton(tr("All"), choiceGroupBox);
	customRadioButton = new QRadioButton(tr("Custom"), choiceGroupBox);
	noneRadioButton = new QRadioButton(tr("None"), choiceGroupBox);

	chooseVLayout->addWidget(allRadioButton);
	chooseVLayout->addWidget(customRadioButton);
	chooseVLayout->addWidget(noneRadioButton);

	QPushButton *defaultPushButton = new QPushButton(tr("Default partitioning"), this);
	defaultPushButton->setToolTip(tr("Reload default macroclock partitioning"));

	buttonBox = new QDialogButtonBox(this);
	buttonBox->setOrientation(Qt::Horizontal);
	buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);

	QSpacerItem *v1Spacer = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
	QSpacerItem *v2Spacer = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);

	mainLayout->addLayout(macroblockGLayout);
	mainLayout->addItem(v1Spacer);
	mainLayout->addWidget(choiceGroupBox);
	mainLayout->addWidget(defaultPushButton);
	mainLayout->addItem(v2Spacer);
	mainLayout->addWidget(buttonBox);

	setLayout(mainLayout);

	setAttribute(Qt::WA_AlwaysShowToolTips);

	strPartitions = partitions;  // to store the user input before closing

	stringToBlocks( *strPartitions, &blkPartitions );

	strDefaults = defaults;

	updateControls();

	connect(i8x8CheckBox, SIGNAL(released()), 
		this, SLOT(checkASplit()));
	connect(i4x4CheckBox, SIGNAL(released()), 
		this, SLOT(checkASplit()));
	connect(p8x8CheckBox, SIGNAL(released()), 
		this, SLOT(checkASplit()));
	connect(p4x4CheckBox, SIGNAL(released()), 
		this, SLOT(checkASplit()));
	connect(b8x8CheckBox, SIGNAL(released()), 
		this, SLOT(checkASplit()));

	connect(allRadioButton, SIGNAL(released()), 
		this, SLOT(checkAChoice()));
	connect(noneRadioButton, SIGNAL(released()), 
		this, SLOT(checkAChoice()));

	connect(defaultPushButton, SIGNAL(released()), 
		this, SLOT(defaultPushButtonClicked()));

	connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
	connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}

void x264PartitionsDialog::updateControls()
{
	QString partitions;

	i8x8CheckBox->setChecked( blkPartitions.i8x8 );
	i4x4CheckBox->setChecked( blkPartitions.i4x4 );
	p8x8CheckBox->setChecked( blkPartitions.p8x8 );
	p4x4CheckBox->setChecked( blkPartitions.p4x4 );
	b8x8CheckBox->setChecked( blkPartitions.b8x8 );

	blocksToString( blkPartitions, &partitions );

	allRadioButton->setChecked( partitions == "all" );
	noneRadioButton->setChecked( partitions == "none" );
	customRadioButton->setChecked( partitions != "all" && *strPartitions != "none" );
}

void x264PartitionsDialog::defaultPushButtonClicked()
{
	stringToBlocks( strDefaults, &blkPartitions );

	updateControls();
}

void x264PartitionsDialog::checkASplit()
{
	if ( i8x8CheckBox->isChecked()
		&& i4x4CheckBox->isChecked()
		&& p8x8CheckBox->isChecked()
		&& p4x4CheckBox->isChecked()
		&& b8x8CheckBox->isChecked() )
	{
		allRadioButton->setChecked( true );
	}
	else if ( !i8x8CheckBox->isChecked()
		&& !i4x4CheckBox->isChecked()
		&& !p8x8CheckBox->isChecked()
		&& !p4x4CheckBox->isChecked()
		&& !b8x8CheckBox->isChecked() )
	{
		noneRadioButton->setChecked( true );
	}
	else
	{
		customRadioButton->setChecked( true );
	}
}

void x264PartitionsDialog::checkAChoice()
{
	if ( allRadioButton->isChecked() )
	{
		i8x8CheckBox->setChecked( true );
		i4x4CheckBox->setChecked( true );
		p8x8CheckBox->setChecked( true );
		p4x4CheckBox->setChecked( true );
		b8x8CheckBox->setChecked( true );
	}
	else if ( noneRadioButton->isChecked() )
	{
		i8x8CheckBox->setChecked( false );
		i4x4CheckBox->setChecked( false );
		p8x8CheckBox->setChecked( false );
		p4x4CheckBox->setChecked( false );
		b8x8CheckBox->setChecked( false );
	}

}

void x264PartitionsDialog::accept()
{
	if ( allRadioButton->isChecked() )
	{
		*strPartitions = "all";
	}
	else if ( noneRadioButton->isChecked() )
	{
		*strPartitions = "none";
	}
	else // if ( customRadioButton )
	{
		blkPartitions.i8x8 = i8x8CheckBox->isChecked();
		blkPartitions.i4x4 = i4x4CheckBox->isChecked();
		blkPartitions.p8x8 = p8x8CheckBox->isChecked();
		blkPartitions.p4x4 = p4x4CheckBox->isChecked();
		blkPartitions.b8x8 = b8x8CheckBox->isChecked();
		
		blocksToString( blkPartitions, strPartitions );
	}

	QDialog::accept();
}

void x264PartitionsDialog::stringToBlocks(const QString &s, mb_t *b)
{
	if ( s == "none" )
	{
		b->clear();
		return;
	}
	
	if ( s == "all" )
	{
		b->all();
		return;
	}

	b->i8x8 =  s.contains("i8x8", Qt::CaseInsensitive);
	b->i4x4 =  s.contains("i4x4", Qt::CaseInsensitive);
	b->p8x8 =  s.contains("p8x8", Qt::CaseInsensitive);
	b->p4x4 =  s.contains("p4x4", Qt::CaseInsensitive);
	b->b8x8 =  s.contains("b8x8", Qt::CaseInsensitive);
}

void x264PartitionsDialog::blocksToString(const mb_t &b, QString *s)
{
	s->clear();

	if ( b.p8x8 )
	{
		if ( !s->isEmpty() ) s->append(",");

		s->append("p8x8");
	}

	if ( b.p4x4 )
	{
		if ( !s->isEmpty() ) s->append(",");

		s->append("p4x4");
	}

	if ( b.b8x8 )
	{
		if ( !s->isEmpty() ) s->append(",");

		s->append("b8x8");
	}

	if ( b.i8x8 )
	{
		if ( !s->isEmpty() ) s->append(",");

		s->append("i8x8");
	}

	if ( b.i4x4 )
	{
		if ( !s->isEmpty() ) s->append(",");

		s->append("i4x4");
	}
}
