/* -*- mode: c++; tab-width: 4; c-basic-offset: 4 -*- */
/*
 * Copyright (C) 2006-2007	Andre Beckedorf
 * 					 		<evilJazz _AT_ katastrophos _DOT_ net>
 *
 * Copyright (C) 2005 Atmark <atmarkat _AT_ msn _DOT_ com>
 *                    AGAWA Koji <i _AT_ atty _DOT_ jp>
 *
 * 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 program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#include <qapplication.h>

#ifdef QTOPIA
#include <qpe/qpemenubar.h>
#include <qpe/qpetoolbar.h>
#include <qpe/qcopenvelope_qws.h>
#include <qpe/resource.h>
#include <qpe/config.h>
#include <qpe/global.h>
#else
#include <qmenubar.h>
#include <qtoolbar.h>
#include <resource.h>
#include <config.h>
// for Qtopia we are using the QPE variants for toolbar and menubar 
// to enable special features like the menu key etc.
// Define aliases to avoid ifdefs...
#define QPEMenuBar QMenuBar
#define QPEToolBar QToolBar
#endif

#include <qmessagebox.h>
#include <qpopupmenu.h>
#include <qlayout.h>
#include <qdir.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qtextstream.h>
#include <qlistview.h>
#include <qheader.h>
#include <qlineedit.h>
#include <qcursor.h>
#include <qwidgetstack.h>
#include <qaction.h>
#include <qvbox.h>
#include <qsignalmapper.h>
#include <qtextcodec.h>
#include <qstringlist.h>
#include <qregexp.h>

#include "textviewdialog.h"
#include "quasar.h"
#include "mplayer.h"
#include "operationpanel.h"
#include "toolpanel.h"
#include "videoplaybackwindow.h"
#include "playinfo.h"
#include "configuration.h"
#include "configurationdialog.h"
#include "media.h"
#include "qtkfiledialog.h"
#include "qinputdialog.h"
#include "qprogressdialog.h"
#include "qsplitter.h"
#include "aboutdialog.h"
#include "action.h"
#include "system_volume.h"
#include "textencoding.h"
#ifdef QTOPIA
#include "batteryplus.h"
#endif
#include "playlist.h"
#include "playlistoverview.h"
#include "playlisttoolpanel.h"
#include "skin.h"
#include "debug.h"

Configuration Quasar::config;

Quasar::Quasar()
	:	keyEventCount_(0)
{
	DMEMSTAT();

#ifdef QTOPIA
	QPEStyle *style = new QuasarStyle();
	qApp->setStyle(style);
#endif
	
	setCaption(APPNAME);

	// configuration
	DPRINTF("Initialize Configuration class...");
	bool isValidConfig = config.isValidConfig();
	if (isValidConfig)
		config.read();
	DPRINTF("Done");

#ifdef QTOPIA	
	setRemoteCon();
#endif

	DMEMSTAT();
	
	// mplayer
	DPRINTF("Initialize MPlayer class...");
	mplayer_ = new MPlayer();
	connect(mplayer_, SIGNAL(eof()), this, SLOT(next()));
	connect(mplayer_, SIGNAL(quit()), this, SLOT(stop()));
	connect(mplayer_, SIGNAL(currentPlayTime(int)), this, SLOT(mplayerCurrentPlayTime(int)));
	connect(mplayer_, SIGNAL(errorMessage(QString)), this, SLOT(mplayerErrorMessage(QString)));
	DPRINTF("Done");

	DMEMSTAT();
	
	// skin
	DPRINTF("Initialize SkinManager class...");
	skinManager_ = new SkinManager(config.getSkinPath(), this);
	if (!skinManager_->load(config.skin1)) {
		QMessageBox::warning(this, tr("Warning"), tr("Couldn't load skin."));
		if (!skinManager_->load("default")) {
			QMessageBox::warning(this, tr("Fatal Error"), tr("Couldn't load default skin."));
			exit(1);
		}
	}
	
	// TODO: get rid of hardcoding...
#ifdef QTOPIA
	if (qApp->desktop()->width() == 640 || qApp->desktop()->width() == 320) {
		skinManager_->setStyle(SkinManager::Landscape);
		DPRINTF("  Initial style is Landscape");
	} else {
		skinManager_->setStyle(SkinManager::Portrait);
		DPRINTF("  Initial style is Portrait");
	}
#else
	skinManager_->setStyle(SkinManager::Landscape);	
#endif
	DPRINTF("Done");

	DMEMSTAT();

	QWidget *centralWidget = new QVBox(this);

	// Toggle Widget(Playlist/PlayInfo)
	DPRINTF("Initialize widget stack class...");
	
	widgetStack_ = new QWidgetStack(centralWidget);
	widgetStack_->setFrameStyle(QFrame::NoFrame);
	widgetStack_->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
	
	DPRINTF("Done");
	DMEMSTAT();

	DPRINTF("Initialize playlist container...");

	playListContainer_ = new QVBox(widgetStack_);
	playListContainer_->setFrameStyle(QFrame::NoFrame);
	widgetStack_->addWidget(playListContainer_, PlayListWidget);

	DPRINTF("Done");
	DMEMSTAT();
	
	DPRINTF("Initialize Playlist tool panel class...");
	playListToolPanel_ = new PlayListToolPanel(skinManager_, playListContainer_);
	// signals are connected further down...

	DPRINTF("Done");
	DMEMSTAT();
	
	playlistStack_ = new QWidgetStack(playListContainer_);
	playlistStack_->setFrameStyle(QFrame::NoFrame);
	playlistStack_->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
	
	DPRINTF("Initialize splitter container...");
	
	splitterContainer_ = new QSplitter(playlistStack_);
	splitterContainer_->setFrameStyle(QFrame::NoFrame);
	splitterContainer_->setOpaqueResize(true);
	splitterContainer_->setOrientation(QSplitter::Vertical);
	
	playlistStack_->addWidget(splitterContainer_, 0);
	playlistStack_->raiseWidget(splitterContainer_);
	
	DPRINTF("Done");
	DMEMSTAT();

	DPRINTF("Initialize Playlist class...");
	
	playList_ = new PlayList(config.getConfigPath() + QString(MEDIADBNAME));
	connect(playList_, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(stop_play()));
	connect(playList_, SIGNAL(selectionChanged()), this, SLOT(scheduleUpdateButtonAndMenuState()));
	
	DPRINTF("Done");
	DMEMSTAT();
	
	DPRINTF("Initialize PlaylistManager class...");
	
	playListManager_ = new PlayListManager(playList_, playlistStack_, config, this);
	connect(playListManager_, SIGNAL(switchingModeTo(PlayListManager::Mode)), this, SLOT(playlistManagerSwitchingModeTo(PlayListManager::Mode)));
	connect(playListManager_, SIGNAL(switchedModeTo(PlayListManager::Mode)), this, SLOT(playlistManagerSwitchedModeTo(PlayListManager::Mode)));
	connect(playListManager_, SIGNAL(playlistFileNameChanged()), this, SLOT(playlistManagerPlayListFileNameChanged()));
	connect(playListManager_, SIGNAL(playlistLoaded()), this, SLOT(playlistManagerPlayListFileNameChanged()));
	connect(playListManager_, SIGNAL(clipboardChanged()), this, SLOT(updateButtonAndMenuState()));
	connect(playListManager_, SIGNAL(selectionChanged()), this, SLOT(scheduleUpdateButtonAndMenuState()));
	
	connect(playListToolPanel_, SIGNAL(modeChanged(PlayListManager::Mode)), this, SLOT(playlistToolPanelModeChanged(PlayListManager::Mode)));
	connect(playListToolPanel_, SIGNAL(inputModeChanged(PlayList::InputMode)), this, SLOT(setInputMode(PlayList::InputMode)));
	connect(playListToolPanel_, SIGNAL(copyClicked()), playListManager_, SLOT(copySelectionFromPlayList()));
	connect(playListToolPanel_, SIGNAL(cutClicked()), playListManager_, SLOT(cutSelectionFromPlayList()));
	connect(playListToolPanel_, SIGNAL(pasteClicked()), playListManager_, SLOT(pasteIntoPlayList()));
	connect(playListToolPanel_, SIGNAL(deleteClicked()), playListManager_, SLOT(removeFileFromPlayList()));
	connect(playListToolPanel_, SIGNAL(resetFilterAndSortingClicked()), this, SLOT(resetFilterAndSorting()));
	connect(playListToolPanel_, SIGNAL(copyToOTGClicked()), playListManager_, SLOT(copyToOnTheGoPlayList()));
	connect(playListToolPanel_, SIGNAL(openPlaylistClicked()), playListManager_, SLOT(execDialogOpenPlayList()));
	connect(playListToolPanel_, SIGNAL(savePlaylistClicked()), playListManager_, SLOT(savePlayList()));
		
	DPRINTF("Done");
	DMEMSTAT();
	
	DPRINTF("Initialize Playlist overview class...");
	playListOverview_ = new PlayListOverview(playList_);
	connect(playListOverview_, SIGNAL(focusOutLeft()), this, SLOT(playlistOverviewFocusOutLeft()));
	connect(playListOverview_, SIGNAL(focusOutRight()), this, SLOT(playlistOverviewFocusOutRight()));

	DPRINTF("Done");
	DMEMSTAT();

	
	DPRINTF("Setting up playlist layout...");
	playListOverview_->reparent(splitterContainer_, QPoint(0, 0), true);
	playList_->reparent(splitterContainer_, QPoint(0, 0), true);

	// hide playlist overview initially, so setOverviewVisibility works correctly...
	playListOverview_->hide();
	playList_->setFocus();

	if (skinManager_->style() == SkinManager::Landscape)
		playList_->loadColumnOrder(config.getConfigName(), "PlayListLandscape");
	else
		playList_->loadColumnOrder(config.getConfigName(), "PlayListPortrait");

	changeOrientation(skinManager_->style() == SkinManager::Landscape, false, false);
	
	DPRINTF("Done");
	DMEMSTAT();

	DPRINTF("Initialize PlayInfo class...");
	// PlayInfo
	playInfo_ = new PlayInfo(config, widgetStack_);
	widgetStack_->addWidget(playInfo_, InfoWidget);

	DPRINTF("Done");
	DMEMSTAT();

	// operation panel
	DPRINTF("Initialize OperationPanel class...");
	operationPanel_ = new OperationPanel(skinManager_, centralWidget);
	connect(operationPanel_, SIGNAL(playClicked()), this, SLOT(play_pause()));
	connect(operationPanel_, SIGNAL(stopClicked()), this, SLOT(stop()));
	connect(operationPanel_, SIGNAL(nextClicked()), this, SLOT(next()));
	connect(operationPanel_, SIGNAL(previousClicked()), this, SLOT(previous()));
	connect(this, SIGNAL(playbackStarted()), operationPanel_, SLOT(showPlaybackWidgets()));
	connect(this, SIGNAL(playbackStopped()), operationPanel_, SLOT(hidePlaybackWidgets()));
	connect(operationPanel_, SIGNAL(seek(int)), this, SLOT(setAbsoluteSeconds(int)));

	DPRINTF("Done");
	DMEMSTAT();

	DPRINTF("Initialize ToolPanel class...");
	toolPanel_ = new ToolPanel(skinManager_, centralWidget);
	connect(playList_, SIGNAL(viewUpdated()), this, SLOT(playlistViewUpdated())); // required here! Will access toolPanel_
	connect(toolPanel_, SIGNAL(playOrderChanged(int)), this, SLOT(setPlayOrder(int)));
	connect(toolPanel_, SIGNAL(overviewVisibilityChanged(bool)), this, SLOT(setOverviewVisibility(bool)));
	connect(toolPanel_, SIGNAL(viewPlayListActivated()), this, SLOT(switchToLastActivePlayList()));
	connect(toolPanel_, SIGNAL(viewPlayInfoActivated()), this, SLOT(switchToInfoWidget()));
	
	connect(playListManager_, SIGNAL(showMessage(const QString &, int)), toolPanel_, SLOT(setStatusText(const QString &, int)));

	DPRINTF("Done");
	DMEMSTAT();
	
	// menu bar
	DPRINTF("Initialize Menus...");
	toolBar_ = new QPEToolBar(this);
	toolBar_->setHorizontalStretchable(true);
	setToolBarsMovable(false);

	subBar_ = new QPEToolBar(this);

	menuBar_ = new QPEMenuBar(toolBar_);
	menuBar_->setMargin(0);
	menuBar_->setFrameStyle(QFrame::NoFrame);
	
	setupMenu();

	connect(playList_, SIGNAL(viewSorted()), this, SLOT(playlistViewSorted()));

	DPRINTF("Done");
	DMEMSTAT();

	// player window
	DPRINTF("Initialize PlayerWindow class...");
	videoPlaybackWindow_ = new VideoPlaybackWindow(this);
	videoPlaybackWindow_->hide();
	connect(videoPlaybackWindow_, SIGNAL(seekAbsolutePercentage(int)), mplayer_, SLOT(seekAbsolutePercentage(int)));
	connect(videoPlaybackWindow_, SIGNAL(seekSliderMoved(int)), mplayer_, SLOT(osdShowProgressBar(int)));
	connect(videoPlaybackWindow_, SIGNAL(seekStart()), mplayer_, SLOT(enableTemporaryOSD()));
	connect(videoPlaybackWindow_, SIGNAL(seekEnd()), mplayer_, SLOT(disableTemporaryOSD()));
	DPRINTF("Done");
	
	DMEMSTAT();

	setupActions();
	
	DMEMSTAT();
	
	// set current display info mode...
	DPRINTF("Setting Playlist font...");
	setPlayListFont(config.infoMode);
	
	DPRINTF("Setting Playlist input mode...");
	setInputMode(config.inputMode);
	
	isFullScreen_ = false;
	
	// Set Repeat Mode
	DPRINTF("Setting play order...");
	setPlayOrder(config.playOrder);

	DPRINTF("Setting central widget...");
	setCentralWidget(centralWidget);

	// raise play list widget...
	DPRINTF("Raising playlist widget...");
	widgetStack_->raiseWidget(PlayListWidget);
	
	DPRINTF("Setting view on tool panel...");
	toolPanel_->setView(ToolPanel::PlayList);
	
	// BatteryPlus
	DPRINTF("Initializing BatteryPlus singleton...");
#ifdef QTOPIA	
	BatteryPlus::singleton();
#endif

	DPRINTF("Checking for valid config file...");
	if (!isValidConfig)
	{
		QMessageBox::warning(centralWidget, APPNAME,
							 tr("Invalid or non existing settings file.\nUsing the default settings."),
							 QMessageBox::Ok, QMessageBox::NoButton);
	}

	DPRINTF("Installing event filter...");
	qApp->installEventFilter(this);

	// allows us to catch cancel/escape to avoid quitting the player by accident
	DPRINTF("Reparenting and setting WFlags...");
#ifdef QTOPIA
	reparent(0, WStyle_Customize | WStyle_NoBorder, QPoint(0, 0));
#endif

	DPRINTF("Initialize %s finished.", APPNAME);
	DMEMSTAT();

	loadWidgetPosition(this, config.getConfigName(), "QuasarMainWindow");
	
	// we can't use polish, because we need to show the window and
	// some additional dialogs...
	QTimer::singleShot(1, this, SLOT(init()));
}

Quasar::~Quasar()
{
	delete mplayer_;
}

void Quasar::init()
{
	// set overview visibility here since we need to be sure
	// the splitter container is correctly sized for the 
	// setting of the splitter position to work correctly.
	setOverviewVisibility(config.isOverviewVisible);

	DPRINTF("Determining mplayer binary features...");
	MPlayer mplayer;
	mplayer.checkFeatures();
	
	DPRINTF("Scanning cover art directory...");
	playInfo_->setCoverArtDirectory(config.coverArtDirectory);

	DPRINTF("Done");
	DMEMSTAT();	

	setActiveView(ViewOpenedPlaylist);
	
	DPRINTF("Loading last playlist...");
	if (!config.lastPlaylistFile.isEmpty())
	{
		playListManager_->clearPlayList();
		playListManager_->readPlayList(config.lastPlaylistFile);
	}
	else
	{
		playListManager_->newPlayList();
	}

	DPRINTF("Done");
	DMEMSTAT();	
}

/*! メニューなどに無いアクションの設定をします。 */
void Quasar::setupActions()
{
	struct SeekAction {
		const char *action;
		int seconds;
	};

	static SeekAction actions[] = {
		{ "Playback/Seek Ahead By 1 Second", 1 },
		{ "Playback/Seek Ahead By 5 Seconds", 5 },
		{ "Playback/Seek Ahead By 10 Seconds", 10 },
		{ "Playback/Seek Ahead By 20 Seconds", 20 },
		{ "Playback/Seek Ahead By 30 Seconds", 30 },
		{ "Playback/Seek Ahead By 1 Minute", 60 * 1 },
		{ "Playback/Seek Ahead By 2 Minutes", 60 * 2 },
		{ "Playback/Seek Ahead By 5 Minutes", 60 * 5 },
		{ "Playback/Seek Ahead By 10 Minutes", 60 * 10 },
		{ "Playback/Seek Back By 1 Second", -1 },
		{ "Playback/Seek Back By 5 Seconds", -5 },
		{ "Playback/Seek Back By 10 Seconds", -10 },
		{ "Playback/Seek Back By 20 Seconds", -20 },
		{ "Playback/Seek Back By 30 Seconds", -30 },
		{ "Playback/Seek Back By 1 Minute", -60 * 1 },
		{ "Playback/Seek Back By 2 Minutes", -60 * 2 },
		{ "Playback/Seek Back By 5 Minutes", -60 * 5 },
		{ "Playback/Seek Back By 10 Minutes", -60 * 10 },
		{ 0, 0 }
	};

	QSignalMapper *sm = new QSignalMapper(this);
	connect(sm, SIGNAL(mapped(int)), mplayer_, SLOT(seekRelativeSeconds(int)));

	for (SeekAction *p = actions; p->action != NULL; ++p) {
		QAction *a = new QAction(this);
		a->setAccel(g_ActionManager.actionByName(p->action).accel());
		connect(a, SIGNAL(activated()), sm, SLOT(map()));
		sm->setMapping(a, p->seconds);
	}

	// volume
	sm = new QSignalMapper(this);
	connect(sm, SIGNAL(mapped(int)), this, SLOT(setVolumeRelative(int)));

	QAction *a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Volume Up").accel());
	connect(a, SIGNAL(activated()), sm, SLOT(map()));
	sm->setMapping(a, 5);

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Volume Down").accel());
	connect(a, SIGNAL(activated()), sm, SLOT(map()));
	sm->setMapping(a, -5);

	// misc
#ifdef QTOPIA
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Turn On LCD").accel());
	connect(a, SIGNAL(activated()), this, SLOT(turnOnLCD()));
#endif
	
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Toggle OSD").accel());
	connect(a, SIGNAL(activated()), mplayer_, SLOT(toggleOSD()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playlist/Focus Filterbox").accel());
	connect(a, SIGNAL(activated()), filterEditBox_, SLOT(setFocus()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playlist/Reset Filter And Focus Filterbox").accel());
	connect(a, SIGNAL(activated()), this, SLOT(resetFilterAndFocusFilterEditBox()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playlist/Reset Filter").accel());
	connect(a, SIGNAL(activated()), this, SLOT(resetFilter()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playlist/Play Selected Song").accel());
	connect(a, SIGNAL(activated()), this, SLOT(stop_play()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Toggle Play Order").accel());
	connect(a, SIGNAL(activated()), this, SLOT(togglePlayOrder()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Toggle Random Play Order").accel());
	connect(a, SIGNAL(activated()), this, SLOT(toggleRandomPlayOrder()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Toggle PlayInfo").accel());
	connect(a, SIGNAL(activated()), this, SLOT(toggleInfoWidget()));
	
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Display/Increase Size").accel());
	connect(a, SIGNAL(activated()), this, SLOT(incDisplaySize()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Display/Decrease Size").accel());
	connect(a, SIGNAL(activated()), this, SLOT(decDisplaySize()));


	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Display/Quickswitch Skin 1").accel());
	connect(a, SIGNAL(activated()), this, SLOT(loadPrimarySkin()));
	
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Display/Quickswitch Skin 2").accel());
	connect(a, SIGNAL(activated()), this, SLOT(loadSecondarySkin()));
	
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playlist/Focus Playlist").accel());
	connect(a, SIGNAL(activated()), playList_, SLOT(setFocus()));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Overview/Focus Overview").accel());
	connect(a, SIGNAL(activated()), this, SLOT(setFocusPlayListOverview()));
	
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Display/Toggle Overview Visibility").accel());
	connect(a, SIGNAL(activated()), this, SLOT(toggleOverviewVisibility()));
	
	/*
	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Toggle PlayInfo").accel());
	connect(a, SIGNAL(activated()), this, SLOT(toggleInfoWidget()));
	*/
	
#ifdef QTOPIA
	// brightness
	QSignalMapper *smb = new QSignalMapper(this);
	connect(smb, SIGNAL(mapped(int)), mplayer_, SLOT(setBrightness(int)));

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Decrease Brightness").accel());
	connect(a, SIGNAL(activated()), smb, SLOT(map()));
	smb->setMapping(a, -10);

	a = new QAction(this);
	a->setAccel(g_ActionManager.actionByName("Playback/Increase Brightness").accel());
	connect(a, SIGNAL(activated()), smb, SLOT(map()));
	smb->setMapping(a, 10);
#endif
}

//! アプリケーション全体のイベントを監視するイベントフィルタです。
/*!
  ホットキーを処理するために使われています。
*/
bool Quasar::eventFilter(QObject *object, QEvent *event)
{
	if (object == filterEditBox_ &&
		((event->type() == QEvent::FocusIn) || (event->type() == QEvent::FocusOut)))
	{
		const SkinModeInformation *modeInfo = skinManager_->getInfo(config.infoMode);
	
		QPalette palette = QApplication::palette();
		
		if (event->type() == QEvent::FocusIn)
		{
			setActiveView(Quasar::ViewLastActivePlaylist);
			
			if (modeInfo->filterBoxBackgroundColorFocused().isUsed())
			{
				palette.setColor(QColorGroup::Base, modeInfo->filterBoxBackgroundColorFocused());
			}

			if (modeInfo->filterBoxFontColorFocused().isUsed())
			{
				palette.setColor(QColorGroup::Text, modeInfo->filterBoxFontColorFocused());
				palette.setColor(QColorGroup::Foreground, modeInfo->filterBoxFontColorFocused());
			}
		}
		else if (event->type() == QEvent::FocusOut)
		{
			if (modeInfo->filterBoxBackgroundColor().isUsed())
			{
				palette.setColor(QColorGroup::Base, modeInfo->filterBoxBackgroundColor());
			}

			if (modeInfo->filterBoxFont().fontColor.isUsed())
			{
				palette.setColor(QColorGroup::Text, modeInfo->filterBoxFont().fontColor);
				palette.setColor(QColorGroup::Foreground, modeInfo->filterBoxFont().fontColor);
			}
		}

		filterEditBox_->setPalette(palette);
	}	

	if (event->type() == QEvent::KeyPress) 
	{
		if (!qApp->activeWindow()->isA("Quasar") &&
			!qApp->activeWindow()->isA("VideoPlaybackWindow"))			
			return QMainWindow::eventFilter(object, event);

		QKeyEvent *e = static_cast<QKeyEvent *>(event);
		int key = e->key();
		//DPRINTF("KeyPress: %d", key);

		// override special keys when the playlist overview is focused.
		if (playListOverview_->hasFocus() && (key == Qt::Key_Right || key == Qt::Key_Left || key == Qt::Key_Space))
			return QMainWindow::eventFilter(object, event);
		
		if (qApp->focusWidget() == filterEditBox_)
		{
			if (key == Qt::Key_Down || key == Qt::Key_Up)
			{
				if (playListManager_->isDynamicPlaylistEditorActive())
				{
					playlistStack_->visibleWidget()->setFocus();
					QMainWindow::eventFilter(playlistStack_->visibleWidget(), event);
				}
				else
				{
					if (playListOverview_->isVisible())
					{
						playListOverview_->setFocus();
						QMainWindow::eventFilter(playListOverview_, event);
					}
					else
					{
						playList_->setFocus();
						QMainWindow::eventFilter(playList_, event);
					}
				}
			}
			else
				return QMainWindow::eventFilter(object, event);
		}
			
		if (e->state() & ShiftButton)
			key |= SHIFT;
		if (e->state() & ControlButton)
			key |= CTRL;
		if (e->state() & AltButton)
			key |= ALT;

		Configuration::HotKeyContext context = Configuration::HOTKEY_CONTEXT_GLOBAL;

		Configuration::HotKeyMap::Iterator it(config.hotKeyMap[context].find(key));
		// グローバルコンテキストに登録されていないキーのみ他のコンテキストを調査する
		if (it == config.hotKeyMap[context].end()) {
			if (videoPlaybackWindow_->isVisible())
				context = Configuration::HOTKEY_CONTEXT_VIDEO;
			else if (playInfo_->isVisible())
				context = Configuration::HOTKEY_CONTEXT_AUDIO;
			else if (playList_->hasFocus() || playListOverview_->hasFocus())
				context = Configuration::HOTKEY_CONTEXT_PLAYLIST;
		}

		it = config.hotKeyMap[context].find(key);
		if (it != config.hotKeyMap[context].end()) {
			QKeyEvent a(QEvent::Accel, it.data(), 0, 0);
			a.ignore();
			// topLevelWidget() or qApp ?
			QApplication::sendEvent(topLevelWidget(), &a);

			e->accept();
			return true;
		}
	}

	if (event->type() == QEvent::Accel)
	{
		QKeyEvent *e = static_cast<QKeyEvent *>(event);

		int key = e->key();	
		if (key == 4096)
		{
			e->ignore();
			return true;
		}		
	}

	return QMainWindow::eventFilter(object, event);
}

void Quasar::play_pause()
{
	play_pause(false);
}

void Quasar::play_pause(bool forcePlayNewFile)
{
	// Toggle play/pause
	if (mplayer_->isRunning() && !forcePlayNewFile)
	{
		if (mplayer_->isPaused())
		{
			mplayer_->pause();
			playList_->setActiveItemPaused(false);
			operationPanel_->setPlayPause(false);

/*	TODO: Enable IPC via QCOP/DCOP/DBUS */
#ifdef QTOPIA
			if (config.qcopBroadcastingEnabled)
				QCopEnvelope("QPE/MediaPlayer", "unpaused()");
#endif
		}
		else
		{
			mplayer_->pause();
			playList_->setActiveItemPaused(true);
			operationPanel_->setPlayPause(true);

/*	TODO: Enable IPC via QCOP/DCOP/DBUS */
#ifdef QTOPIA
			if (config.qcopBroadcastingEnabled)
				QCopEnvelope("QPE/MediaPlayer", "paused()");		
#endif
		}
	}
	// Start mplayer
	else if (playList_->childCount() > 0 && playList_->currentItem() != NULL)
	{
		playList_->generatePlayOrderTable();	// class PlayList内部に持って行く
		startPlaying();
		Media *media = playList_->currentMedia();
		if (media->isAudio() && config.automaticallySwitchToPlayInfoEnabled) {
			// Show info widget
			setActiveView(Quasar::ViewPlayInfo);
		}

#ifdef QTOPIA
		// BatteryPlus関係の処理
		if (config.isBatteryPlusEnabled) {
			if (media->isVideo()) {
				g_BatteryPlus.setMode(config.batteryPlusMode4Video);
			} else {
				g_BatteryPlus.setMode(config.batteryPlusMode4Audio);
			}
		}
		
		disableSuspend();		
#endif
	}
}

void Quasar::stop_play()
{
	stopPlaying(true, false);
	playList_->setActiveItem(static_cast<PlayListItem *>(playList_->currentItem()));
	qApp->processEvents();
	play_pause(true);
}

void Quasar::stop()
{
	setActiveView(Quasar::ViewLastActivePlaylist);
	stopPlaying();

#ifdef QTOPIA
	enableSuspend();

	// BatteryPlus関係の処理
	if (config.isBatteryPlusEnabled)
		g_BatteryPlus.setMode(g_BatteryPlus.initialMode());
#endif
}

/*!
	@brief	MPlayerを起動し再生を開始する
*/
void Quasar::startPlaying()
{
	Media *media = playList_->currentMedia();
	
	DPRINTF("Current Media: %s", (const char *)(media->location().toString().utf8()));

	nextMediaPrefetched_ = false;
	currentMediaLength_ = media->length();

	// Start mplayer
	if (mplayer_->play(media) == false)
	{
		int result = QMessageBox::critical(this, tr("mplayer"),
				 tr("mplayer could not be executed or\nwas not found on your system.\nWould you like to specify the location\nof the mplayer binary on your system?"),
				 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape);
		
		if (result == QMessageBox::Yes)
		{
			configuration(true);
		}
	
		return;
	}
	
	// Set Operation Panel
	operationPanel_->setPlayPause(false);
	operationPanel_->setTotalPlayTime(currentMediaLength_);
	
	if (media->isVideo())
	{
		videoPlaybackWindow_->hide();
		videoPlaybackWindow_->reparent(0, QPoint(0, 0));
		videoPlaybackWindow_->resize(qApp->desktop()->size());
		videoPlaybackWindow_->setCursor(QCursor(blankCursor));
		videoPlaybackWindow_->showFullScreen();
		
#ifdef QTOPIA
		if (config.qcopBroadcastingEnabled)
		{
			QCopEnvelope e("QPE/MediaPlayer", "playingVideo(QString, int)");
			e << media->location().toString() << media->length();
		}
#endif
	}
	
	if (media->isAudio())
	{
		playInfo_->setMediaInfo(*playList_->currentMedia());
		playInfo_->setTotalNumber(playList_->childCount());
		// Get current number
		unsigned int n = 1;
		for (QListViewItemIterator it(playList_);
			it.current() != playList_->activeItem();
			++it, ++n) ;
		playInfo_->setCurrentNumber(n);
		
#ifdef QTOPIA		
		if (config.qcopBroadcastingEnabled)
		{
			if (media->location().isLocalFile())
			{
				QCopEnvelope e("QPE/MediaPlayer", "playingAudio(QString, QString, QString, QString, int)");
				e << media->location().toString() << media->title() << media->artist() << media->album() << media->length();
			}
			else
			{
				QCopEnvelope e("QPE/MediaPlayer", "playingStream(QString)");
				e << media->location().toString();
			}
		}
#endif
	}

	emit playbackStarted();
}

/*!
	@brief	MPlayerを終了する
*/
void Quasar::stopPlaying(bool temporarily, bool stopBackend)
{
	// Set Panels
	if (!temporarily)
	{
		operationPanel_->setCurrentPlayTime(0);
		operationPanel_->setPlayPause(true);
	}

	// Stop mplayer
	emit playbackStopped();
	
	if (stopBackend)
		mplayer_->stop();

#ifdef QTOPIA
	if (config.qcopBroadcastingEnabled)
		QCopEnvelope("QPE/MediaPlayer", "stopped()");
#endif
	
	if (!temporarily)
	{
		playList_->setActiveItem(NULL);
		playList_->setActiveItemPaused(false);
	}
	
	if (videoPlaybackWindow_->isVisible())
	{
		videoPlaybackWindow_->hide();
		videoPlaybackWindow_->reparent(this, QPoint(0, 0));
		videoPlaybackWindow_->resize(QSize(0, 0));
		videoPlaybackWindow_->unsetCursor();
	}
}

/*!
	@brief	現在選択されている次のアイテムを再生
	@see	previous()
*/
void Quasar::next()
{
	DPRINTF("Quasar::next()");
	if (playList_->nextMedia() != NULL)
	{
		++keyEventCount_;
		qApp->processEvents();
		--keyEventCount_;
		if (keyEventCount_ <= 0)
		{
			stopPlaying(true, false);
			startPlaying();
			keyEventCount_ = 0;
		}
	}
}

/*!
	@brief	現在選択されている前のアイテムを再生
	@see	next()
*/
void Quasar::previous()
{
	if (playList_->previousMedia() != NULL)
	{
		++keyEventCount_;
		qApp->processEvents();
		--keyEventCount_;
		if (keyEventCount_ <= 0)
		{
			stopPlaying(true, false);
			startPlaying();
			keyEventCount_ = 0;
		}
	}
}

/*!
	@brief	関連付からの起動時に呼ばれるスロット
*/
void Quasar::setDocument(const QString &path)
{
	stop();
	playListManager_->newPlayList();
	
	// Load ASX
	QRegExp asxExp("^[^\\.]+.asx$", false);
	if (asxExp.match(path) != -1)
	{
		playListManager_->openASX(path);
	}
	else
	{
		config.lastDirectory = QFileInfo(path).dirPath(true);
		playList_->insertItem(path);
	}

	playList_->updateFilter();	
	playList_->setActiveItem(0);
	play_pause();
}

void Quasar::closeEvent(QCloseEvent *e)
{
	if (mplayer_->isRunning())
	{
		stop();
		e->ignore();
		return;
	}
	else
	{
		// 終了確認
		if (config.isAskQuitingEnabled)
		{
			int ret;
			
			ret = QMessageBox::warning(this, tr("Confirmation"),
										tr("Do you really want to quit?"),
										tr("Yes"), tr("No"), QString::null,
										1, 1);
			
			/*
				MessageBoxを出した後はe->ignore()が無効になっている？
				e->ignore();
				return;
				としても終了してしまう
			*/
			if (ret == 1)
			{
				DPRINTF("close cancelled.");
				e->ignore();
				DPRINTF("event ignored.");
				return;
			}
		}	

#ifdef QTOPIA		
		setRemoteCon(true);
#endif

		if (skinManager_->style() == SkinManager::Landscape)
			playList_->saveColumnWidth(config.getConfigName(), "PlayListLandscape");
		else
			playList_->saveColumnWidth(config.getConfigName(), "PlayListPortrait");

		playList_->saveColumnOrder(config.getConfigName(), "PlayListLandscape");
		playList_->saveColumnOrder(config.getConfigName(), "PlayListPortrait");
		
		saveWidgetPosition(this, config.getConfigName(), "QuasarMainWindow");

		// save current splitter position if playlist overview is visible...
		if (playListOverview_->isVisible())
			config.overviewSplitterPosition = splitterContainer_->sizes()[0];
		
		// TODO: Reenable Media Cache saving
		//playList_->saveMediaCache();		

		delete playList_;		
		
		DPRINTF("close ok.");
		
		e->accept();
		return;
	}
}

void Quasar::resizeEvent(QResizeEvent *e)
{
 	DPRINTF("Quasar::resizeEvent : oldSize(%dx%d), newSize(%dx%d)",
 		   e->oldSize().width(), e->oldSize().height(),
 		   e->size().width(), e->size().height());
 	DPRINTF("  desktop(%dx%d)", qApp->desktop()->width(), qApp->desktop()->height());

	// are we switching back from full screen mode?
	if (e->oldSize().width() == qApp->desktop()->width() &&
		e->oldSize().height() == qApp->desktop()->height())
	{
		// necessary to switch back to normal mode in a clean fashion
		// otherwise the fullscreen mode won't work again.
		showNormal();
#ifdef QTOPIA
		 // on Qtopia force maximized view immediately after switching back to normal mode...
		showMaximized();
#endif
		isFullScreen_ = false;
	}

	checkOrientation();
}

void Quasar::setPlayOrder(int itemID)
{
	// 再生順序に関するアイテムが選択された場合のみ
	if (itemID >= 0 && itemID < PlayList::ORDER_MAX) {
		for (int i = 0; i < PlayList::ORDER_MAX; ++i) {
			playback_->setItemChecked(i, i == itemID ? true : false);
		}

		PlayList::PlayOrder playOrder = static_cast<PlayList::PlayOrder>(itemID);
		playList_->setPlayOrder(playOrder);
		toolPanel_->setPlayOrder(playOrder);
		/*
		filteredPlayList_->setPlayOrder(playOrder);
		*/
		config.playOrder = playOrder;
		
		QString statusMsg;
		switch (config.playOrder) {
		case PlayList::ORDER_REPEAT_ALL:
			statusMsg = tr("Switched to play order Repeat All.");
			break;
		case PlayList::ORDER_REPEAT_ONE:
			statusMsg = tr("Switched to play order Repeat One.");
			break;
		case PlayList::ORDER_RANDOM:
			statusMsg = tr("Switched to play order Random.");
			break;
		case PlayList::ORDER_REPEAT_RANDOM:
			statusMsg = tr("Switched to play order Repeat Random.");
			break;
		default:
			statusMsg = tr("Switched to play order Normal.");
			break;
		}
	
		toolPanel_->setStatusText(statusMsg);
	}
}

void Quasar::togglePlayOrder()
{
	config.playOrder = static_cast<PlayList::PlayOrder>(config.playOrder + 1);
	if (config.playOrder >= PlayList::ORDER_MAX)
		config.playOrder = PlayList::ORDER_NORMAL;
	
	setPlayOrder(config.playOrder);
}

void Quasar::toggleRandomPlayOrder()
{
	if (config.playOrder >= PlayList::ORDER_NORMAL &&
		config.playOrder <= PlayList::ORDER_REPEAT_ALL)
		config.playOrder = static_cast<PlayList::PlayOrder>(PlayList::ORDER_RANDOM + config.playOrder - PlayList::ORDER_NORMAL);
	else if (config.playOrder >= PlayList::ORDER_RANDOM &&
			 config.playOrder <= PlayList::ORDER_REPEAT_RANDOM)
		config.playOrder = static_cast<PlayList::PlayOrder>(PlayList::ORDER_NORMAL + config.playOrder - PlayList::ORDER_RANDOM);
	
	setPlayOrder(config.playOrder);
}

void Quasar::setFullScreen(int id)
{
	if (id != fullScreenMenuItemID_)
		return;

	config.isFullScreenEnabled = config.isFullScreenEnabled ? false : true;
	playback_->setItemChecked(fullScreenMenuItemID_, config.isFullScreenEnabled);
}

void Quasar::about()
{
	AboutDialog dialog(this, 0, true);
	loadWidgetPosition(&dialog, config.getConfigName(), "AboutDialog");
	dialog.exec();
	saveWidgetPosition(&dialog, config.getConfigName(), "AboutDialog");
}

//! Qtopiaの自動サスペンドとスクリーンセーバを無効にします。
/*!
  \sa Quasar::enableSuspend()
 */
void Quasar::disableSuspend()
{
#ifdef QTOPIA
	// 自動減光と自動サスペンドを無効にする
	/* +--+- 減光 -+- サスペンド -+
	 * |0 |        |              |
	 * |1 |        |       o      |
	 * |2 |   o    |              |
	 * |3 |   o    |       o      |
	 */
	QCopEnvelope e1("QPE/System", "setScreenSaverMode(int)");
	e1 << 0;
	// スクリーンセーバを無効にする
	QCopEnvelope e2("QPE/System", "setScreenSaverIntervals(int,int,int)");
	e2 << 0 << 0 << 0;
#endif
}

//! Qtopiaの自動サスペンドとスクリーンセーバを有効にします。
/*!
  \sa Quasar::disableSuspend()
 */
void Quasar::enableSuspend()
{
#ifdef QTOPIA
	// スクリーンセーバを有効にする
	QCopEnvelope e1("QPE/System", "setScreenSaverIntervals(int,int,int)");
	e1 << -1 << -1 << -1;
	// 自動減光とオートパワーオフを有効にする
	QCopEnvelope e2("QPE/System", "setScreenSaverMode(int)");
	e2 << 3;
#endif
}

/*!
	@brief	LCDを消灯する
	@see	turnOnLCD()
	@todo	復帰するときにCancel用のダミーを表示、あるいはkey制御を完全に奪う
*/
void Quasar::turnOnLCD()
{
#ifdef QTOPIA
	QCopEnvelope screenMode("QPE/System", "setBlankLCD(int)");
	screenMode << 0;
#endif
}

/*!
	@brief	LCDを点灯する
	@see	turnOffLCD()
*/
void Quasar::turnOffLCD()
{
#ifdef QTOPIA
	QCopEnvelope screenMode("QPE/System", "setBlankLCD(int)");
	screenMode << 1;
#endif
}

/*!
	@brief	現在の値からボリュームを相対指定する
	@see	setVolumeAbsolute()
	@todo	別クラス化
*/
void Quasar::setVolumeRelative(int v)
{
	int setLevel = (qSystemVolume.getCurrentLevel() + v);
	
	if (setLevel < 0)
		setLevel = 0;
	if (100 <= setLevel)
		setLevel = 100;
	
	qSystemVolume.setLevel(setLevel);
}

/*!
	@brief	ボリュームを0-100で絶対指定する
	@see	setVolumeRelative()
	@todo	別クラス化
*/
void Quasar::setVolumeAbsolute(int v)
{
	int setLevel = v;
	
	if (setLevel < 0)
		setLevel = 0;
	if (100 <= setLevel)
		setLevel = 100;
	
	qSystemVolume.setLevel(setLevel);
}

void Quasar::setupMenu()
{
	QAction *a;
	
	updateButtonAndMenuTimer_ = new QTimer(this);
	connect(updateButtonAndMenuTimer_, SIGNAL(timeout()), this, SLOT(updateButtonAndMenuState()));
	
	// Playlist
	fileMenu_ = new QPopupMenu(this);
	idFileMenuNewPlaylist_ = fileMenu_->insertItem(tr("New Playlist"), playListManager_, SLOT(newPlayList()),
						 g_ActionManager.actionByName("Playlist/New").accel());
	idFileMenuNewDynPlaylist_ = fileMenu_->insertItem(tr("New Dynamic Playlist..."), playListManager_, SLOT(newDynamicPlayList()));
	idFileMenuOpenPlaylist_ = fileMenu_->insertItem(tr("Open Playlist..."), playListManager_, SLOT(execDialogOpenPlayList()),
						 g_ActionManager.actionByName("Playlist/Open...").accel());
	fileMenu_->insertSeparator();
	idFileMenuSavePlaylist_ = fileMenu_->insertItem(tr("Save Playlist"), playListManager_, SLOT(savePlayList()),
						 g_ActionManager.actionByName("Playlist/Save").accel());
	idFileMenuSaveAsPlaylist_ = fileMenu_->insertItem(tr("Save Playlist As..."), playListManager_, SLOT(execDialogSavePlayListAs()),
						 g_ActionManager.actionByName("Playlist/Save As...").accel());
	fileMenu_->insertSeparator();
	fileMenu_->insertItem(tr("Quit"), this, SLOT(close()));
	
	connect(fileMenu_, SIGNAL(aboutToShow()), this, SLOT(fileMenuAboutToShow()));
	
	menuBar_->insertItem(tr("File"), fileMenu_);

	editMenu_ = new QPopupMenu(this);
	editMenu_->insertItem(tr("Add From URL..."), playListManager_, SLOT(execDialogAddURLToPlayList()),
							g_ActionManager.actionByName("Playlist/Add Location...").accel());
	editMenu_->insertItem(tr("Add From File..."), playListManager_, SLOT(execDialogAddFileToPlayList()),
							g_ActionManager.actionByName("Playlist/Add Files...").accel());
	editMenu_->insertItem(tr("Add From Directory..."), playListManager_, SLOT(execDialogAddDirToPlayList()),
							g_ActionManager.actionByName("Playlist/Add Directory...").accel());
	editMenu_->insertItem(tr("Add From Directory Including Subdirectories..."), playListManager_, SLOT(execDialogAddDirWithSubDirsToPlayList()));
	
	editMenu_->insertSeparator();

	idEditMenuCutItem_ = editMenu_->insertItem(tr("Cut"), playListManager_, SLOT(cutSelectionFromPlayList()),
						 g_ActionManager.actionByName("Playlist/Cut").accel());

	idEditMenuCopyItem_ = editMenu_->insertItem(tr("Copy"), playListManager_, SLOT(copySelectionFromPlayList()),
						 g_ActionManager.actionByName("Playlist/Copy").accel());

	idEditMenuPasteItem_ = editMenu_->insertItem(tr("Paste"), playListManager_, SLOT(pasteIntoPlayList()),
						 g_ActionManager.actionByName("Playlist/Paste").accel());

	idEditMenuDeleteItem_ = editMenu_->insertItem(tr("Delete"), playListManager_, SLOT(removeFileFromPlayList()),
						 g_ActionManager.actionByName("Playlist/Delete").accel());
	
	editMenu_->insertSeparator();

	editMenu_->insertItem(tr("Clear"), playListManager_, SLOT(clearPlayList()),
						 g_ActionManager.actionByName("Playlist/Clear").accel());

	editMenu_->insertSeparator();
	
	editMenu_->insertItem(tr("Select All"), playListManager_, SLOT(selectAll()),
						 g_ActionManager.actionByName("Playlist/Select All").accel());

	editMenu_->insertItem(tr("Deselect All"), playListManager_, SLOT(deselectAll()),
						 g_ActionManager.actionByName("Playlist/Deselect All").accel());
	
	editMenu_->insertSeparator();

	idEditMenuSelectModeItem_ = editMenu_->insertItem(tr("Select Mode"), this, SLOT(toggleSelectMode()),
			 g_ActionManager.actionByName("Playlist/Select Mode").accel());
	
	idEditMenuMultiSelectModeItem_ = editMenu_->insertItem(tr("Multiselect Mode"), this, SLOT(toggleMultiSelectMode()),
			 g_ActionManager.actionByName("Playlist/Multiselect Mode").accel());
	
	idEditMenuMoveItemModeItem_ = editMenu_->insertItem(tr("Move Item Mode"), this, SLOT(toggleMoveItemMode()),
			 g_ActionManager.actionByName("Playlist/Move Item Mode").accel());

	editMenu_->insertSeparator();
	
	editMenu_->insertItem(tr("Copy to On-The-Go play list"), playListManager_, SLOT(copyToOnTheGoPlayList()),
						 g_ActionManager.actionByName("Playlist/Copy To On-The-Go Playlist").accel());

	// connect handler for updating the above entries everytime the popup menu is shown...	
	connect(editMenu_, SIGNAL(aboutToShow()), this, SLOT(editMenuAboutToShow()));	
			
	menuBar_->insertItem(tr("Edit"), editMenu_);
	
	// View
	viewMenu_ = new QPopupMenu(this);

#ifdef QTOPIA
	viewMenu_->insertItem(tr("Turn Off LCD"), this, SLOT(turnOffLCD()),
					  g_ActionManager.actionByName("Playback/Turn Off LCD").accel());
#endif
	
	idViewMenuFullscreenItem_ = viewMenu_->insertItem(tr("Fullscreen"), this, SLOT(toggleFullScreen()),
					  g_ActionManager.actionByName("Display/Toggle Fullscreen").accel());
	
	idViewMenuShowOverviewItem_ = viewMenu_->insertItem(tr("Show Overview"), this, SLOT(toggleOverviewVisibility()),
			g_ActionManager.actionByName("Display/Toggle Overview Visibility").accel());
	
	viewMenu_->insertSeparator();
	
	// Sort By Submenu
	sortByMenu_ = new QPopupMenu(this);
	sortByMenu_->insertItem(tr("List order"), PlayList::COLUMN_NONE);
	sortByMenu_->insertSeparator();
	sortByMenu_->insertItem(tr("Track number"), PlayList::COLUMN_TRACKNO);
	sortByMenu_->insertItem(tr("Title"), PlayList::COLUMN_TITLE);
	sortByMenu_->insertItem(tr("Artist"), PlayList::COLUMN_ARTIST);
	sortByMenu_->insertItem(tr("Album"), PlayList::COLUMN_ALBUM);
	sortByMenu_->insertItem(tr("Length"), PlayList::COLUMN_LENGTH);
	sortByMenu_->setItemChecked(playList_->sortedColumn(), true);
	connect(sortByMenu_, SIGNAL(activated(int)), playList_, SLOT(setSortedColumn(int)));			
	
	viewMenu_->insertItem(tr("Sort by"), sortByMenu_);

	viewMenu_->insertSeparator();
	
	idViewMenuDynamicPlayListEditorItem_ = viewMenu_->insertItem(tr("Dynamic Playlist Editor"), this, SLOT(switchPlaylistEditorView()));
	idViewMenuCurrentPlayListItem_ = viewMenu_->insertItem(tr("Current Playlist"), this, SLOT(switchToCurrentPlayList()),
			g_ActionManager.actionByName("View/Current Playlist").accel());

	idViewMenuOnTheGoPlayListItem_ = viewMenu_->insertItem(tr("On-The-Go Playlist"), this, SLOT(switchToOnTheGoPlayList()),
			  g_ActionManager.actionByName("View/On-The-Go Playlist").accel());
	
	idViewMenuPlayInfoItem_ = viewMenu_->insertItem(tr("PlayInfo"), this, SLOT(switchToInfoWidget()),
			  g_ActionManager.actionByName("View/PlayInfo").accel());
	
	viewMenu_->insertSeparator();
	
	idViewMenuIncDisplaySize_ = viewMenu_->insertItem(tr("Increase Size"), this, SLOT(incDisplaySize()), 
			 g_ActionManager.actionByName("Display/Increase Size").accel());

	idViewMenuDecDisplaySize_ = viewMenu_->insertItem(tr("Decrease Size"), this, SLOT(decDisplaySize()), 
			 g_ActionManager.actionByName("Display/Decrease Size").accel());

	viewMenu_->insertSeparator();
	
	idViewMenuQuickswitchSkin1_ = viewMenu_->insertItem(tr("Quickswitch Skin 1"), this, SLOT(loadPrimarySkin()), 
			 g_ActionManager.actionByName("Display/Quickswitch Skin 1").accel());

	idViewMenuQuickswitchSkin2_ = viewMenu_->insertItem(tr("Quickswitch Skin 2"), this, SLOT(loadSecondarySkin()), 
			 g_ActionManager.actionByName("Display/Quickswitch Skin 2").accel());
	
	connect(viewMenu_, SIGNAL(aboutToShow()), this, SLOT(viewMenuAboutToShow()));
	
	menuBar_->insertItem(tr("View"), viewMenu_);

	// Playback
	playback_ = new QPopupMenu(this);
	playback_->setCheckable(true);
	fullScreenMenuItemID_ = playback_->insertItem(tr("Play Videos In Fullscreen Mode"));
	playback_->setItemChecked(fullScreenMenuItemID_, config.isFullScreenEnabled);
	connect(playback_, SIGNAL(activated(int)), this, SLOT(setFullScreen(int)));
	playback_->insertSeparator();
	
	playback_->insertItem(tr("Play Or Pause"), this, SLOT(play_pause()),
						 g_ActionManager.actionByName("Playback/Play Or Pause").accel());
	playback_->insertItem(tr("Stop"), this, SLOT(stop()),
						 g_ActionManager.actionByName("Playback/Stop").accel());
	playback_->insertItem(tr("Previous"), this, SLOT(previous()),
						 g_ActionManager.actionByName("Playback/Previous").accel());
	playback_->insertItem(tr("Next"), this, SLOT(next()),
						 g_ActionManager.actionByName("Playback/Next").accel());

	playback_->insertSeparator();

	playback_->insertItem(tr("Normal"), PlayList::ORDER_NORMAL);
	playback_->insertItem(tr("Repeat All"), PlayList::ORDER_REPEAT_ALL);
	playback_->insertItem(tr("Repeat One"), PlayList::ORDER_REPEAT_ONE);
	playback_->insertItem(tr("Random"), PlayList::ORDER_RANDOM);
	playback_->insertItem(tr("Repeat Random"), PlayList::ORDER_REPEAT_RANDOM);
	playback_->setItemChecked(config.playOrder, true);
	connect(playback_, SIGNAL(activated(int)), this, SLOT(setPlayOrder(int)));

	menuBar_->insertItem(tr("Controls"), playback_);

	// Tools
	toolsMenu_ = new QPopupMenu(this);
	toolsMenu_->insertItem(tr("Rescan For Cover Art Images..."), playInfo_, SLOT(rescanCoverArtDirectory()));
	idToolsMenuRescanDynamicPlaylist_ = toolsMenu_->insertItem(tr("Rescan Dynamic Playlist..."), playListManager_, SLOT(refreshDynamicPlayList()));
	toolsMenu_->insertSeparator();
	toolsMenu_->insertItem(tr("Configuration..."), this, SLOT(configuration()));
	toolsMenu_->insertSeparator();
	toolsMenu_->insertItem(tr("About..."), this, SLOT(about()));
	connect(toolsMenu_, SIGNAL(aboutToShow()), this, SLOT(toolsMenuAboutToShow()));
	
	menuBar_->insertItem(tr("Tools"), toolsMenu_);

	// Filter Edit Box		
	filterEditBox_ = new QLineEdit(subBar_);
	filterEditTimer_ = new QTimer(filterEditBox_);
	connect(filterEditTimer_, SIGNAL(timeout()), this, SLOT(filterEditBoxTimedUpdate()));
	connect(filterEditBox_, SIGNAL(returnPressed()), this, SLOT(filterEditBoxReturnPressed()));
	connect(filterEditBox_, SIGNAL(textChanged(const QString&)), this, SLOT(filterEditBoxTextChanged(const QString&)));
	connect(playListManager_, SIGNAL(playlistFilterChanged(const QString &)), this, SLOT(playlistManagerPlayListFilterChanged(const QString &)));
	subBar_->setStretchableWidget(filterEditBox_);
}

void Quasar::playlistManagerPlayListFilterChanged(const QString &filter)
{
	if (filterEditBox_->text() != filter)
	{
		filterEditBox_->blockSignals(true);
		filterEditBox_->setText(filter);
		filterEditBox_->blockSignals(false);
	}
}

void Quasar::fileMenuAboutToShow()
{
	Quasar::View view = activeView();
	bool viewIsOpenedPlaylist = (view == Quasar::ViewOpenedPlaylist || view == Quasar::ViewDynPlaylistEditor);
	
	// New Playlist Menu Item
	fileMenu_->changeItem(idFileMenuNewPlaylist_, viewIsOpenedPlaylist ? tr("New Playlist") : tr("New Playlist (N/A)"));
	fileMenu_->setItemEnabled(idFileMenuNewPlaylist_, viewIsOpenedPlaylist);
	
	// New Dynamic Playlist Menu Item
	fileMenu_->changeItem(idFileMenuNewDynPlaylist_, viewIsOpenedPlaylist ? tr("New Dynamic Playlist") : tr("New Dynamic Playlist (N/A)"));
	fileMenu_->setItemEnabled(idFileMenuNewDynPlaylist_, viewIsOpenedPlaylist);
	
	// Open Menu Item
	fileMenu_->changeItem(idFileMenuOpenPlaylist_, viewIsOpenedPlaylist ? tr("Open Playlist...") : tr("Load From Playlist File..."));
	
	// Save Menu Item
	fileMenu_->changeItem(idFileMenuSavePlaylist_, viewIsOpenedPlaylist ? tr("Save Playlist") : tr("Save Playlist (N/A)"));
	fileMenu_->setItemEnabled(idFileMenuSavePlaylist_, viewIsOpenedPlaylist);
	
	// Save As Menu Item
	fileMenu_->changeItem(idFileMenuSaveAsPlaylist_, viewIsOpenedPlaylist ? tr("Save As Playlist...") : tr("Save To Playlist File..."));	
}

void Quasar::updateButtonAndMenuState()
{
	if (updateButtonAndMenuTimer_->isActive())
		updateButtonAndMenuTimer_->stop();

	editMenuAboutToShow();
}

void Quasar::scheduleUpdateButtonAndMenuState()
{
	if (updateButtonAndMenuTimer_->isActive())
		updateButtonAndMenuTimer_->stop();

	updateButtonAndMenuTimer_->start(500, TRUE);
}

void Quasar::editMenuAboutToShow()
{
	bool isDynamicPlaylist = playListManager_->isDynamicPlaylist();
	bool isDynamicPlaylistEditorActive = playListManager_->isDynamicPlaylistEditorActive();
	bool anythingSelected = playListManager_->isAnythingSelected();
	
	editMenu_->changeItem(idEditMenuCutItem_, isDynamicPlaylist ? tr("Cut (N/A for Dynamic Playlists)") : tr("Cut"));
	bool cutEnabled = !isDynamicPlaylist && !isDynamicPlaylistEditorActive && anythingSelected;
	editMenu_->setItemEnabled(idEditMenuCutItem_, cutEnabled);
	playListToolPanel_->setCutEnabled(cutEnabled);

	bool copyEnabled = !isDynamicPlaylistEditorActive && anythingSelected;
	editMenu_->setItemEnabled(idEditMenuCopyItem_, copyEnabled);
	playListToolPanel_->setCopyEnabled(copyEnabled);

	editMenu_->changeItem(idEditMenuPasteItem_, isDynamicPlaylist ? tr("Paste (N/A for Dynamic Playlists)") : tr("Paste"));
	bool pasteEnabled = 
		!isDynamicPlaylist &&
		!isDynamicPlaylistEditorActive &&
		playListManager_->mediaClipboardCount() > 0;

	editMenu_->setItemEnabled(idEditMenuPasteItem_, pasteEnabled);
	playListToolPanel_->setPasteEnabled(pasteEnabled);
	
	editMenu_->changeItem(idEditMenuDeleteItem_, isDynamicPlaylist && !isDynamicPlaylistEditorActive ? tr("Delete (N/A for Dynamic Playlists)") : tr("Delete"));
	bool deleteEnabled = (!isDynamicPlaylist || isDynamicPlaylistEditorActive) && anythingSelected;
	editMenu_->setItemEnabled(idEditMenuDeleteItem_, deleteEnabled);
	playListToolPanel_->setDeleteEnabled(deleteEnabled);
	
	playListToolPanel_->setCopyToOTGEnabled(playListManager_->activeMode() == PlayListManager::ModeOpenedPlaylist && anythingSelected);
	
	editMenu_->setItemChecked(idEditMenuSelectModeItem_, playList_->inputMode() == PlayList::Select);
	editMenu_->setItemChecked(idEditMenuMultiSelectModeItem_, playList_->inputMode() == PlayList::MultiSelect);
	editMenu_->setItemChecked(idEditMenuMoveItemModeItem_, playList_->inputMode() == PlayList::Move);
	editMenu_->setItemEnabled(idEditMenuMoveItemModeItem_, !isDynamicPlaylist && anythingSelected);
}

void Quasar::viewMenuAboutToShow()
{
	Quasar::View view = activeView();
	
	viewMenu_->setItemChecked(idViewMenuFullscreenItem_, isFullScreen_);
	viewMenu_->setItemChecked(idViewMenuShowOverviewItem_, playListOverview_->isVisible());
	
	// current playlist menu item
	viewMenu_->setItemChecked(idViewMenuCurrentPlayListItem_, view == Quasar::ViewOpenedPlaylist);
	
	// on the go playlist menu item
	viewMenu_->setItemChecked(idViewMenuOnTheGoPlayListItem_, view == Quasar::ViewOnTheGoPlaylist);

	// Dynamic playlist editor menu item
	viewMenu_->changeItem(idViewMenuDynamicPlayListEditorItem_, playListManager_->isDynamicPlaylist() ? tr("Dynamic Playlist Editor") : tr("Dynamic Playlist Editor (N/A)"));
	viewMenu_->setItemEnabled(idViewMenuDynamicPlayListEditorItem_, playListManager_->isDynamicPlaylist());
	viewMenu_->setItemChecked(idViewMenuDynamicPlayListEditorItem_, view == Quasar::ViewDynPlaylistEditor);
	
	// Play info menu item
	viewMenu_->setItemChecked(idViewMenuPlayInfoItem_, view == Quasar::ViewPlayInfo);
	
	// Update Increase / Decrease size menu items
	viewMenu_->setItemEnabled(idViewMenuIncDisplaySize_, config.infoMode != SkinManager::BigMode);
	viewMenu_->setItemEnabled(idViewMenuDecDisplaySize_, config.infoMode != SkinManager::SmallMode);
}

void Quasar::toolsMenuAboutToShow()
{
	toolsMenu_->setItemEnabled(idToolsMenuRescanDynamicPlaylist_, playListManager_->isDynamicPlaylist());	
}

void Quasar::setAbsoluteSeconds(int secs)
{
/*	TODO: Enable IPC via QCOP/DCOP/DBUS */
#ifdef QTOPIA
	if (config.qcopBroadcastingEnabled)
		QCopEnvelope("QPE/MediaPlayer", "seeked(int)") << secs;
#endif

	mplayer_->seekAbsoluteSeconds(secs);
}

void Quasar::mplayerErrorMessage(QString msg)
{
	TextViewDialog errDialog(tr("MPlayer Error Message"),
		 tr("MPlayer could not be started for the following reason.") + "\n" + 
		 tr("Perhaps your format configuration is wrong.") + "\n" + 
		 tr("Do you want to open the configuration dialog?"),
		 msg, this
	);
	
	if (errDialog.exec())
		configuration(true);
}

void Quasar::mplayerCurrentPlayTime(int seconds)
{
	operationPanel_->setCurrentPlayTime(seconds);

	if (!nextMediaPrefetched_ && currentMediaLength_ - seconds < 21)
	{
		// prefetch next track...
		nextMediaPrefetched_ = true;
		
		PlayListItem *item = playList_->nextPlayItem();
		Media *media = NULL;
		
		if (item)
			media = item->media();
		
		if (media)
		{
			QFile mediaFile(media->location().toString());
		
			// make sure all necessary data is read from database...
			if (media->isAudio())
				MediaAudio *audio = media->mediaAudio();
			else if (media->isVideo())
				MediaVideo *video = media->mediaVideo();
		
			if (config.isPrefetchFileEnabled && mediaFile.open(IO_Raw | IO_ReadOnly))
			{
				char buffer[65536];
				
				int maxFetchBytes = 1024 * 1024;
				if (config.isCacheEnabled && (config.cacheSize + 128) * 1024 > maxFetchBytes)
					maxFetchBytes = (config.cacheSize + 128) * 1024;
		
				QTime time;
				time.start();
				
		        while (!mediaFile.atEnd() && mediaFile.at() < maxFetchBytes)
		        {
		        	// only read a block any x milliseconds
		        	// in order not to overload the I/O and induce skips
		        	while (time.elapsed() < 25) 
		        		qApp->processOneEvent();
		        	 
		        	mediaFile.readBlock(&buffer[0], 65536);
		        	
		        	time.restart();
		        }

		        mediaFile.close();
			}
	        
			playInfo_->precacheCoverArt(*media);
		}
	}
}

/*! 設定ダイアログを実行し、設定の変更を反映します。

 設定ファイルにも書き戻します。
*/
void Quasar::configuration()
{
	configuration(false);
}

void Quasar::configuration(bool showMPlayerConfig)
{
	DPRINTF("[ConfigurationDialog] Initializing...");
	ConfigurationDialog configDialog(config, this, "Configuration Dialog");

	connect(&configDialog, SIGNAL(nukeMediaCacheButtonClicked()), playList_, SLOT(cleanUpMediaCache()));
	DPRINTF("[ConfigurationDialog] Done");

	if (showMPlayerConfig)
		configDialog.showMPlayerConfig();
	
	DPRINTF("[ConfigurationDialog] Executing...");
	if (configDialog.exec() == QDialog::Accepted)
	{
		DPRINTF("[ConfigurationDialog] Done");

		config = configDialog.result();
		config.write();

#ifdef QTOPIA		
		setRemoteCon();
#endif
		setPlayListFont(config.infoMode);

		MPlayer mplayer;
		mplayer.checkFeatures();
		
		playInfo_->setCoverArtDirectory(config.coverArtDirectory);
	}
	DPRINTF("[ConfigurationDialog] Destroy");
}

void Quasar::filterEditBoxReturnPressed()
{
	playList_->setFocus();
}

void Quasar::filterEditBoxTextChanged(const QString &text)
{
	newFilterText_ = text;

	setActiveView(Quasar::ViewLastActivePlaylist);
	
	if (filterEditTimer_->isActive())
		filterEditTimer_->stop();

	filterEditTimer_->start(config.playlistAutoTriggerFilterInterval, TRUE);
}

void Quasar::filterEditBoxTimedUpdate()
{
	DPRINTF("searchEditTextChanged %s", newFilterText_.latin1());
	setFilter(newFilterText_);
}

void Quasar::setFilter(const QString &text)
{
	DTIMERINIT(filteroverall);
	
	setActiveView(Quasar::ViewLastActivePlaylist);

	DTIMERINIT(setfilter);
	playList_->setFilter(text);
	DTIMERPRINT(setfilter, "playList_->setFilter(text);");
	
	DTIMERPRINT(filteroverall, "Quasar::setFilter");
}

void Quasar::resetFilter()
{
	filterEditBox_->clear(); // will trigger setFilter
}

void Quasar::resetFilterAndFocusFilterEditBox()
{
	resetFilter();
	filterEditBox_->setFocus();
}

void Quasar::setPlayListFont(SkinManager::InfoMode mode)
{
	const SkinModeInformation *modeInfo = skinManager_->getInfo(mode);
	
	playList_->setSkinMode(*modeInfo);
	playListOverview_->setSkinMode(*modeInfo);
	
	if (modeInfo->playListOverviewSeparatorColor().isUsed())
	{
		QPalette palette(modeInfo->playListOverviewSeparatorColor());
		splitterContainer_->setPalette(palette);
	}
	else
		splitterContainer_->unsetPalette();
		
	playInfo_->setFont(modeInfo->playInfoFont().font);
	playInfo_->setColor(modeInfo->playInfoFont().fontColor, modeInfo->playInfoBackgroundColor());
	
	if (modeInfo->toolBarColor().isUsed())
	{
		QPalette palette(modeInfo->toolBarColor());
		
		if (modeInfo->toolBarFont().fontColor.isUsed())
		{
			palette.setColor(QColorGroup::Text, modeInfo->toolBarFont().fontColor);
			palette.setColor(QColorGroup::ButtonText, modeInfo->toolBarFont().fontColor);
			palette.setColor(QColorGroup::Foreground, modeInfo->toolBarFont().fontColor);
		}

		toolBar_->setPalette(palette);
		subBar_->setPalette(palette);
	}
	else
	{
		toolBar_->unsetPalette();
		subBar_->unsetPalette();
	}

	if (modeInfo->toolBarFont().font.isUsed())
	{
		toolBar_->setFont(modeInfo->toolBarFont().font);
		subBar_->setFont(modeInfo->toolBarFont().font);
	}
	else
	{
		toolBar_->unsetFont();
		subBar_->unsetFont();
	}

	if (modeInfo->filterBoxBackgroundColor().isUsed())
	{
		QPalette palette(modeInfo->filterBoxBackgroundColor());
		
		if (modeInfo->filterBoxFont().fontColor.isUsed())
		{
			palette.setColor(QColorGroup::Text, modeInfo->filterBoxFont().fontColor);
			palette.setColor(QColorGroup::Foreground, modeInfo->filterBoxFont().fontColor);
		}

		filterEditBox_->setPalette(palette);
	}
	else
	{
		filterEditBox_->unsetPalette();
	}
	
	if (modeInfo->filterBoxFont().font.isUsed())
		filterEditBox_->setFont(modeInfo->filterBoxFont().font);
	else
		filterEditBox_->unsetFont();

#ifndef QTOPIA
	// Workaround for realignment issues in Qt3
	toolBar_->hide();
	toolBar_->show();
#endif
}

void Quasar::incDisplaySize()
{
	if (config.infoMode == SkinManager::BigMode) return;
	if (config.infoMode == SkinManager::SmallMode)
		config.infoMode = SkinManager::NormalMode;
	else
		config.infoMode = SkinManager::BigMode;
	setPlayListFont(config.infoMode);
}

void Quasar::decDisplaySize()
{
	if (config.infoMode == SkinManager::SmallMode) return;
	if (config.infoMode == SkinManager::BigMode)
		config.infoMode = SkinManager::NormalMode;
	else
		config.infoMode = SkinManager::SmallMode;
	setPlayListFont(config.infoMode);	
}

void Quasar::setRemoteCon(bool shuttingDown)
{
#ifdef QTOPIA
	Config cfg("qpe");
	cfg.setGroup("Remocon");
	
	//QCopEnvelope e("QPE/System", "registRemoconMaster(QString,int)");

	if (config.registerAsRemoteConMaster)
	{
		//e << QString(BINNAME) << (shuttingDown ? 0 : 1);
		cfg.writeEntry("master", QString(BINNAME));
	}
	else if (cfg.readEntry("master") == QString(BINNAME))
	{
		//e << QString("musicplayer") << (shuttingDown ? 0 : 1);
		cfg.writeEntry("master", "musicplayer");
	}
#endif	
}

void Quasar::changeOrientation(bool landscape, bool setSkinStyle, bool saveCurrentColumnWidths)
{
	if (landscape)
	{
		if (setSkinStyle)
			skinManager_->setStyle(SkinManager::Landscape);
			
		if (saveCurrentColumnWidths)
			playList_->saveColumnWidth(config.getConfigName(), "PlayListPortrait");

		// TODO: Remove hardcoded default column widths to some other place...
		const int defaultColumnWidth[6] = {20, 42, 182, 154, 162, 54};
		for (int i = 0; i < playList_->columns(); ++i)
			playList_->setColumnWidth(playList_->header()->mapToSection(i), defaultColumnWidth[i]);

		playList_->loadColumnWidth(config.getConfigName(), "PlayListLandscape");
	}
	else 
	{
		if (setSkinStyle)
			skinManager_->setStyle(SkinManager::Portrait);
		
		if (saveCurrentColumnWidths)
			playList_->saveColumnWidth(config.getConfigName(), "PlayListLandscape");
		
		// TODO: Remove hardcoded default column widths to some other place...
		const int defaultColumnWidth[6] = {24, 40, 107, 105, 119, 48};
		for (int i = 0; i < playList_->columns(); ++i)
			playList_->setColumnWidth(playList_->header()->mapToSection(i), defaultColumnWidth[i]);
		
		playList_->loadColumnWidth(config.getConfigName(), "PlayListPortrait");
	}
	
	if (centralWidget())
	{
		centralWidget()->updateGeometry();
		if (centralWidget()->layout())
			centralWidget()->layout()->activate();
	}
	
	currentWidth_ = qApp->desktop()->width();
}

void Quasar::checkOrientation()
{
	if (qApp->desktop()->width() != currentWidth_)
	{
		changeOrientation(qApp->desktop()->width() > qApp->desktop()->height());
		/*
		if (isActiveWindow())
		{
			DPRINTF("Active Window!! Start workaround...");
			hide();
			show();
		}
		*/
	}
}

void Quasar::toggleFullScreen()
{
	if (!isFullScreen_)
	{
		showFullScreen();
		isFullScreen_ = true;
	}
	else
	{
		// necessary to switch back to normal mode in a clean fashion
		// otherwise the fullscreen mode won't work again.
		showNormal();
#ifdef QTOPIA
		 // on Qtopia force maximized view immediately after switching back to normal mode...
		showMaximized();
#endif
		isFullScreen_ = false;
	}
}

void Quasar::toggleOverviewVisibility()
{
	setOverviewVisibility(!playListOverview_->isVisible());
}

void Quasar::setOverviewVisibility(bool visible)
{
	setActiveView(Quasar::ViewLastActivePlaylist);
	
	if (visible)
	{
		playListOverview_->show();

		// create list of heights for each of the two widgets in the splitter container
		// that is: PlayListOverview and PlayList
		QValueList<int> sizes;
		sizes.append(config.overviewSplitterPosition);
		sizes.append(splitterContainer_->height() - config.overviewSplitterPosition);
		splitterContainer_->setSizes(sizes);	

		playListOverview_->setFocus();
	}
	else
	{
		// only set current splitter position if playlist overview is visible...
		if (playListOverview_->isVisible())
			config.overviewSplitterPosition = splitterContainer_->sizes()[0];
		
		playListOverview_->hide();
		playList_->setFocus();
	}
	
	config.isOverviewVisible = visible;
	toolPanel_->setOverviewVisibility(visible);	
}

void Quasar::loadPrimarySkin()
{
	operationPanel_->hide();
	skinManager_->load(config.skin1);
	if (qApp->desktop()->width() > qApp->desktop()->height())
		skinManager_->setStyle(SkinManager::Landscape);
	else
		skinManager_->setStyle(SkinManager::Portrait);

	setPlayListFont(config.infoMode);
	operationPanel_->show();
	operationPanel_->updateGeometry();
	repaint();
}

void Quasar::loadSecondarySkin()
{
	operationPanel_->hide();
	skinManager_->load(config.skin2);
	if (qApp->desktop()->width() > qApp->desktop()->height())
		skinManager_->setStyle(SkinManager::Landscape);
	else
		skinManager_->setStyle(SkinManager::Portrait);

	setPlayListFont(config.infoMode);
	operationPanel_->show();
	operationPanel_->updateGeometry();
	repaint();
}

void Quasar::playlistViewUpdated()
{
	// calculate overall playtime for current view:	
	long long playtime = playList_->totalPlaytime();
	
	long long playtimeMins = playtime / 60;
	long playtimeSecsRem = playtime % 60;
	long long playtimeHours = playtimeMins / 60;
	long playtimeMinsRem = playtimeMins % 60; 
	long playtimeDays = playtimeHours / 24;
	long playtimeHoursRem = playtimeHours % 24;
	
	QCString timeDisplay;
	if (playtimeDays > 0)
		timeDisplay = QCString().sprintf("%d:%02d:%02d:%02d", playtimeDays, playtimeHoursRem, playtimeMinsRem, playtimeSecsRem);
	else if (playtimeHoursRem > 0)
		timeDisplay = QCString().sprintf("%d:%02d:%02d", playtimeHoursRem, playtimeMinsRem, playtimeSecsRem);
	else if (playtimeMinsRem > 0)
		timeDisplay = QCString().sprintf("%d:%02d", playtimeMinsRem, playtimeSecsRem);
	else
		timeDisplay = QCString().sprintf("%d", playtimeSecsRem);
	
	// calculate overall filesize for current view:	
	long long filesize = playList_->totalFileSize();
	
	QCString filesizeDisplay;
	if (filesize > 1024 * 1024 * 1024)
		filesizeDisplay = QCString().sprintf("%.2f GB", (float)filesize / (1024 * 1024 * 1024));
	else if (filesize > 1024 * 1024)
		filesizeDisplay = QCString().sprintf("%.1f MB", (float)filesize / (1024 * 1024));
	else
		filesizeDisplay = QCString().sprintf("%.1f KB", (float)filesize / 1024);
	
	toolPanel_->setInfoText(QString().sprintf("%d titles, %s, %s", playList_->itemCount(), (const char *)timeDisplay, (const char *)filesizeDisplay));
	
	updateButtonAndMenuState();
}

void Quasar::playlistViewSorted()
{
	for (int i = 0; i < PlayList::COLUMN_MAX; ++i)
		sortByMenu_->setItemChecked(i, i == playList_->sortedColumn() ? true : false);
		
	updateButtonAndMenuState();
}

void Quasar::playlistManagerPlayListFileNameChanged()
{
	setCaption(QString(APPNAME) + " - " + playListManager_->getDisplayPlayListFilename());
}

void Quasar::playlistManagerPlayListCleared()
{
	resetFilter();
	updateButtonAndMenuState();	
}

void Quasar::playlistOverviewFocusOutLeft()
{
	filterEditBox_->setFocus();
}

void Quasar::playlistOverviewFocusOutRight()
{
	playList_->setFocus();
}

void Quasar::setFocusPlayListOverview()
{
	if (!playListOverview_->isVisible())
		setOverviewVisibility(true);
	
	playListOverview_->setFocus();
}

Quasar::View Quasar::activeView()
{
	if (widgetStack_->visibleWidget() == playInfo_)
		return Quasar::ViewPlayInfo;
	else
	{
		switch (playListManager_->activeMode())
		{
			case PlayListManager::ModeDynPlaylistEditor:
				return Quasar::ViewDynPlaylistEditor;
			case PlayListManager::ModeOpenedPlaylist:
				return Quasar::ViewOpenedPlaylist;
			case PlayListManager::ModeOnTheGoPlaylist:
				return Quasar::ViewOnTheGoPlaylist;
			default:
				return Quasar::ViewLastActivePlaylist;
		}
	}
}

bool Quasar::setActiveView(View view)
{
	bool result = false;
	
	if (view == activeView())
		return true;
	
	if (view == Quasar::ViewPlayInfo)
	{
		playListManager_->setActiveMode(PlayListManager::ModeLastActivePlaylist);
		widgetStack_->raiseWidget(InfoWidget);
		toolPanel_->setView(ToolPanel::PlayInfo);
	}
	else
	{
		PlayListManager::Mode mode = PlayListManager::ModeLastActivePlaylist;
		
		switch (view)
		{
			case Quasar::ViewDynPlaylistEditor:
				mode = PlayListManager::ModeDynPlaylistEditor;
				break;
			case Quasar::ViewOpenedPlaylist:
				mode = PlayListManager::ModeOpenedPlaylist;
				break;
			case Quasar::ViewOnTheGoPlaylist:
				mode = PlayListManager::ModeOnTheGoPlaylist;
				break;
			default:
				mode = PlayListManager::ModeLastActivePlaylist;
		}
		
		// this will fire playlistManagerSwitchingModeTo below...
		// play info widget is taken care of there...
		playListManager_->setActiveMode(mode);		
	}
	
	updateButtonAndMenuState();
	return result;
}

void Quasar::playlistManagerSwitchingModeTo(PlayListManager::Mode mode)
{
	// make sure play info widget is lower than playlist...
	if (widgetStack_->visibleWidget() == playInfo_)
	{
		widgetStack_->raiseWidget(PlayListWidget);
		toolPanel_->setView(ToolPanel::PlayList);
		
		// if we are switching because the filter edit box was activated,
		// keep the focus in there, otherwise shift focus to playlist widget...
		if (qApp->focusWidget() != filterEditBox_)
			playList_->setFocus();
	}
}

void Quasar::playlistManagerSwitchedModeTo(PlayListManager::Mode mode)
{
	playlistManagerPlayListFileNameChanged();
	playListToolPanel_->setMode(mode);
	updateButtonAndMenuState();
}

void Quasar::playlistToolPanelModeChanged(PlayListManager::Mode mode)
{
	playListManager_->setActiveMode(mode);
}

void Quasar::toggleInfoWidget()
{
	if (activeView() != Quasar::ViewPlayInfo)
		setActiveView(Quasar::ViewPlayInfo);
	else
		setActiveView(Quasar::ViewLastActivePlaylist);
}

void Quasar::switchPlaylistEditorView()
{
	setActiveView(Quasar::ViewDynPlaylistEditor);
}

void Quasar::switchToLastActivePlayList()
{
	setActiveView(Quasar::ViewLastActivePlaylist);	
}

void Quasar::switchToCurrentPlayList()
{
	setActiveView(Quasar::ViewOpenedPlaylist);
}

void Quasar::switchToOnTheGoPlayList()
{
	setActiveView(Quasar::ViewOnTheGoPlaylist);
}

void Quasar::switchToInfoWidget()
{
	setActiveView(Quasar::ViewPlayInfo);
}

void Quasar::setInputMode(PlayList::InputMode inputMode)
{
	config.inputMode = inputMode;
	playListManager_->setInputMode(inputMode);
	playListToolPanel_->setInputMode(inputMode);
}

void Quasar::resetFilterAndSorting()
{
	playList_->resetSorting();
	playListOverview_->resetFilter();
	resetFilter();
	updateButtonAndMenuState();	
}
