/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2010-2011  Oleg Linkin
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
 **********************************************************************/

#include "separatetabwidget.h"
#include <algorithm>
#include <QStackedWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QToolButton>
#include <QToolBar>
#include <QMenu>
#include <QMouseEvent>
#include <QLayoutItem>
#include <QLayout>
#include <QShortcut>
#include <QStyle>
#include <QtDebug>
#include <interfaces/ihavetabs.h>
#include <interfaces/ihaverecoverabletabs.h>
#include "util/xpc/defaulthookproxy.h"
#include "util/sll/prelude.h"
#include "util/sll/qobjectrefcast.h"
#include "coreproxy.h"
#include "separatetabbar.h"
#include "xmlsettingsmanager.h"
#include "core.h"
#include "coreinstanceobject.h"
#include "coreplugin2manager.h"
#include "tabmanager.h"
#include "rootwindowsmanager.h"
#include "mainwindow.h"
#include "iconthemeengine.h"

namespace LC
{
	SeparateTabWidget::SeparateTabWidget (QWidget *parent)
	: QWidget (parent)
	, MainStackedWidget_ (new QStackedWidget)
	, MainTabBar_ (new SeparateTabBar)
	, AddTabButton_ (new QToolButton)
	, LeftToolBar_ (new QToolBar)
	, RightToolBar_ (new QToolBar)
	, DefaultTabAction_ (new QAction (QString (), this))
	, PreviousWidget_ (0)
	, CurrentToolBar_ (0)
	{
		XmlSettingsManager::Instance ()->RegisterObject ("SelectionBehavior",
			this, "handleSelectionBehavior");
		Core::Instance ().GetCoreInstanceObject ()->
				GetCorePluginManager ()->RegisterHookable (this);
		handleSelectionBehavior ();

		MainTabBar_->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Minimum);
		MainTabBar_->SetTabWidget (this);

