/*
 * chatsplitter.cpp - QSplitter replacement that masquerades it
 * Copyright (C) 2007  Michail Pishchagin
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include "chatsplitter.h"

#include <QSplitter>
#include <QVBoxLayout>
#include <QChildEvent>

#include "psioptions.h"

/**
 * Handy widget that masquerades itself as QSplitter, and could work
 * in both QSplitter mode, and QSplitter-less mode.
 */
ChatSplitter::ChatSplitter(QWidget* parent)
	: QWidget(parent)
	, splitterEnabled_(true)
	, splitter_(0)
	, layout_(0)
{
	connect(PsiOptions::instance(), SIGNAL(optionChanged(const QString&)), SLOT(optionsChanged()));
	optionsChanged();

	if (!layout_)
		updateLayout();
}

/**
 * Dummy function to fool Qt Designer-generated forms.
 */
void ChatSplitter::setOrientation(Qt::Orientation orientation)
{
	Q_ASSERT(orientation == Qt::Vertical);
	Q_UNUSED(orientation);
}

/**
 * Adds the given \a widget to the splitter's layout after all the
 * other items. Don't call this function if widget is already added
 * to the splitter's layout.
 */
void ChatSplitter::addWidget(QWidget* widget)
{
	Q_ASSERT(!children_.contains(widget));
	children_ << widget;
	connect(widget, SIGNAL(destroyed(QObject*)), SLOT(childDestroyed(QObject*)));
	updateChildLayout(widget);
}

/**
 * If splitter mode is enabled, the \a list is passed to the
 * actual splitter. Has no effect otherwise.
 */
void ChatSplitter::setSizes(const QList<int>& list)
{
	if (splitter_)
		splitter_->setSizes(list);
}

QList<int> ChatSplitter::sizes()
{
	QList<int> list;
	if(splitter_)
		list = splitter_->sizes();

	return list;
}

/**
 * Moves \a child either to the real QSplitter, or adds it to the
 * private layout.
 */
void ChatSplitter::updateChildLayout(QWidget* child)
{
	if (splitterEnabled() && splitter_) {
		splitter_->addWidget(child);
	}
	else {
		layout_->addWidget(child);
	}
}

/**
 * Removes destroyed widget from the splitter's child list.
 */
void ChatSplitter::childDestroyed(QObject* obj)
{
	Q_ASSERT(obj->isWidgetType());
	children_.removeAll(static_cast<QWidget*>(obj));
}

/**
 * If \a enable is true, the true QSplitter gets enabled, otherwise
 * all widgets are managed by QLayout.
 */
void ChatSplitter::setSplitterEnabled(bool enable)
{
	if (splitterEnabled_ == enable)
		return;

	splitterEnabled_ = enable;
	updateLayout();
}

/**
 * Invalidates layout and moves all child widgets to the proper position.
 */
void ChatSplitter::updateLayout()
{
	foreach(QWidget* child, children_)
		child->setParent(this);

	delete splitter_;
	delete layout_;
	splitter_ = new QSplitter(this);
	layout_ = new QVBoxLayout(this);
	layout_->setMargin(0);
	layout_->addWidget(splitter_);
	splitter_->setOrientation(Qt::Vertical);
	splitter_->setVisible(splitterEnabled());

	foreach(QWidget* child, children_)
		updateChildLayout(child);

	connect(splitter_, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterMoved(int,int)));
}

/**
 * Updates layout according to current options.
 * FIXME: When PsiOptions::instance()->getOption("options.ui.chat.use-expanding-line-edit").toBool() finally makes it to PsiOptions, make this slot
 *        private.
 */
void ChatSplitter::optionsChanged()
{
	setSplitterEnabled(!PsiOptions::instance()->getOption("options.ui.chat.use-expanding-line-edit").toBool());
}