		LeftToolBar_->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);
		RightToolBar_->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);

		LeftToolBar_->setMaximumHeight (25);
		RightToolBar_->setMaximumHeight (25);

		auto leftToolBarLayout = new QVBoxLayout;
		auto rightToolBarLayout = new QVBoxLayout;
		leftToolBarLayout->addWidget (LeftToolBar_);
		leftToolBarLayout->setContentsMargins (0, 0, 0, 0);
		rightToolBarLayout->addWidget (RightToolBar_);
		rightToolBarLayout->setContentsMargins (0, 0, 0, 0);

		MainTabBarLayout_ = new QHBoxLayout;
		MainTabBarLayout_->setContentsMargins (0, 0, 0, 0);
		MainTabBarLayout_->setSpacing (0);
		MainTabBarLayout_->addLayout (leftToolBarLayout);
		MainTabBarLayout_->addWidget (MainTabBar_);
		MainTabBarLayout_->addLayout (rightToolBarLayout);

		MainToolBarLayout_ = new QHBoxLayout;
		MainToolBarLayout_->setSpacing (0);
		MainToolBarLayout_->setContentsMargins (0, 0, 0, 0);

		MainToolBarLayout_->addSpacerItem (new QSpacerItem (1, 1,
				QSizePolicy::Minimum, QSizePolicy::Minimum));

		MainLayout_ = new QVBoxLayout (this);
		MainLayout_->setContentsMargins (0, 0, 0, 0);
		MainLayout_->setSpacing (0);
		MainLayout_->addLayout (MainToolBarLayout_);
		MainLayout_->addWidget (MainStackedWidget_);

		XmlSettingsManager::Instance ()->RegisterObject ("TabBarPosition",
				this, "handleTabBarPosition");
		handleTabBarPosition ();

		Init ();
		AddTabButtonInit ();
	}

	void SeparateTabWidget::SetWindow (MainWindow *window)
	{
		Window_ = window;

		MainTabBar_->SetWindow (window);
	}

	QObject* SeparateTabWidget::GetQObject ()
	{
		return this;
	}

	int SeparateTabWidget::WidgetCount () const
	{
		return MainStackedWidget_->count ();
	}

	QWidget* SeparateTabWidget::Widget (int index) const
	{
		return MainStackedWidget_->widget (index);
	}

	QList<QAction*> SeparateTabWidget::GetPermanentActions () const
	{
		return Util::Map (TabBarActions_, &QPointer<QAction>::data);
	}

	QString SeparateTabWidget::TabText (int index) const
	{
		return TabNames_.value (index);
	}

	void SeparateTabWidget::SetTabText (int index, const QString& text)
	{
		if (index < 0 || index >= WidgetCount ())
		{
			qWarning () << Q_FUNC_INFO
					<< "invalid index"
					<< index;
			return;
		}

		const auto proxy = std::make_shared<Util::DefaultHookProxy> ();
		emit hookTabSetText (proxy, index,
				Core::Instance ().GetRootWindowsManager ()->GetWindowIndex (Window_));
		if (proxy->IsCancelled ())
			return;

		auto escaped = text;
		escaped.replace ("&", "&&");
		MainTabBar_->setTabText (index, escaped);
		MainTabBar_->setTabToolTip (index, text);
		if (!text.isEmpty ())
			TabNames_ [index] = text;
	}

	QIcon SeparateTabWidget::TabIcon (int index) const
	{
		return MainTabBar_->tabIcon (index);
	}

	void SeparateTabWidget::SetTabIcon (int index, const QIcon& icon)
	{
		if (index < 0 ||
				index >= WidgetCount ())
		{
			qWarning () << Q_FUNC_INFO
					<< "invalid index"
					<< index;
			return;
		}

		MainTabBar_->setTabIcon (index, icon);
	}

	QString SeparateTabWidget::TabToolTip (int index) const
	{
		return MainTabBar_->tabToolTip (index);
	}

	void SeparateTabWidget::SetTabToolTip (int index, const QString& tip)
	{
		if (index < 0 ||
				index >= WidgetCount ())
		{
			qWarning () << Q_FUNC_INFO
				<< "invalid index"
				<< index;
			return;
		}

		MainTabBar_->setTabToolTip (index, tip);
	}

	QWidget* SeparateTabWidget::TabButton (int index, QTabBar::ButtonPosition positioin) const
	{
		return MainTabBar_->tabButton (index, positioin);
	}

	QTabBar::ButtonPosition SeparateTabWidget::GetCloseButtonPosition () const
	{
		return MainTabBar_->GetCloseButtonPosition ();
	}

	void SeparateTabWidget::SetTabClosable (int index, bool closable, QWidget *closeButton)
	{
		MainTabBar_->SetTabClosable (index, closable, closeButton);
	}

	void SeparateTabWidget::SetTabsClosable (bool closable)
	{
		MainTabBar_->setTabsClosable (closable);
		MainTabBar_->SetTabClosable (WidgetCount (), false);
	}

	void SeparateTabWidget::AddWidget2TabBarLayout (QTabBar::ButtonPosition pos,
			QWidget *w)
	{
		if (pos == QTabBar::LeftSide)
			LeftToolBar_->addWidget (w);
		else
			RightToolBar_->addWidget (w);
	}

	void SeparateTabWidget::AddAction2TabBarLayout (QTabBar::ButtonPosition pos,
			QAction *action)
	{
		if (pos == QTabBar::LeftSide)
			LeftToolBar_->addAction (action);
		else
			RightToolBar_->addAction (action);
	}

	void SeparateTabWidget::InsertAction2TabBarLayout (QTabBar::ButtonPosition pos,
			QAction *action, int index)
	{
		const auto tb = pos == QTabBar::LeftSide ? LeftToolBar_ : RightToolBar_;
		tb->insertAction (tb->actions ().value (index), action);
	}

	void SeparateTabWidget::RemoveActionFromTabBarLayout (QTabBar::ButtonPosition pos,
			QAction *action)
	{
		if (pos == QTabBar::LeftSide)
			LeftToolBar_->removeAction (action);
		else
			RightToolBar_->removeAction (action);
	}

	void SeparateTabWidget::AddAction2TabBar (QAction *act)
	{
		TabBarActions_ << act;
		connect (act,
				SIGNAL (destroyed (QObject*)),
				this,
				SLOT (handleActionDestroyed ()));
	}

	void SeparateTabWidget::InsertAction2TabBar (int index, QAction *act)
	{
		TabBarActions_.insert (index, act);
		connect (act,
				SIGNAL (destroyed (QObject*)),
				this,
				SLOT (handleActionDestroyed ()));
	}

	void SeparateTabWidget::InsertAction2TabBar (QAction *before, QAction *action)
	{
		int idx = TabBarActions_.indexOf (before);
		if (idx < 0)
			idx = TabBarActions_.size ();
		InsertAction2TabBar (idx, action);
	}

	int SeparateTabWidget::CurrentIndex () const
	{
		return MainTabBar_->currentIndex ();
	}

	QWidget* SeparateTabWidget::CurrentWidget () const
	{
		return MainStackedWidget_->currentWidget ();
	}

	QMenu* SeparateTabWidget::GetTabMenu (int index)
	{
		const auto widget = Widget (index);
		const auto itw = qobject_cast<ITabWidget*> (widget);
		if (!itw)
		{
			qWarning () << widget << "not an ITabWidget";
			return nullptr;
		}

		auto menu = new QMenu;

		if (XmlSettingsManager::Instance ()->property ("ShowPluginMenuInTabs").toBool ())
		{
			const bool asSub = XmlSettingsManager::Instance ()->property ("ShowPluginMenuInTabsAsSubmenu").toBool ();

			const auto& tabActions = itw->GetTabBarContextMenuActions ();

			const auto pluginMenu = asSub ? new QMenu (TabText (index), menu) : menu;
			for (const auto act : tabActions)
				pluginMenu->addAction (act);

			if (asSub)
				menu->addMenu (pluginMenu);

			if (tabActions.size ())
				menu->addSeparator ();
		}

		auto rootWM = Core::Instance ().GetRootWindowsManager ();
		const int windowIndex = rootWM->GetWindowIndex (Window_);

		auto moveMenu = menu->addMenu (tr ("Move tab to"));
		auto toNew = moveMenu->addAction (tr ("New window"),
				rootWM, SLOT (moveTabToNewWindow ()));
		toNew->setProperty ("TabIndex", index);
		toNew->setProperty ("FromWindowIndex", windowIndex);
		if (rootWM->GetWindowsCount () > 1)
		{
			moveMenu->addSeparator ();

			for (int i = 0; i < rootWM->GetWindowsCount (); ++i)
			{
				auto thatWin = rootWM->GetMainWindow (i);
				if (thatWin == Window_)
					continue;

				const auto& actTitle = tr ("To window %1 (%2)")
							.arg (i + 1)
							.arg (thatWin->windowTitle ());
				auto toExisting = moveMenu->addAction (actTitle,
						rootWM, SLOT (moveTabToExistingWindow ()));
				toExisting->setProperty ("TabIndex", index);
				toExisting->setProperty ("FromWindowIndex", windowIndex);
				toExisting->setProperty ("ToWindowIndex", i);
			}
		}

		const auto tabFeatures = itw->GetTabClassInfo ().Features_;
		const auto isOpenable = tabFeatures & TFOpenableByRequest && !(tabFeatures & TFSingle);
		if (const auto irt = qobject_cast<IRecoverableTab*> (widget);
			isOpenable && irt)
			if (const auto info = irt->GetTabSaveInfo ())
			{
				const auto cloneAct = menu->addAction (tr ("Clone tab"), this,
						[itw, widget = QPointer { widget }, info]
						{
							if (!widget)
								return;

							QList<QPair<QByteArray, QVariant>> props;
							for (const auto& name : widget->dynamicPropertyNames ())
								if (name.startsWith ("SessionData/"))
									props.append ({ name, widget->property (name) });

							auto& ihrt = qobject_ref_cast<IHaveRecoverableTabs> (itw->ParentMultiTabs ());
							ihrt.RecoverTabs ({ { info->Data_, props } });
						});
				cloneAct->setProperty ("ActionIcon", "tab-duplicate");
			}

		for (auto act : TabBarActions_)
		{
			if (!act)
			{
				qWarning () << Q_FUNC_INFO
						<< "detected null pointer";
				continue;
			}
			menu->addAction (act);
		}

		Util::DefaultHookProxy_ptr proxy (new Util::DefaultHookProxy);
		emit hookTabContextMenuFill (proxy, menu, index,
				Core::Instance ().GetRootWindowsManager ()->GetWindowIndex (Window_));

		return menu;
	}

	int SeparateTabWidget::IndexOf (QWidget *page) const
	{
		return MainStackedWidget_->indexOf (page);
	}

	int SeparateTabWidget::GetLastContextMenuTab () const
	{
		return LastContextMenuTab_;
	}

	void SeparateTabWidget::SetAddTabButtonContextMenu (QMenu *menu)
	{
		AddTabButtonContextMenu_ = menu;
		AddTabButton_->setMenu (AddTabButtonContextMenu_);
	}

	SeparateTabBar* SeparateTabWidget::TabBar () const
	{
		return MainTabBar_;
	}

	int SeparateTabWidget::AddTab (QWidget *page, const QString& text)
	{
		return AddTab (page, QIcon (), text);
	}

	int SeparateTabWidget::AddTab (QWidget *page,
			const QIcon& icon, const QString& text)
	{
		if (!page)
		{
			qWarning () << Q_FUNC_INFO
					<< "There is no widget to add to SeaprateTabWidget"
					<< page;
			return -1;
		}

		if (MainStackedWidget_->indexOf (page) != -1)
			return -1;

		MainStackedWidget_->addWidget (page);
		TabNames_ << text;
		const auto newIndex = MainTabBar_->
				insertTab (MainTabBar_->count () - 1, icon, text);

		MainTabBar_->setTabToolTip (newIndex, text);

		if (MainTabBar_->currentIndex () >= WidgetCount ())
			setCurrentTab (WidgetCount () - 1);

		return newIndex;
	}

	int SeparateTabWidget::InsertTab (int index, QWidget *page,
			const QString& text)
	{
		return InsertTab (index, page, QIcon (), text);
	}

	int SeparateTabWidget::InsertTab (int index, QWidget *page,
			const QIcon& icon, const QString& text)
	{
		const int newIndex = std::min (index, WidgetCount ());

		MainStackedWidget_->insertWidget (index, page);
		int idx = MainTabBar_->insertTab (newIndex, icon, text);
		MainTabBar_->setTabToolTip (idx, text);

		TabNames_.insert (index, text);

		if (MainTabBar_->currentIndex () >= WidgetCount ())
			setCurrentTab (WidgetCount () - 1);

		return idx;
	}

	void SeparateTabWidget::RemoveTab (int index)
	{
		if (index >= WidgetCount ())
		{
			qWarning () << Q_FUNC_INFO
					<< "invalid index"
					<< index;
			return;
		}

		Util::DefaultHookProxy_ptr proxy (new Util::DefaultHookProxy);
		const auto winId = Core::Instance ().GetRootWindowsManager ()->GetWindowIndex (Window_);
		emit hookTabIsRemoving (proxy, index, winId);
		if (proxy->IsCancelled ())
			return;

		const auto widget = Widget (index);

		if (widget == PreviousWidget_)
			PreviousWidget_ = 0;
		else if (widget == CurrentWidget_)
			CurrentWidget_ = 0;

		if (auto itw = qobject_cast<ITabWidget*> (widget))
			if (auto bar = itw->GetToolBar ())
				RemoveWidgetFromSeparateTabWidget (bar);

		if (!CurrentWidget_)
		{
			int nextIdx = -1;
			switch (MainTabBar_->selectionBehaviorOnRemove ())
			{
			case QTabBar::SelectLeftTab:
				nextIdx = index - 1;
				if (nextIdx == -1 && WidgetCount () > 1)
					nextIdx = 1;
				break;
			case QTabBar::SelectRightTab:
				nextIdx = index == WidgetCount () - 1 ?
						WidgetCount () - 2 :
						index + 1;
				break;
			default:
				nextIdx = IndexOf (PreviousWidget_);
				break;
			}

			if (nextIdx >= 0)
				setCurrentTab (nextIdx);
		}

		MainStackedWidget_->removeWidget (widget);
		MainTabBar_->removeTab (index);

		TabNames_.removeAt (index);

		widget->setParent (0);
	}

	void SeparateTabWidget::AddWidget2SeparateTabWidget (QWidget *widget)
	{
		widget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Minimum);
		SavedWidgetParents_ [widget] = widget->parentWidget ();
		MainToolBarLayout_->addWidget (widget);
	}

	void SeparateTabWidget::RemoveWidgetFromSeparateTabWidget (QWidget *widget)
	{
		MainToolBarLayout_->removeWidget (widget);
		widget->setParent (SavedWidgetParents_.take (widget));
		widget->hide ();
	}

	int SeparateTabWidget::TabAt (const QPoint& point)
	{
		return MainTabBar_->tabAt (point);
	}

	void SeparateTabWidget::MoveTab (int from, int to)
	{
		MainTabBar_->moveTab (from, to);
	}

	QWidget* SeparateTabWidget::GetPreviousWidget () const
	{
		return PreviousWidget_;
	}

	void SeparateTabWidget::resizeEvent (QResizeEvent *event)
	{
		QWidget::resizeEvent (event);
	}

	void SeparateTabWidget::mousePressEvent (QMouseEvent *event)
	{
		const bool mBack = event->button () == Qt::XButton1;
		const bool mForward = event->button () == Qt::XButton2;
		if (mBack || mForward)
		{
			auto rootWM = Core::Instance ().GetRootWindowsManager ();
			auto tm = rootWM->GetTabManager (Window_);
			mBack ? tm->rotateLeft () : tm->rotateRight ();
			event->accept ();
			return;
		}

		QWidget::mousePressEvent (event);
	}

	void SeparateTabWidget::Init ()
	{
		connect (MainTabBar_,
				SIGNAL (addDefaultTab ()),
				this,
				SLOT (handleAddDefaultTab ()));

		connect (DefaultTabAction_,
				SIGNAL (triggered ()),
				this,
				SLOT (handleAddDefaultTab ()));

		connect (MainTabBar_,
				SIGNAL (tabWasInserted (int)),
				this,
				SIGNAL (tabInserted (int)));
		connect (MainTabBar_,
				SIGNAL (tabWasRemoved (int)),
				this,
				SIGNAL (tabWasRemoved (int)));
		connect (MainTabBar_,
				SIGNAL (tabCloseRequested (int)),
				this,
				SIGNAL (tabCloseRequested (int)));
		connect (MainTabBar_,
				SIGNAL (tabMoved (int, int)),
				this,
				SLOT (handleTabMoved (int, int)));
		connect (MainTabBar_,
				SIGNAL (currentChanged (int)),
				this,
				SLOT (setCurrentIndex (int)));
		connect (MainTabBar_,
				SIGNAL (customContextMenuRequested (const QPoint&)),
				this,
				SLOT (handleContextMenuRequested (const QPoint&)));
		connect (MainTabBar_,
				SIGNAL (releasedMouseAfterMove (int)),
				this,
				SLOT (releaseMouseAfterMove (int)));
	}

	void SeparateTabWidget::AddTabButtonInit ()
	{
		DefaultTabAction_->setProperty ("ActionIcon", "list-add");

		AddTabButton_->setPopupMode (QToolButton::MenuButtonPopup);
		AddTabButton_->setToolButtonStyle (Qt::ToolButtonIconOnly);
		AddTabButton_->setDefaultAction (DefaultTabAction_);

		const auto iconSize = QApplication::style ()->pixelMetric (QStyle::PM_TabBarIconSize);
		AddTabButton_->setIconSize ({ iconSize, iconSize });
		AddTabButton_->setMaximumHeight (iconSize);

		AddTabButton_->setAutoRaise (true);

		auto cont = new QWidget;
		auto lay = new QHBoxLayout;
		lay->setContentsMargins (0, 0, 0, 0);
		lay->addWidget (AddTabButton_);
		cont->setLayout (lay);
		MainTabBar_->SetAddTabButton (cont);
	}

	void SeparateTabWidget::setCurrentIndex (int index)
	{
		if (index >= WidgetCount ())
			index = WidgetCount () - 1;

		auto rootWM = Core::Instance ().GetRootWindowsManager ();
		auto tabManager = rootWM->GetTabManager (Window_);

		MainStackedWidget_->setCurrentIndex (-1);
		if (CurrentToolBar_)
		{
			RemoveWidgetFromSeparateTabWidget (CurrentToolBar_);
			CurrentToolBar_ = nullptr;
		}

		MainTabBar_->setCurrentIndex (index);

		if (auto bar = tabManager->GetToolBar (index))
		{
			AddWidget2SeparateTabWidget (bar);
			bar->show ();
			CurrentToolBar_ = bar;
		}
		MainStackedWidget_->setCurrentIndex (index);

		CurrentIndex_ = index;
		if (CurrentWidget_ != Widget (index))
		{
			PreviousWidget_ = CurrentWidget_;
			CurrentWidget_ = Widget (index);
			emit currentChanged (index);
		}
	}

	void SeparateTabWidget::setCurrentTab (int tabIndex)
	{
		MainTabBar_->setCurrentIndex (tabIndex);
	}

	void SeparateTabWidget::setCurrentWidget (QWidget *widget)
	{
		if (!widget)
			return;

		int index = MainStackedWidget_->indexOf (widget);
		setCurrentTab (index);
	}

	void SeparateTabWidget::handleNewTabShortcutActivated ()
	{
		handleAddDefaultTab ();
	}

	void SeparateTabWidget::setPreviousTab ()
	{
		setCurrentWidget (PreviousWidget_);
	}

	void SeparateTabWidget::handleTabMoved (int from, int to)
	{
		if (from == MainTabBar_->count () - 1)
		{
			MainTabBar_->moveTab (to, from);
			return;
		}

		if (to == MainTabBar_->count () - 1)
			return;

		const auto& str = TabNames_.takeAt (from);
		TabNames_.insert (to, str);

		MainStackedWidget_->insertWidget (to, MainStackedWidget_->widget (from));

		MainTabBar_->SetInMove (true);
		setCurrentIndex (to);
		emit tabWasMoved (from, to);
	}

	void SeparateTabWidget::handleContextMenuRequested (const QPoint& point)
	{
		if (point.isNull ())
			return;

		QMenu *menu = new QMenu ("", MainTabBar_);
		int index = MainTabBar_->tabAt (point);

		if (index == -1)
			for (auto act : TabBarActions_)
			{
				if (!act)
				{
					qWarning () << Q_FUNC_INFO
							<< "detected null pointer";
					continue;
				}
				menu->addAction (act);
			}
		else if (index == MainTabBar_->count () - 1)
			menu->addActions (AddTabButtonContextMenu_->actions ());
		else
		{
			LastContextMenuTab_ = index;
			delete menu;
			menu = GetTabMenu (index);
		}

		if (menu)
			menu->exec (MainTabBar_->mapToGlobal (point));

		delete menu;
	}

	void SeparateTabWidget::handleActionDestroyed ()
	{
		for (const auto& act : TabBarActions_)
			if (!act || act == sender ())
				TabBarActions_.removeAll (act);
	}

	void SeparateTabWidget::releaseMouseAfterMove (int index)
	{
		Util::DefaultHookProxy_ptr proxy (new Util::DefaultHookProxy);
		emit hookTabFinishedMoving (proxy, index,
				Core::Instance ().GetRootWindowsManager ()->GetWindowIndex (Window_));
	}

	void SeparateTabWidget::handleTabBarPosition ()
	{
		MainLayout_->removeItem (MainTabBarLayout_);

		const auto& settingVal = XmlSettingsManager::Instance ()->property ("TabBarPosition").toString ();
		const bool isBottom = settingVal == "Bottom";
		if (isBottom)
			MainLayout_->addLayout (MainTabBarLayout_);
		else
			MainLayout_->insertLayout (0, MainTabBarLayout_);

		MainTabBar_->setShape (isBottom ? QTabBar::RoundedSouth : QTabBar::RoundedNorth);
	}

	void SeparateTabWidget::handleSelectionBehavior ()
	{
		const QString& selection = XmlSettingsManager::Instance ()->
				property ("SelectionBehavior").toString ();
		if (selection == "PreviousActive")
			MainTabBar_->setSelectionBehaviorOnRemove (QTabBar::SelectPreviousTab);
		else if (selection == "NextIndex")
			MainTabBar_->setSelectionBehaviorOnRemove (QTabBar::SelectRightTab);
		else if (selection == "PreviousIndex")
			MainTabBar_->setSelectionBehaviorOnRemove (QTabBar::SelectLeftTab);
	}

	void SeparateTabWidget::handleAddDefaultTab ()
	{
		const auto& combined = XmlSettingsManager::Instance ()->
				property ("DefaultNewTab").toString ().toLatin1 ();
		if (combined != "contextdependent")
		{
			const auto& parts = combined.split ('|');
			if (parts.size () != 2)
				qWarning () << Q_FUNC_INFO
						<< "incorrect split"
						<< parts
						<< combined;
			else
			{
				const QByteArray& newTabId = parts.at (0);
				const QByteArray& tabClass = parts.at (1);
				QObject *plugin = Core::Instance ()
						.GetPluginManager ()->GetPluginByID (newTabId);
				IHaveTabs *iht = qobject_cast<IHaveTabs*> (plugin);
				if (!iht)
					qWarning () << Q_FUNC_INFO
							<< "plugin with id"
							<< newTabId
							<< "is not a IMultiTabs";
				else
				{
					iht->TabOpenRequested (tabClass);
					return;
				}
			}
		}

		IHaveTabs *highestIHT = 0;
		QByteArray highestTabClass;
		int highestPriority = 0;
		for (auto iht : Core::Instance ().GetPluginManager ()->GetAllCastableTo<IHaveTabs*> ())
			for (const auto& info : iht->GetTabClasses ())
			{
				if (!(info.Features_ & TFOpenableByRequest))
					continue;

				if (info.Priority_ <= highestPriority)
					continue;

				highestIHT = iht;
				highestTabClass = info.TabClass_;
				highestPriority = info.Priority_;
			}

		const auto imtw = qobject_cast<ITabWidget*> (CurrentWidget ());
		const int delta = 15;
		if (imtw && imtw->GetTabClassInfo ().Priority_ + delta > highestPriority)
		{
			highestIHT = qobject_cast<IHaveTabs*> (imtw->ParentMultiTabs ());
			highestTabClass = imtw->GetTabClassInfo ().TabClass_;
		}

		if (!highestIHT)
		{
			qWarning () << "no IHT detected";
			return;
		}

		highestIHT->TabOpenRequested (highestTabClass);
	}
}
