//**************************************************************************
//*                     This file is part of the                           *
//*                MMC - Mpxplay Multimedia Commander                      *
//*                   The source code of MMC is                            *
//*        (C) copyright 1998-2018 by PDSoft (Attila Padar)                *
//*                http://mpxplay.sourceforge.net                          *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  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.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: QT main window build

//#define MPXPLAY_USE_DEBUGF 1
#define DISPQT_DEBUG_ERROR stderr
#define DISPQT_DEBUG_MENUBAR NULL // stdout
#define DISPQT_DEBUG_MIXER NULL //stdout
#define DISPQT_DEBUG_OUTPUT NULL // stdout
#define MPXPLAY_DEBUG_TRANSOUT NULL // stdout
#define DISPQT_DEBUG_OPACITY stdout
#define DISPQT_DEBUGOUT_FFMPEG stdout

#include <QtWidgets>
#include <QtWinExtras/QtWinExtras>
#ifdef QT_STATIC
#include <QtPlugin>
Q_IMPORT_PLUGIN (QWindowsIntegrationPlugin);
#ifdef MPXPLAY_LINK_QTMEDIA
Q_IMPORT_PLUGIN (DSServicePlugin);
#endif
#endif
#include <malloc.h>
#include "disp_qt.h"
#include "moc_mainwindow.h"
#include "moc_avmixer.h"
#include "moc_config.h"
#include "moc_editor.h"
#include "moc_seekbar.h"
#include "moc_textwin.h"
#include "moc_video_ctrlbar.h"
#include "moc_video_qt.h"
#include "mpxplay.h"
#include "control/cntfuncs.h"
#include "display/display.h"
#include "newfunc/newfunc.h"
#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
#include <libavutil/ffversion.h>
#endif

#define DISPQT_MAINWIN_SIZEY_BASE       30 // FIXME: calculate
#define DISPQT_MAINWIN_SIZEY_VIDEO_MIN  10
#define DISPQT_MAINWIN_SIZEY_EDITOR_MIN 50
//#define DISPQT_MAINWIN_SIZEY_OPTIMAL   (DISPQT_MAINWIN_SIZEY_BASE + DISPQT_MAINWIN_SIZEY_VIDEO_MIN + DISPQT_MAINWIN_SIZEY_EDITOR_MIN + 200)

#define DISPQT_MAINWIN_MOUSEPRESS_STARTTIME  300 // start press process after ms
#define DISPQT_MAINWIN_MOUSEPRESS_REPEATTIME  33 // repeat press process in every ms

static void mpxplay_dispqt_mainwindow_apply_loadfiles_callback(void *passdata);

extern "C" {
 extern struct mainvars mvps;
 extern unsigned int playcontrol, refdisp, desktopmode, playrand, playreplay, playstartframe;
 extern unsigned long mpxplay_config_videoplayer_type, mpxplay_config_videoplayer_control;
 extern keyconfig kb[];
}

static struct dispqt_cfgwinctrl_to_widgetnum_s dispqt_mainwin_widgetlist[DISPQT_MAINWIN_WIDGET_MAX + 1] = {
 { 0,      DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO, DISPQT_MAINWIN_WIDGET_VIDEO,   0, 1 },
 { DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR,    0, DISPQT_MAINWIN_WIDGET_SEEKBAR, 0, 0 },
 { DISPQT_CONFIG_MAINWINCTRL_SHOW_TOOLBAR,    0, DISPQT_MAINWIN_WIDGET_TOOLBAR, 0, 0 },
 { DISPQT_CONFIG_MAINWINCTRL_SHOW_AVMIXER,    0, DISPQT_MAINWIN_WIDGET_AVMIXER, 0, 1 },
 { DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR,     0, DISPQT_MAINWIN_WIDGET_EDITOR,  0, 3 },
 { DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE, 0, DISPQT_MAINWIN_WIDGET_STATUSLINE, 0, 0 },
 { 0, DISPQT_MAINWIN_WIDGET_MAX}
};

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "MainWindow BEGIN");
	this->mainwin_initialized = false;
	this->hide();
	this->analtabdelay = 3;
	this->prev_mainwin_control = 0;
	this->action_statusbar_msg_dynamic = NULL;
	this->qt_video_player = NULL;
	this->mainwin_seekbar = NULL;
	this->toolbar_widget = NULL;
	this->mixer_widget = NULL;
	this->mixer_dialog = NULL;
	this->mainwin_gsave_lock = false;
	this->is_composition_enabled = false;
	this->mainwin_opacity_curr = DISPQT_CONFIG_MAINWIN_OPACITY_GENERAL_MAX;
	this->timer_mainwin_onvideo = NULL;
	this->timer_mainwin_mousepress = new QTimer(this);
	this->timer_mainwin_mousepress_repeat = new QTimer(this);
	this->timer_mainwin_mousepress_repeat->setInterval(DISPQT_MAINWIN_MOUSEPRESS_REPEATTIME);
	this->timer_mainwin_mousepress_repeat->setSingleShot(false);
	connect(this->timer_mainwin_mousepress, SIGNAL(timeout()), this, SLOT(mainwin_handle_mousepress_timer()));
	connect(this->timer_mainwin_mousepress_repeat, SIGNAL(timeout()), this, SLOT(mainwin_handle_mousepress_timer()));

	this->setMinimumSize(200, 100);

	struct mmc_dispqt_config_s *gcfg = this->gui_config = mpxplay_dispqt_configini_get();

	//int screen_num = QApplication::desktop()->screenNumber(QPoint((gcfg->mainwin_pos_x + 50), (gcfg->mainwin_pos_y + 50))); // doesn't work?
	int nb_screens = QApplication::desktop()->screenCount();
	int maxx_screen0 = QApplication::desktop()->screenGeometry(0).width();
	int max_x = maxx_screen0, max_y = QApplication::desktop()->screenGeometry().height();
	for(int i = 1; i < nb_screens; i++)
		max_x += QApplication::desktop()->screenGeometry(i).width();

	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "MainWindow sn:%d mx:%d my:%d x:%d y:%d", nb_screens, max_x, max_y, gcfg->mainwin_pos_x, gcfg->mainwin_pos_y);

	// correct main window position if it's out of screen
	if(gcfg->mainwin_pos_x < 0)
		gcfg->mainwin_pos_x = maxx_screen0 - gcfg->mainwin_size_x - 20;
	else if(gcfg->mainwin_pos_x > (max_x - 30))
		gcfg->mainwin_pos_x = max_x - gcfg->mainwin_size_x - 20;
	if(gcfg->mainwin_pos_x < 0)
		gcfg->mainwin_pos_x = 0;

	if((gcfg->mainwin_pos_y < 0) || (gcfg->mainwin_pos_y > (max_y - 30)))
		gcfg->mainwin_pos_y = 10;
	if(gcfg->mainwin_size_y <= 0)
		gcfg->mainwin_size_y = max_y - gcfg->mainwin_pos_y - 90;
	if(gcfg->mainwin_size_y <= 0)
		gcfg->mainwin_size_y = DISPQT_MAINWIN_INITSIZE_Y;

	if(gcfg->font_text_name[DISPQT_FONTTEXTID_MAINWIN]){
		this->font_mainwin.fromString(QString::fromUtf8(gcfg->font_text_name[DISPQT_FONTTEXTID_MAINWIN]));
		this->setFont(this->font_mainwin);
	}

	this->mainwin_geometry_restore(false);

	this->main_widget = new QWidget;
	this->main_layout = new QVBoxLayout;
	this->main_layout->setMargin(0);

	if(gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT)
		this->mainwin_set_style();

	createActions();
	createMenus();
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "MainWindow createVideo() %d %8.8X", gcfg->selected_videoplayer_type, gcfg->video_control);
	createVideo(this);
	if(this->qt_video_player)
		this->main_layout->addWidget(this->qt_video_player, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_VIDEO));
	createSeekbar(true);
	createToolBars(true);
	createVideoControlbar(true);
	createAVmixer(true);
	connect(this, SIGNAL(signal_mixer_dialog_close()), this, SLOT(event_mixer_dialog_close()));
	createEditor(true);
	createDialogHandler(this);

	this->main_widget->setLayout(this->main_layout);
	setCentralWidget(this->main_widget);

	mainwin_statusbar_init();
	mainwin_taskbar_init();

	mainwin_connect_signals();

	this->prev_mainwin_control = gcfg->mainwin_control;
	this->prev_video_control = gcfg->video_control;
	gcfg->selected_videoplayer_control = mpxplay_config_videoplayer_control;

	if((gcfg->transparent_control & (DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_RESTORE | DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED)) == (DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_RESTORE | DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED))
		this->mainwin_set_transparent(true, true);
	else if(gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_ALWAYS_ON_TOP)
		mainwindow_set_always_on_top(true);
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "MainWindow END");
}

void MainWindow::mainwin_connect_signals(void)
{
	connect(this, SIGNAL(signal_config_apply()), this, SLOT(config_apply()));
	connect(this, SIGNAL(signal_config_style_apply()), this, SLOT(config_style_apply()));

	connect(this, SIGNAL(signal_media_set_currfileinfos(struct dispqt_currfileinfo_s *)), this, SLOT(mainwin_media_set_currfileinfos(struct dispqt_currfileinfo_s *)));
	connect(this, SIGNAL(signal_media_set_timepos(int)), this, SLOT(mainwin_media_set_timepos(int)));
	connect(this, SIGNAL(signal_action_file_openfiles(void)), this, SLOT(actfunc_file_addfiles(void)));
	//connect(this, SIGNAL(signal_option_timemode_change(unsigned int)), this, SLOT(mainwin_option_timemode_change(unsigned int)));
	connect(this, SIGNAL(signal_event_mainwindow_wakeup(void)), this, SLOT(mainwin_event_window_wakeup(void)));
	connect(this, SIGNAL(signal_event_mainwindow_statechange(void)), this, SLOT(mainwin_event_window_statechange(void)));
	connect(this, SIGNAL(signal_event_mainwindow_activate(QEvent::Type)), this, SLOT(mainwin_event_window_activate(QEvent::Type)));
}

void MainWindow::mainwin_disconnect_signals(void)
{
	disconnect(this, SIGNAL(signal_config_apply()), this, SLOT(config_apply()));
	disconnect(this, SIGNAL(signal_config_style_apply()), this, SLOT(config_style_apply()));

	disconnect(this, SIGNAL(signal_media_set_currfileinfos(struct dispqt_currfileinfo_s *)), this, SLOT(mainwin_media_set_currfileinfos(struct dispqt_currfileinfo_s *)));
	disconnect(this, SIGNAL(signal_media_set_timepos(int)), this, SLOT(mainwin_media_set_timepos(int)));
	disconnect(this, SIGNAL(signal_action_file_openfiles(void)), this, SLOT(actfunc_file_addfiles(void)));
	//disconnect(this, SIGNAL(signal_option_timemode_change(unsigned int)), this, SLOT(mainwin_option_timemode_change(unsigned int)));
	disconnect(this, SIGNAL(signal_event_mainwindow_wakeup(void)), this, SLOT(mainwin_event_window_wakeup(void)));
	disconnect(this, SIGNAL(signal_event_mainwindow_statechange(void)), this, SLOT(mainwin_event_window_statechange(void)));
	disconnect(this, SIGNAL(signal_event_mainwindow_activate(QEvent::Type)), this, SLOT(mainwin_event_window_activate(QEvent::Type)));
}

void MainWindow::closeEvent(QCloseEvent *e)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	mainwin_disconnect_signals();
	if(gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED) {
		this->mainwin_set_transparent(false, true);
		if(gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_RESTORE)
			funcbit_enable(gcfg->transparent_control, DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED);
	}
	this->mainwin_geometry_save();
	mpxplay_dispqt_main_clean();
	if(gcfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO)
	{
		funcbit_disable(gcfg->video_control, DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO);
		createVideo(this);
		funcbit_enable(gcfg->video_control, DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO);
	}
	QMainWindow::closeEvent(e);
}

void MainWindow::CloseWindowTriggeredfromExternal(void)
{
	this->action_file_exit->activate(QAction::Trigger);
}

void MainWindow::CloseWindowInternal(void)
{
	mpxplay_dispqt_main_clean();
	mainwin_disconnect_signals();
	if(this->is_mainwin_on_video || (this->qt_video_player && this->qt_video_player->video_is_fullscreen()))
		this->showMinimized();
	mpxplay_playcontrol_pause(&mvps, 1, 0);
	this->close();
}

void MainWindow::exit_handler(QPrivateSignal signum)
{
	//pds_threads_sleep(1000);
}

void MainWindow::exit_handler_commit(QSessionManager &sessman)
{
    //mpxplay_dispqt_main_clean();
    //mpxplay_dispqt_configini_save_to_file();
	//pds_threads_sleep(1000);
	sessman.release();
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
	emit this->signal_video_mainwin_wakeup(false, false);
	if((this->width() < (QApplication::desktop()->screenGeometry().width()) - 10) && (this->height() < (QApplication::desktop()->screenGeometry().height() - 10)))
		this->mainwin_geometry_save();
	QMainWindow::resizeEvent(event);
}

void MainWindow::moveEvent(QMoveEvent *event)
{
	emit this->signal_video_mainwin_wakeup(false, false);
	if((this->width() < (QApplication::desktop()->screenGeometry().width()) - 10) && (this->height() < (QApplication::desktop()->screenGeometry().height() - 10)))
		this->mainwin_geometry_save();
	QMainWindow::moveEvent(event);
}

bool MainWindow::event(QEvent *event)
{
	switch(event->type())
	{
		case QEvent::Enter:
			emit this->signal_event_mainwindow_wakeup();
			break;
		case QEvent::WindowStateChange:
			emit this->signal_event_mainwindow_statechange();
			break;
		case QEvent::WindowDeactivate:
			if(this->mainwin_opacity_forbidd)
				break;
		case QEvent::WindowActivate:
			if(!this->is_mainwin_on_video && !(this->gui_config->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED))
				emit this->signal_event_mainwindow_activate(event->type());
			break;
		default:
			if (event->type() == QWinEvent::CompositionChange || event->type() == QWinEvent::ColorizationChange) {
				emit this->signal_config_style_apply();
				mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "EVENT comp %3d", event->type());
			}
			break;
	}

	return QMainWindow::event(event);
}

void MainWindow::mainwin_event_window_wakeup(void)
{
	bool lock_success = this->mutex_mainwindow.tryLock(DISPQT_MUTEX_TIMEOUT);
	//mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "ENTER");
	this->video_fullscreen_mainwin_wakeup(false, true);
	if(this->video_controlbar)
		this->video_controlbar->videoctrlbar_check_show(-1, -1);
	if(lock_success)
		this->mutex_mainwindow.unlock();
}

void MainWindow::mainwin_event_window_statechange(void)
{
	bool lock_success = this->mutex_mainwindow.tryLock(DISPQT_MUTEX_TIMEOUT);
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	if(!(this->windowState() & Qt::WindowMaximized)){
		int size_y = gcfg->mainwin_size_y;
		if(!(gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR) && (gcfg->editor_flags & DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED)) {
			if((size_y - gcfg->editor_size_y)> DISPQT_MAINWIN_SIZEY_BASE)
				size_y -= gcfg->editor_size_y;
			funcbit_disable(gcfg->editor_flags, DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED);
		} else if((gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR) && !(gcfg->editor_flags & DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED)) {
			size_y += gcfg->editor_size_y;
			funcbit_enable(gcfg->editor_flags, DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED);
		}
		gcfg->mainwin_state = this->windowState();
		gcfg->mainwin_size_y = size_y;
		this->mainwin_geometry_restore();
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "EVENT resize");
	}
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "EVENT state ov:%d w:%4d h:%4d s:%8.8X", (int)this->is_mainwin_on_video, this->width(), this->height(), (int)this->windowState());
	if(lock_success)
		this->mutex_mainwindow.unlock();
}

void MainWindow::mainwin_event_window_activate(QEvent::Type event_type)
{
	bool lock_success = this->mutex_mainwindow.tryLock(DISPQT_MUTEX_TIMEOUT / 2);
	if(lock_success){
		struct mmc_dispqt_config_s *gcfg = this->gui_config;
		if((!!(gcfg->editor_flags & DISPQT_CONFIG_EDITORFLAG_TRANSLUCENT_INACTIVE)) != (!!(gcfg->editor_flags & DISPQT_CONFIG_EDITORFLAG_TRANSLUCENT_INWINDOW)))
			this->PlaylistEditor->editor_config_style_onvideo_switch(false);
		mainwindow_opacity_shotwindowopacitytimer((event_type == QEvent::WindowDeactivate)? gcfg->mainwin_opacity_inactive : gcfg->mainwin_opacity_general);
		this->mutex_mainwindow.unlock();
	}
}

//------------------------------------------------------------------------------------------

unsigned long mpxplay_dispqt_mainwindow_keypress_convert(QKeyEvent *event)
{
	if(!event)
		return 0;
	QString qs = event->text();
	const ushort *u16_str = qs.utf16();
	QByteArray ascii_ba = qs.toLatin1();
	char *ascii_str = ascii_ba.data();
	unsigned int win32_keymoders = 0, dos_scancode;
	Qt::KeyboardModifiers qt_keymoders = event->modifiers();

	if(qt_keymoders & Qt::ShiftModifier)
		win32_keymoders |= SHIFT_PRESSED;
	if(qt_keymoders & Qt::ControlModifier)
		win32_keymoders |= RIGHT_CTRL_PRESSED;
	if(qt_keymoders & Qt::AltModifier)
		win32_keymoders |= RIGHT_ALT_PRESSED;
	if(qt_keymoders & Qt::KeypadModifier)
		win32_keymoders |= NUMLOCK_ON;

	dos_scancode = newfunc_keyboard_winkey_to_extkey(win32_keymoders, event->nativeVirtualKey(), ascii_str[0]);
	//mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "mod:%8.8X wm:%2X scan:%8.8X virt:%8.8X a:%2x", (unsigned int)qt_keymoders, win32_keymoders, dos_scancode, event->nativeVirtualKey(), ascii_str[0]);
	return PDS_KEYCODE_PUT_MERGE(u16_str[0], dos_scancode);
}

static void mpxplay_dispqt_mainwindow_keypress_push(QKeyEvent *event, unsigned long keycode)
{
	if(!event)
		return;
	int count = event->count();
	if(keycode)
		while(count--)
			pds_keyboard_push_keycode(keycode);
	event->accept();
}

unsigned long MainWindow::mainwin_keypresscode_catch(unsigned long keycode)
{
	if(!keycode)
		return keycode;
	struct mmc_dispqt_config_s *gcfg = this->gui_config;

	if((gcfg->video_control & DISPQT_CONFIG_VIDEOCTRL_POPUP_MAINWIN_BY_KEYS) && this->is_mainwin_on_video && mpxplay_keyboard_check_editor_key(PDS_KEYCODE_GET_EXTKEY(keycode)))
		emit this->signal_video_mainwin_wakeup(true, false);

	unsigned int extkey = PDS_KEYCODE_GET_EXTKEY(keycode);
	if(extkey == kb[135].c){ // TAB
		const unsigned long both_sides_mask = DISPQT_CONFIG_EDITORFLAG_SHOWPANEL_LEFT | DISPQT_CONFIG_EDITORFLAG_SHOWPANEL_RIGHT;
		if((gcfg->editor_flags & both_sides_mask) != both_sides_mask) {
			//this->mainwindow_set_focus();
			keycode = 0;
		}
	} else if(((extkey == KEY_ESC) || (extkey == kb[237].c)) && (gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED)) { // ESC or alt-Enter
		this->mainwin_set_transparent(false, false);
		keycode = 0;
	}

	return keycode;
}

void MainWindow::mainwin_handle_keypresscode(unsigned long keycode)
{
	keycode = mainwin_keypresscode_catch(keycode);
	if(keycode)
		pds_keyboard_push_keycode(keycode);
}

void MainWindow::handle_keypressevent(QKeyEvent *event)
{
	if((event->key() == Qt::Key_Escape) && !mpxplay_control_keyboard_get_topfunc() && (this->is_mainwin_on_video || (this->qt_video_player && this->qt_video_player->video_is_fullscreen()))) {
		emit this->qt_video_player->signal_video_switch_fullscreen();
		if((playcontrol & PLAYC_RUNNING) && (this->gui_config->video_control & DISPQT_CONFIG_VIDEOCTRL_FULLSCREEN_ESC_PAUSE))
			this->action_play_start->activate(QAction::Trigger);
		event->accept();
	} else {
		unsigned long keycode = mpxplay_dispqt_mainwindow_keypress_convert(event);
		if(keycode) {
			keycode = this->mainwin_keypresscode_catch(keycode);
			if(keycode)
				mpxplay_dispqt_mainwindow_keypress_push(event, keycode);
			else
				event->accept();
		}
	}
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
	this->handle_keypressevent(event);
}

//------------------------------------------------------------------------------------------

void MainWindow::mainwin_handle_mousepress_skip_or_seek_event(QMouseEvent *event)
{
    this->mainwin_mousepress_button = Qt::NoButton;
    this->timer_mainwin_mousepress->stop();

	switch(event->type())
	{
		case QEvent::MouseButtonPress:
			this->timer_mainwin_mousepress->start(DISPQT_MAINWIN_MOUSEPRESS_STARTTIME);
			this->mainwin_mousepress_button = event->button();
			break;
		case QEvent::MouseButtonRelease:
			if(!this->timer_mainwin_mousepress_repeat->isActive()){
				if(event->button() & Qt::MiddleButton){        // skip back like CD
					this->mainwin_handle_keypresscode(kb[22].c);
				}else if(event->button() & Qt::RightButton){   // skip forward
					this->mainwin_handle_keypresscode(kb[21].c);
				}
			}
			break;
	}
	this->timer_mainwin_mousepress_repeat->stop();
    event->accept();
}

void MainWindow::mainwin_handle_mousepress_timer(void)
{
	if(!this->timer_mainwin_mousepress_repeat->isActive()){
		this->timer_mainwin_mousepress->stop();
		this->timer_mainwin_mousepress_repeat->start();
	}
	if(mainwin_mousepress_button & Qt::MiddleButton){        // KeyRewind1
		this->mainwin_handle_keypresscode(kb[0].c);
	}else if(mainwin_mousepress_button & Qt::RightButton){   // KeyForward1
		this->mainwin_handle_keypresscode(kb[2].c);
	}
}

//------------------------------------------------------------------------------------------
void MainWindow::mainwin_set_style(void)
{
    this->is_composition_enabled = QtWin::isCompositionEnabled();
	if(this->mainwin_is_translucent_enabled()) {
        QtWin::extendFrameIntoClientArea(this, -1, -1, -1, -1);
        setAttribute(Qt::WA_TranslucentBackground, true);
        setAttribute(Qt::WA_NoSystemBackground, false);
        setStyleSheet("MainWindow { background: transparent}");
    } else {
        QtWin::resetExtendedFrame(this);
        setAttribute(Qt::WA_TranslucentBackground, false);
        setStyleSheet(QString());
    }
}

void MainWindow::mainwindow_set_always_on_top(bool enable)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	//this->setUpdatesEnabled(false);  // FIXME: ???
	Qt::WindowFlags curr_flags = this->windowFlags(), new_flags, mod_flags = (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
	if(enable)
		new_flags = curr_flags | mod_flags;
	else
		new_flags = curr_flags & ~mod_flags;
	if(!(curr_flags ^ new_flags))
		this->setWindowFlags(new_flags ^ mod_flags);
	if(gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED) {
		funcbit_enable(new_flags, Qt::WindowTransparentForInput);
		/*if(gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_FRAMELESS) { // FIXME: doesn't work
			QtWin::resetExtendedFrame(this);
			funcbit_enable(new_flags, (Qt::FramelessWindowHint));
		}*/
	} else {
		funcbit_disable(new_flags, Qt::WindowTransparentForInput);
		/*if((gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_FRAMELESS) && (new_flags & Qt::FramelessWindowHint)) {
			funcbit_disable(new_flags, (Qt::FramelessWindowHint));
			mainwin_set_style();
		}*/
	}
	this->setWindowFlags(new_flags);
#ifdef Q_OS_WIN
	if(!enable)
		SetWindowPos((HWND)this->winId(), ((enable)? HWND_TOPMOST : HWND_NOTOPMOST), 0, 0, 0, 0,  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
	else
	    pds_threads_sleep(0);
#endif
	//this->setUpdatesEnabled(true);
	this->show();
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "mainwindow_set_always_on_top e:%d cf:%8.8X nf:%8.8X", (int)enable, (int)curr_flags, (int)new_flags);
}

void MainWindow::mainwin_set_transparent(bool enable, bool initial)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	unsigned long curr_mainwin_control = gcfg->mainwin_control;
	gcfg->mainwin_state = this->windowState() & ~((unsigned int)Qt::WindowMinimized);
    if(enable) {
    	funcbit_enable(gcfg->transparent_control, DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED);
    	if(this->qt_video_player) {
    		if(!initial) {
    			if(this->qt_video_player->video_is_fullscreen())
    				funcbit_enable(gcfg->video_control, DISPQT_CONFIG_VIDEOCTRL_FULLSCREEN_FROM_TRANSP);
    			else
    				funcbit_disable(gcfg->video_control, DISPQT_CONFIG_VIDEOCTRL_FULLSCREEN_FROM_TRANSP);
    		}
    		emit this->qt_video_player->signal_video_set_fullscreen(false);
    	}
    	gcfg->mainwin_control = (gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRLS_COPYMASK_TRANSCTRL) | (gcfg->mainwin_control & DISPQT_CONFIG_TRANSCTRLS_COPYMASK_MAINWINCTRL);
    	this->config_apply();
    	this->prev_mainwin_control = curr_mainwin_control;
    	mainwindow_opacity_setwindowopacity(gcfg->mainwin_opacity_transparent);
    	setAttribute(Qt::WA_TransparentForMouseEvents, enable);
    	this->mainwin_geometry_save();
    	this->mainwindow_set_always_on_top(enable);
    	if((gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_AUTOMAXI) && !(gcfg->mainwin_state & Qt::WindowMaximized)) {
    		funcbit_enable(gcfg->mainwin_state, Qt::WindowMaximized);
    		this->setWindowState((Qt::WindowStates)gcfg->mainwin_state);
    	}
    } else {
    	funcbit_disable(gcfg->transparent_control, DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED);
    	funcbit_disable(gcfg->mainwin_state, Qt::WindowMaximized);
    	mainwindow_opacity_setwindowopacity(gcfg->mainwin_opacity_general);
    	this->setWindowState((Qt::WindowStates)gcfg->mainwin_state);
    	setAttribute(Qt::WA_TransparentForMouseEvents, enable);
    	this->mainwindow_set_always_on_top((gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_ALWAYS_ON_TOP)? true : false);
    	gcfg->mainwin_control = this->prev_mainwin_control;
    	this->prev_mainwin_control = curr_mainwin_control;
    	this->config_apply();
    	this->mainwin_geometry_restore();
    	mpxplay_debugf(MPXPLAY_DEBUG_TRANSOUT, "TC:%8.8X VC:%8.8X", gcfg->transparent_control, gcfg->video_control);
    	if(((gcfg->transparent_control & DISPQT_CONFIG_TRANSCTRL_EXIT_TO_FULLVIDEO) || (gcfg->video_control & DISPQT_CONFIG_VIDEOCTRL_FULLSCREEN_FROM_TRANSP)) && this->qt_video_player)
    		emit this->qt_video_player->signal_video_switch_fullscreen();
    }
}

void MainWindow::mainwin_geometry_resize(int w, int h)
{
	this->mainwin_gsave_lock = true;
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	int max_size_y = QApplication::desktop()->screenGeometry().height() - this->y() - 50;
	if(h > max_size_y)  // correct height if it's out of the screen
		h = max_size_y;
	this->resize(w, h);
	gcfg->mainwin_size_x = this->width();
	gcfg->mainwin_size_y = this->height();
	this->mainwin_gsave_lock = false;
}

void MainWindow::mainwin_geometry_move(int x, int y)
{
	this->mainwin_gsave_lock = true;
	this->move(x, y);
	this->mainwin_gsave_lock = false;
}

void MainWindow::mainwin_geometry_save(void)
{
	if(this->mainwin_gsave_lock)
		return;
	this->mainwin_gsave_lock = true;
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	gcfg->mainwin_state = this->windowState() & ~((unsigned int)Qt::WindowMinimized);
	if(!(gcfg->mainwin_state & (unsigned int)Qt::WindowMaximized)){
		gcfg->mainwin_pos_x = this->x();
		gcfg->mainwin_pos_y = this->y();
		gcfg->mainwin_size_x = this->width();
		gcfg->mainwin_size_y = this->height();
		if(gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR)
			gcfg->editor_size_y = PlaylistEditor->height();
	}
	this->mainwin_gsave_lock = false;
}

void MainWindow::mainwin_geometry_restore(bool chk_maxi)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	this->mainwin_gsave_lock = true;
	this->setWindowState((Qt::WindowStates)gcfg->mainwin_state);
	this->mainwin_gsave_lock = false;
	if(!chk_maxi || !(gcfg->mainwin_state & (unsigned int)Qt::WindowMaximized)){
		if(gcfg->mainwin_size_x < 20)
			gcfg->mainwin_size_x = DISPQT_MAINWIN_INITSIZE_X;
		if(gcfg->mainwin_size_y < 20)
			gcfg->mainwin_size_y = DISPQT_MAINWIN_INITSIZE_Y;
		this->mainwin_geometry_resize(gcfg->mainwin_size_x, gcfg->mainwin_size_y);
		if((gcfg->mainwin_pos_x >= 0) && (gcfg->mainwin_pos_y >= 0))
			this->mainwin_geometry_move(gcfg->mainwin_pos_x, gcfg->mainwin_pos_y);
	}
}

void MainWindow::mainwindow_set_focus(void)
{
	this->setFocus();//Qt::ActiveWindowFocusReason);
	if((this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR) && this->PlaylistEditor)
		this->PlaylistEditor->set_default_focus(mvps.psie);
}

bool MainWindow::mainwin_is_translucent_enabled(void)
{
	return ((this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT) && this->is_composition_enabled)? true : false;
}

bool MainWindow::mainwin_widget_exists(enum dispqt_mainwin_widget_ids wid_id)
{
	if(wid_id >= DISPQT_MAINWIN_WIDGET_MAX)
		return false;
	struct dispqt_cfgwinctrl_to_widgetnum_s *dmwp = &dispqt_mainwin_widgetlist[wid_id];
	unsigned long mainwin_ctrl = this->gui_config->mainwin_control;
	unsigned long video_ctrl = this->gui_config->video_control;
	if((!dmwp->winctrl_bit || (mainwin_ctrl & dmwp->winctrl_bit)) && (!dmwp->videoctrl_bit || (video_ctrl & dmwp->videoctrl_bit)))
		return true;
	return false;
}

int MainWindow::mainwin_widget_index(enum dispqt_mainwin_widget_ids wid_id)
{
	struct dispqt_cfgwinctrl_to_widgetnum_s *dmwp = &dispqt_mainwin_widgetlist[0];
	unsigned long mainwin_ctrl = this->gui_config->mainwin_control;
	unsigned long video_ctrl = this->gui_config->video_control;
	int pos = 0;

	do{
		if(dmwp->widgetnum == wid_id)
			break;
		if((!dmwp->winctrl_bit || (mainwin_ctrl & dmwp->winctrl_bit)) && (!dmwp->videoctrl_bit || (video_ctrl & dmwp->videoctrl_bit)))
			pos++;
		dmwp++;
	} while(dmwp->winctrl_bit);
	return pos;
}

int MainWindow::mainwin_widget_stretch(enum dispqt_mainwin_widget_ids wid_id)
{
	if(wid_id >= DISPQT_MAINWIN_WIDGET_MAX)
		return 0;
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	if((gcfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO) && (gcfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO))
		return dispqt_mainwin_widgetlist[wid_id].stretch_withvideo;
	return dispqt_mainwin_widgetlist[wid_id].stretch_novideo;
}

//------------------------------------------------------------------------------------------
void MainWindow::config_apply(void)
{
	struct mmc_dispqt_config_s *cfg = this->gui_config;
	bool playfile_reopen = false;

	mainwindow_opacity_setwindowopacity((this->is_mainwin_on_video)? cfg->mainwin_opacity_onvideo_show : cfg->mainwin_opacity_general);

	// FIXME: other solutions for this?
	if(!(cfg->mainwin_control & (DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO | DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR)) && (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO))
		funcbit_enable(cfg->mainwin_control, DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO);

	if(((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_ALWAYS_ON_TOP) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_ALWAYS_ON_TOP)) && !this->is_mainwin_on_video)
		this->mainwindow_set_always_on_top((cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_ALWAYS_ON_TOP)? true : false);

	if((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_HIDE_MENU) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_HIDE_MENU)) {
		if(cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_HIDE_MENU)
			menuBar()->hide();
		else
			menuBar()->show();
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "menubar: %d", (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_HIDE_MENU));
	}

	if(cfg->selected_videoplayer_type != mpxplay_config_videoplayer_type){
		unsigned int filetype = mvps.fr_primary->filetype;
		if(this->qt_video_player)
			emit this->qt_video_player->signal_video_set_fullscreen(false);
		if(filetype & HFT_FILE_INT){
			if(funcbit_test(playcontrol,PLAYC_RUNNING)){
				mpxplay_play_start_or_pause(&mvps);
				pds_threads_sleep(200);
				funcbit_enable(playcontrol, PLAYC_STARTNEXT);
			}
			playstartframe = mvps.fr_primary->frameNum;
		}
		if(this->qt_video_player)
			this->main_layout->removeWidget(this->qt_video_player);
		if(cfg->selected_videoplayer_type == MPXPLAY_VIDEOPLAYERTYPE_NONE)
			funcbit_disable(cfg->video_control, DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO);
		else
			funcbit_enable(cfg->video_control, DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO);
		if((cfg->selected_videoplayer_type != mpxplay_config_videoplayer_type) && (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO) && ((this->prev_video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO) == (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO)))
		{
			funcbit_disable(cfg->video_control,DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO);
			createVideo(this);
			funcbit_enable(cfg->video_control,DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO);
		}
		mpxplay_config_videoplayer_type = cfg->selected_videoplayer_type;
		createVideo(this);
		if(this->qt_video_player)
			this->main_layout->insertWidget(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_VIDEO), this->qt_video_player, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_VIDEO));
		if(filetype & (HFT_FILE_INT|HFT_FILE_EXT))
			playfile_reopen = true;
	} else {
		if(this->qt_video_player && !this->is_mainwin_on_video && (this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO))
			this->main_layout->setStretch(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_VIDEO), this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_VIDEO));
	}

	if((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR))
		createSeekbar(false);

	if( (this->prev_mainwin_control & (DISPQT_CONFIG_MAINWINCTRL_SHOW_TOOLBAR | DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT))
	 != (cfg->mainwin_control & (DISPQT_CONFIG_MAINWINCTRL_SHOW_TOOLBAR | DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT))) {
		this->createToolBars(false);
	}

	if((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_EMBEDD_AVMIXER) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_EMBEDD_AVMIXER))
		createAVmixer(false);

	if(this->PlaylistEditor)
		this->PlaylistEditor->editor_config_apply(this->is_mainwin_on_video);
	if((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR))
		createEditor(false);

	if((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE))
		this->mainwin_statusbar_init();

	if(	   (this->prev_video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO) != (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO)
		|| (this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO)
	){
		this->setUpdatesEnabled(false);
		for(int i = DISPQT_MAINWIN_WIDGET_SEEKBAR; i < DISPQT_MAINWIN_WIDGET_MAX; i++) // !!! only if video is the first
			if(this->mainwin_widget_exists((dispqt_mainwin_widget_ids)i))
				this->main_layout->setStretch(this->mainwin_widget_index((dispqt_mainwin_widget_ids)i), this->mainwin_widget_stretch((dispqt_mainwin_widget_ids)i));
		this->setUpdatesEnabled(true);
	}

	if((this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT) != (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT))
		this->config_style_apply();

	if(((this->prev_video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_CONTROLBAR) != (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_CONTROLBAR)) && this->video_controlbar) {
		bool enable = (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_CONTROLBAR)? true : false;
		emit this->video_controlbar->signal_videoctrlbar_set_show(enable);
		if(enable)
			funcbit_enable(refdisp, (RDT_HEADER | RDT_BROWSER));
	}

	if(this->is_mainwin_on_video && !(cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_SHOW_MAINWIN_ON_VIDEO))
		this->mainwindow_opacity_start(true, true);

    this->action_list_replay->setChecked((playreplay)? true : false);
    this->action_list_random->setChecked((playrand)? true : false);

	this->prev_mainwin_control = cfg->mainwin_control;
	this->prev_video_control = cfg->video_control;

	if(cfg->selected_videoplayer_control != mpxplay_config_videoplayer_control)
	{
		if( (mvps.fr_primary->filetype & HFT_FILE_INT)
		 && ((cfg->selected_videoplayer_control & MPXPLAY_CONFIG_VIDEOPLAYERCONTROL_REOPEN_REQUIRED) != (mpxplay_config_videoplayer_control & MPXPLAY_CONFIG_VIDEOPLAYERCONTROL_REOPEN_REQUIRED))
		){
			playfile_reopen = true;
		}
		mpxplay_config_videoplayer_control = cfg->selected_videoplayer_control;
	}

	if(playfile_reopen)
		mvps.adone = ADONE_REOPEN;
}

void MainWindow::config_style_apply(void)
{
	bool lock_success = this->mutex_mainwindow.tryLock(DISPQT_MUTEX_TIMEOUT);
	bool lucent_enable = this->mainwin_is_translucent_enabled();
	this->mainwin_set_style();
	this->mainwin_menubar->menubar_set_style();
	if(this->mainwin_seekbar)
		this->mainwin_seekbar->mainwinseekbar_config_style_apply(lucent_enable);
	if(this->video_controlbar) {
		delete this->video_controlbar;
		this->video_controlbar = NULL;
		createVideoControlbar(true);
		funcbit_enable(refdisp, (RDT_HEADER | RDT_BROWSER));
		//emit this->video_controlbar->signal_videoctrlbar_config_style_apply(lucent_enable); // FIXME: doesn't work properly
	}
	if(this->mixer_dialog)
		emit this->mixer_dialog->signal_avdialog_config_style_apply(lucent_enable);
	else if(this->mixer_widget)
		emit this->mixer_widget->signal_avmixer_config_style_apply(lucent_enable);
	if(this->PlaylistEditor)
		this->PlaylistEditor->editor_config_style_apply(lucent_enable);
	this->mainwin_statusbar_style_apply();
	if(lock_success)
		this->mutex_mainwindow.unlock();
}

//--------------------------------------------------------------------------------------
bool MainWindow::mainwin_is_underMouse(void)
{
	int ex = QCursor::pos().x(), ey = QCursor::pos().y();
	int mxt = this->x(), myt = this->y();
	int mxb = mxt + this->width(), myb = myt + this->height();
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "UM ex:%d ey:%d y:%d mxt:%d mxb:%d myt:%d myb:%d ", ex,ey,this->y(),mxt,mxb,myt,myb);
	if((ex >= mxt) && (ex < mxb) && (ey >= myt) && (ey < myb)) // main window area
		return true;
	return false;
}

void MainWindow::video_fullscreen_mainwin_opacity_disable(bool disable)
{
	this->mainwin_opacity_forbidd = disable;
	if(this->qt_video_player) {
		this->qt_video_player->video_mouse_cursor_forbid_hide(disable);
		emit this->qt_video_player->signal_video_check_windows();
	}
	if(disable)
	    this->video_fullscreen_mainwin_wakeup(false, false);
	else
	    this->mainwindow_opacity_start(true, true);
	mpxplay_debugf(DISPQT_DEBUG_OPACITY, "video_fullscreen_mainwin_opacity_disable %d", (int) disable);
}

void MainWindow::mainwindow_opacity_setwindowopacity(long opacity_new)
{
	if((this->mainwin_opacity_curr != opacity_new) && (opacity_new >= 0)){
		bool lock_success = this->mutex_opacity.tryLock(DISPQT_MUTEX_TIMEOUT);
		mpxplay_debugf(DISPQT_DEBUG_OPACITY, "mainwindow_opacity_setwindowopacity %d->%d isa:%d ls:%d", this->mainwin_opacity_curr, opacity_new, (int)this->timer_mainwin_onvideo->isActive(), (int)lock_success);
		if(lock_success){
			if(opacity_new > DISPQT_CONFIG_MAINWIN_OPACITY_GENERAL_MAX)
				opacity_new = DISPQT_CONFIG_MAINWIN_OPACITY_GENERAL_MAX;
			this->mainwin_opacity_curr = opacity_new;
			this->setWindowOpacity((qreal)opacity_new / (qreal)DISPQT_CONFIG_MAINWIN_OPACITY_GENERAL_MAX);
			this->mutex_opacity.unlock();
		}
	}
}

// to avoid over-locking, sometimes we set opacity on timer
void MainWindow::mainwindow_opacity_shotwindowopacitytimer(long opacity_new)
{
	if(!this->is_mainwin_on_video && this->timer_mainwin_onvideo){
		mpxplay_debugf(DISPQT_DEBUG_OPACITY, "mainwindow_opacity_shotwindowopacitytimer %d->%d isa:%d", this->mainwin_opacity_curr, opacity_new, (int)this->timer_mainwin_onvideo->isActive());
		this->timer_mainwin_onvideo->stop();
		this->mainwin_opacity_target = opacity_new;
		this->timer_mainwin_onvideo->setSingleShot(true);
		this->timer_mainwin_onvideo->start();
	}
}

void MainWindow::mainwindow_opacity_timed_change(void)
{
	if(!this->timer_mainwin_onvideo)
		return;
	if(this->timer_mainwin_onvideo->isSingleShot()){
		mainwindow_opacity_setwindowopacity(this->mainwin_opacity_target);
		return;
	}
	if(!this->is_mainwin_on_video)
		return;
	if(!this->mainwin_opacity_status_showout){
		this->timer_mainwin_onvideo->setInterval(this->mainwin_opacity_showout_interval_ms);
		this->mainwin_opacity_status_showout = true;
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "OPT SH0");
		return;
	}
	if( ((this->mainwin_opacity_steps > 0) && (this->mainwin_opacity_curr > this->mainwin_opacity_target))
	 || ((this->mainwin_opacity_steps < 0) && (this->mainwin_opacity_curr < this->mainwin_opacity_target))
	) {
		this->timer_mainwin_onvideo->stop();
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "OPT STOP");
		if(this->mainwin_opacity_steps > 0)
			this->mainwindow_opacity_start(true, false); // !!! automatically restart hide timer after show
		else {
			if(this->qt_video_player)
				this->qt_video_player->set_focus();
			this->releaseKeyboard();
		}
		return;
	}
	mainwindow_opacity_setwindowopacity(this->mainwin_opacity_curr + this->mainwin_opacity_steps);
	//mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "OP timed: op:%d s:%d sh:%d hd:%d", mainwin_opacity_curr, mainwin_opacity_steps, this->gui_config->mainwin_opacity_onvideo_show, this->gui_config->mainwin_opacity_onvideo_hide);
}

bool MainWindow::mainwindow_opacity_start(bool hide, bool fast_hide)
{
	if(!this->is_mainwin_on_video || !this->timer_mainwin_onvideo)
		return false;
	this->timer_mainwin_onvideo->stop();
	struct mmc_dispqt_config_s *cfg = this->gui_config;
	if(!(cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_AUTO_HIDE_MAINWIN) && (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_SHOW_MAINWIN_ON_VIDEO))
		return false;
	int interval_next;
	if(hide){
		if((cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_SHOW_MAINWIN_ON_VIDEO) && (this->mainwin_opacity_forbidd || this->dialog_handler->is_dialog_open() || this->underMouse() || this->menuBar()->underMouse() || this->mainwin_is_underMouse()))
			return false;
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "OP hide um:%d",(int)this->underMouse());
		this->mainwin_opacity_steps = -1;
		this->mainwin_opacity_target = cfg->mainwin_opacity_onvideo_hide;
		this->mainwin_opacity_showout_interval_ms = cfg->mainwin_opacity_fadeout_time / (cfg->mainwin_opacity_onvideo_show - cfg->mainwin_opacity_onvideo_hide);
		if(fast_hide) {
			this->mainwin_opacity_status_showout = true;
			interval_next = this->mainwin_opacity_showout_interval_ms;
		} else {
			this->mainwin_opacity_status_showout = false;
			interval_next = cfg->mainwin_opacity_showkeep_time;
		}
	} else { // show
		this->mainwin_opacity_steps = +1;
		this->mainwin_opacity_target = cfg->mainwin_opacity_onvideo_show;
		this->mainwin_opacity_showout_interval_ms = cfg->mainwin_opacity_fadein_time / (cfg->mainwin_opacity_onvideo_show - cfg->mainwin_opacity_onvideo_hide);
		this->mainwin_opacity_status_showout = true;
		interval_next = this->mainwin_opacity_showout_interval_ms;
	}
	if((this->mainwin_opacity_showout_interval_ms <= 0) || (interval_next <= 0))
		return false;
	this->timer_mainwin_onvideo->setInterval(interval_next);
	this->timer_mainwin_onvideo->setSingleShot(false);
	this->timer_mainwin_onvideo->start();
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "OP timer: hide:%d ms:%d op:%d sh:%d hd:%d", (int)hide, this->mainwin_opacity_showout_interval_ms, this->mainwin_opacity_curr, cfg->mainwin_opacity_onvideo_show, cfg->mainwin_opacity_onvideo_hide );
	return true;
}

bool MainWindow::mainwindow_opacity_hide_start(void)
{
	if((this->mainwin_opacity_steps < 0) && (this->mainwin_opacity_status_showout || this->timer_mainwin_onvideo->isActive()))
		return false;
	return this->mainwindow_opacity_start(true, true);
}

void MainWindow::video_fullscreen_switch(bool full)
{
	const struct mmc_dispqt_config_s *cfg = this->gui_config;
	const bool ontop = (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_ALWAYS_ON_TOP)? true : false;
	long opacity_new = cfg->mainwin_opacity_general;
	if(full && (cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_SHOW_MAINWIN_ON_VIDEO)) {
		this->is_mainwin_on_video = true;
		if(!ontop){
			this->mainwindow_set_focus();
			this->mainwindow_set_always_on_top(true);
		}
		this->mainwindow_set_focus();
		if((cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO) && this->qt_video_player) {
			this->mainwin_video_window_size_y = this->qt_video_player->video_get_value(DispQtVideoPlayer::VideoCtrlValue_Height);
			if(this->mainwin_video_window_size_y < DISPQT_MAINWIN_SIZEY_VIDEO_MIN) {
				this->mainwin_video_window_size_y = DISPQT_MAINWIN_SIZEY_VIDEO_MIN;
				this->mainwin_geometry_resize(this->width(), this->height() + this->mainwin_video_window_size_y);
			}
			this->main_layout->setStretch(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_VIDEO), 0);
		}
		opacity_new = cfg->mainwin_opacity_onvideo_show;
		this->mainwindow_opacity_start(true, true);
	} else {
		this->timer_mainwin_onvideo->stop();
		if(full) {
			if(this->qt_video_player)
				this->qt_video_player->set_focus();
			this->hide();
			opacity_new = 0;
		} else {
			this->show();
			this->activateWindow(); // TODO: this may has unwanted side effects (see qwidget.cpp)
			this->mainwindow_set_focus();
			if((cfg->video_control & DISPQT_CONFIG_VIDEOCTRL_SHOW_MAINWIN_ON_VIDEO) && !ontop)
				this->mainwindow_set_always_on_top(ontop);
			if(cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO)
				this->main_layout->setStretch(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_VIDEO), this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_VIDEO));
		}
		this->is_mainwin_on_video = false;
	}
	mainwindow_opacity_setwindowopacity(opacity_new);
	this->mainwin_geometry_save();
	this->PlaylistEditor->editor_config_style_onvideo_switch(this->is_mainwin_on_video);
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "MAIN FS %d", (int)full);
	if(full && this->qt_video_player)
		emit this->qt_video_player->signal_video_apply_fullscreen(full);
}

void MainWindow::video_fullscreen_mainwin_wakeup(bool to_top, bool fast_hide)
{
	if(!this->is_mainwin_on_video || !(this->gui_config->video_control & DISPQT_CONFIG_VIDEOCTRL_SHOW_MAINWIN_ON_VIDEO))
		return;
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "WAKE st:%d um:%d", this->mainwin_opacity_steps, (int)this->underMouse());
	if(to_top){
		this->raise();
		//QApplication::setActiveWindow(this);
	} else if(this->qt_video_player)
		this->qt_video_player->video_mouse_cursor_show(false);  // FIXME: to_top vs. mouse_cursor
	this->mainwindow_set_focus();
	this->mainwindow_opacity_start(false, fast_hide);
}

void MainWindow::mainwin_video_check_show(int ex, int ey)
{
	bool found = false;
	if(this->video_controlbar && this->video_controlbar->videoctrlbar_check_show(ex, ey)) {
		this->mainwindow_opacity_hide_start();
		found = true;
	}
	else if(this->is_mainwin_on_video)
	{
		int mxt = this->x(), myt = this->y();
		int mxb = mxt + this->width(), myb = myt + this->height();
		if((ex >= mxt) && (ex < mxb) && (ey >= myt) && (ey < myb)){ // main window area
			this->video_fullscreen_mainwin_wakeup(true, true);
			found = true;
		} else {
			this->mainwindow_opacity_hide_start();
		}
	}
	if(this->qt_video_player)
		this->qt_video_player->video_mouse_cursor_show(!found);
	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "mainwin_video_check_show f:%d ex:%d ey:%d", (int)found, ex, ey);
}

void MainWindow::mainwin_load_files_or_dir(int sidenum, int tabnum, Mainwindow_SelectLoadType load_type)
{
	struct dispqt_loadfile_callbackdata_s *dlcs = NULL;
	struct playlist_side_info *psi;
	int i;
	QList<QUrl> urllist;
	QFileDialog fdialog(this);
	char strtmp[MAX_PATHNAMELEN];

	psi = playlist_editlist_tabpsi_get(&mvps, sidenum, tabnum);  // FIXME: direct references and calls
	if(!psi)
		return;

	if(funcbit_test(psi->editloadtype, PLL_LOCKTAB)){
		if(!this->PlaylistEditor)
			return;
		PlaylistEditorTabs *pew = this->PlaylistEditor->editor_tab_widget[psi->sidenum];
		if(pew)
			emit pew->signal_tab_head_lockedfuncmsg();
		return;
	}

	funcbit_enable(psi->editloadtype, PLL_LOCKTAB);

	switch(load_type){
		case Mainwindow_SelectLoadFiles:
			fdialog.setFileMode(QFileDialog::ExistingFiles);
			fdialog.setNameFilter(tr("All files (*.*);;Playlists (*.cue *.fpl *.m3u *.m3u8 *.mxu *.pls);;Audio files (*.aac *.ac3 *.aif *.ape *.cdw *.dts *.flac *.mka *.mp2 *.mp3 *.m4a *.mpc *.ogg *.oga *.opus *.spx *.wav *.w64 *.wma *.wv);;Video files (*.asf *.avi *.flv *.m2ts *.mkv *.mov *.mp4 *.mpg *.ogm *.ogv *.ts *.vob *.webm *.wmv)"));
			fdialog.setDirectory(QString::fromUtf8(psi->currdir));
			break;
		case Mainwindow_SelectLoadDir:
			fdialog.setFileMode(QFileDialog::Directory);
			if((psi->editsidetype & PLT_DIRECTORY) || psi->currdir[0])  // FIXME: direct references
				pds_getpath_from_fullname(strtmp, psi->currdir);
			else
				pds_getpath_nowildcard_from_filename(strtmp, &psi->sublistnames[psi->sublistlevel][0]);
			fdialog.setDirectory(QString::fromUtf8(strtmp));
			mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.exec dirname:%s curr:%s", strtmp, psi->currdir);
			break;
		case Mainwindow_SelectLoadUrl:
			fdialog.setFileMode(QFileDialog::AnyFile);
			fdialog.setOption(QFileDialog::DontUseNativeDialog, true);
			fdialog.setDirectory(tr(""));
			fdialog.setResolveSymlinks(false);
			break;
	}

	if(!fdialog.exec()){
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.exec failed");
		goto err_out_mlfd;
	}

	urllist = fdialog.selectedUrls();

	if(!urllist.size()){
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.exec !urllist.size()");
		goto err_out_mlfd;
	}

	dlcs = (struct dispqt_loadfile_callbackdata_s *)pds_malloc(sizeof(struct dispqt_loadfile_callbackdata_s));
	if(!dlcs){
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.exec !dlcs");
		goto err_out_mlfd;
	}

	dlcs->sidenum = sidenum;
	dlcs->tabnum = tabnum;
	dlcs->load_type = load_type;
	dlcs->nb_filenames = urllist.size();
	dlcs->filenames = (char **)pds_calloc(dlcs->nb_filenames, sizeof(char *));
	if(!dlcs->filenames){
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.exec !dlcs->filenames");
		goto err_out_mlfd;
	}

	for(i = 0; i < dlcs->nb_filenames; i++)
	{
		QString fileName = urllist.at(i).toString(QUrl::None);
		QByteArray qba = fileName.toUtf8();
		char *filename = qba.data();
		int len;
		if(!filename || !filename[0])
			continue;
		if(pds_strlicmp(filename, (char *)"file://") == 0){  // TODO:
			filename += sizeof("file://");
			pds_strcpy(strtmp, filename);
			filename = &strtmp[0];
			pds_filename_conv_slashes_to_local(filename);
		}
		len = pds_strlen(filename) + 1;
		dlcs->filenames[i] = (char *)pds_malloc(len);
		if(!dlcs->filenames[i])
			goto err_out_mlfd;
		pds_memcpy(dlcs->filenames[i], filename, len);
	}

	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.exec mpxplay_dispqt_mainthread_callback_init");
	mpxplay_dispqt_mainthread_callback_init((void *)&mpxplay_dispqt_mainwindow_apply_loadfiles_callback, (void *)dlcs, 0);

	return;

err_out_mlfd:
	if(dlcs){
		if(dlcs->filenames){
			for(i = 0; i < dlcs->nb_filenames; i++)
				if(dlcs->filenames[i])
					pds_free(dlcs->filenames[i]);
			pds_free(dlcs->filenames);
		}
		free(dlcs);
	}
	funcbit_disable(psi->editloadtype, PLL_LOCKTAB);
}

static void mpxplay_dispqt_mainwindow_apply_loadfiles_callback(void *passdata)
{
	struct dispqt_loadfile_callbackdata_s *dlcs = (struct dispqt_loadfile_callbackdata_s *)passdata;
	struct playlist_side_info *psi;
	int i;
	char strtmp[MAX_PATHNAMELEN];

	if(!dlcs)
		return;
	if(!dlcs->nb_filenames || !dlcs->filenames)
		goto err_out_maoc;
	psi = playlist_editlist_tabpsi_get(&mvps, dlcs->sidenum, dlcs->tabnum);
	if(!psi)
		goto err_out_maoc;

	if(dlcs->sidenum < 0){  // !!! Open files (called from File menu)
		playlist_loaddir_switch_to_playlist(psi);  // FIXME: disable jukebox with opening file/list?
		mpxplay_playlist_sideclear_entries(psi);
		playlist_disable_side_full(psi);
		mpxplay_playlist_sideclear_sidetype(psi);
		psi->currdir[0]=0;
	}

	mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fdialog.urllist.size: %d", dlcs->nb_filenames);
	for(i = 0; i < dlcs->nb_filenames; i++){
		struct playlist_entry_info *pei_begin;
		char *filename = dlcs->filenames[i];
		bool empty;
		if(!filename || !filename[0])
			continue;
		mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "fileName: %s", filename);
		if(dlcs->load_type == Mainwindow_SelectLoadDir){
			int len=pds_strcpy(strtmp, filename);
			len+=pds_strcpy(&strtmp[len], (char *)PDS_DIRECTORY_SEPARATOR_STR);
			len+=pds_strcpy(&strtmp[len], (char *)PDS_DIRECTORY_ALLDIR_STR);
			len+=pds_strcpy(&strtmp[len], (char *)PDS_DIRECTORY_SEPARATOR_STR);
			pds_strcpy(&strtmp[len], (char *)PDS_DIRECTORY_ALLFILE_STR);
			filename = &strtmp[0];
		}
		pei_begin = psi->lastentry + 1;
		empty = (psi->lastentry < psi->firstentry)? true : false;
		if((dlcs->load_type != Mainwindow_SelectLoadUrl) && ((dlcs->load_type == Mainwindow_SelectLoadDir) || playlist_loadlist_check_extension(filename))){
			unsigned int result = playlist_buildlist_one(psi,filename,(dlcs->load_type == Mainwindow_SelectLoadDir)? PLL_DIRSCAN : 0,NULL,NULL);
			if(empty && result){
				mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "playlist_loadsub_setnewinputfile lt:%d ms:%d : %s", (int)dlcs->load_type, (int)Mainwindow_SelectLoadDir, filename);
				playlist_loadsub_setnewinputfile(psi, filename, (dlcs->load_type == Mainwindow_SelectLoadDir)? PLL_DIRSCAN:PLL_LOADLIST);
				mpxplay_debugf(DISPQT_DEBUG_OUTPUT, "playlist_loadsub_setnewinputfile sub:%s", &psi->sublistnames[psi->sublistlevel][0]);
			}
		} else {
			struct playlist_entry_info *pei = playlist_editlist_add_entry(psi);
			playlist_editlist_add_filename(psi, pei, filename);
			if(empty)
				playlist_enable_side(psi);
		}
		if(empty){
			if(dlcs->load_type == Mainwindow_SelectLoadUrl){
				psi->currdir[0] = 0;
				psi->sublistnames[0][0] = 0;
			}else if(dlcs->load_type == Mainwindow_SelectLoadDir)
				pds_strcpy(psi->currdir, dlcs->filenames[i]);
			else
				pds_getpath_from_fullname(psi->currdir, dlcs->filenames[i]);
		}
		playlist_chkfile_start_norm(psi, pei_begin);
	}

	if(dlcs->sidenum < 0){  // !!! Open files (called from File menu)
		playlist_editorhighline_set_nocenter(psi, psi->firstsong);
		playlist_newsong_enter(&mvps, psi);
	}

	if(psi->tabnum == mvps.editorsides_selected_tab[psi->sidenum])
		funcbit_enable(refdisp, RDT_EDITOR);
	else
		funcbit_enable(refdisp, RDT_TABINFOS);
	if(psi == mvps.psip)
	  refdisp|=RDT_BROWSER;

err_out_maoc:
	funcbit_disable(psi->editloadtype, PLL_LOCKTAB);

	if(dlcs->filenames){
		for(i = 0; i < dlcs->nb_filenames; i++)
			if(dlcs->filenames[i])
				pds_free(dlcs->filenames[i]);
		pds_free(dlcs->filenames);
	}
	pds_free((void *)dlcs);
}

//------------------------------------------------------------------------------------------
void MainWindow::actfunc_file_addfiles(void) { mainwin_load_files_or_dir(-1, -1, Mainwindow_SelectLoadFiles); }
void MainWindow::actfunc_file_adddir(void) { mainwin_load_files_or_dir(-1, -1, Mainwindow_SelectLoadDir); }
void MainWindow::actfunc_file_addurl(void) { mainwin_load_files_or_dir(-1, -1, Mainwindow_SelectLoadUrl); }
void MainWindow::actfunc_file_info(void) { pds_pushkey(kb[175].c); }
void MainWindow::actfunc_file_edit(void) { pds_pushkey(kb[176].c); }
void MainWindow::actfunc_file_copy(void) { pds_pushkey(kb[157].c); }
void MainWindow::actfunc_file_move(void) { pds_pushkey(kb[158].c); }
void MainWindow::actfunc_file_rename(void) { pds_pushkey(kb[159].c); }
void MainWindow::actfunc_file_del(void) { pds_pushkey(kb[156].c); }

void MainWindow::play_start_or_pause() { mpxplay_play_start_or_pause(&mvps); }
void MainWindow::play_stop() { mpxplay_stop_and_clear(&mvps, 0); }
void MainWindow::play_skip_back() { pds_pushkey(kb[20].c); }
void MainWindow::play_skip_forward() { pds_pushkey(kb[21].c); }
void MainWindow::play_seek_back() { pds_pushkey(kb[0].c); }
void MainWindow::play_seek_forward() { pds_pushkey(kb[2].c); }
void MainWindow::play_seek_faster_back() { pds_pushkey(kb[4].c); }
void MainWindow::play_seek_faster_forward() { pds_pushkey(kb[6].c); }
void MainWindow::actfunc_play_pausenext(void) { pds_pushkey(kb[64].c); }
void MainWindow::actfunc_play_highlight(void) { pds_pushkey(kb[65].c); }
void MainWindow::actfunc_play_highlight_movie(int frame) { action_play_highlight->setIcon(QIcon(actmovie_play_highlight->currentPixmap())); }

void MainWindow::actfunc_list_gotocurr(void) { pds_pushkey(kb[132].c); }
void MainWindow::actfunc_list_comparedirs(void) {pds_pushkey(kb[199].c); }
void MainWindow::actfunc_list_index_insert(void) { pds_pushkey(kb[132].c); pds_pushkey(kb[202].c);}
void MainWindow::actfunc_list_index_remove(void) { pds_pushkey(kb[203].c); }
void MainWindow::actfunc_list_replay(void) { pds_pushkey(kb[60].c); }
void MainWindow::actfunc_list_random(void) { pds_pushkey(kb[62].c); }
void MainWindow::actfunc_list_subdirlist(void) { pds_pushkey(kb[140].c); }
void MainWindow::actfunc_list_id3search(void) { pds_pushkey(kb[238].c); }

void MainWindow::actfunc_view_editorsw(void)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	funcbit_inverse(gcfg->mainwin_control, DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR);
	if(!(gcfg->mainwin_control & (DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO | DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR)) && (gcfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO)){
		funcbit_enable(gcfg->mainwin_control, DISPQT_CONFIG_MAINWINCTRL_SHOW_VIDEO);
		this->main_layout->setStretch(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_VIDEO), this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_VIDEO));
	}
	createEditor(false);
	this->prev_mainwin_control = gcfg->mainwin_control;
}

void MainWindow::actfunc_options_configure(void)
{
	this->prev_mainwin_control = this->gui_config->mainwin_control;
	this->prev_video_control = this->gui_config->video_control;
	DispQtConfigWindow *cfgwin = new DispQtConfigWindow((MainWindow *)this, this);
}

void MainWindow::actfunc_options_commandermode(void) { mpxplay_dispqt_mainthread_callback_init((void *)playlist_commandermode_switch, (void *)&mvps, 0); }
void MainWindow::actfunc_options_ftp_connect(void) { mpxplay_dispqt_mainthread_callback_init((void *)mpxplay_diskdrive_openftp_connect, (void *)mvps.psie, 0); }
void MainWindow::actfunc_options_ftp_disconnect(void) { mpxplay_dispqt_mainthread_callback_init((void *)mpxplay_diskdrive_openftp_disconnect, (void *)mvps.psie, 0); }

void MainWindow::actfunc_options_avmixer(void)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	funcbit_inverse(gcfg->mainwin_control, DISPQT_CONFIG_MAINWINCTRL_SHOW_AVMIXER);
	createAVmixer(false);
	this->prev_mainwin_control = gcfg->mainwin_control;
}

void MainWindow::actfunc_options_videofs(void) // !!! has double function
{
	if(this->gui_config->transparent_control & DISPQT_CONFIG_TRANSCTRL_DESKTOPTRANS_ENABLED)
		this->mainwin_set_transparent(false, false);
	else if(this->qt_video_player)
		emit this->qt_video_player->signal_video_switch_fullscreen();
}
void MainWindow::actfunc_options_mainwin_transparent(void) { this->mainwin_set_transparent(true, false); }

void MainWindow::actfunc_help_help(void) { pds_pushkey(kb[230].c); }
void MainWindow::actfunc_help_about()
{
	QMessageBox::about(this, tr("About MMC"),
		tr("MMC - Mpxplay Multimedia Commander v") + tr(DISPQT_MMC_VERSION_STRING) +
		tr("\n  build date: ") + tr(__DATE__) + tr("  ") + tr(__TIME__) +
		tr("\n  compiler: MinGW-w64 ") + tr(__VERSION__) + tr(" "
#ifdef MPXPLAY_ARCH_X64
		"x64"
#else
		"x86"
#endif
		) +
#ifdef MPXPLAY_LINK_ORIGINAL_FFMPEG
		tr("\n  decoder: FFmpeg v") + tr(FFMPEG_VERSION) +
#endif
		tr("\n  author: Attila Padar - PDSoft \n"
		"  web : http://mpxplay.sourceforge.net \n"
		"  email: mpxplay@freemail.hu"));
}

void MainWindow::createActions()
{
	action_file_openfiles = new QAction(QIcon(":/images/open.png"), tr("&Open files..."), this);
	action_file_openfiles->setShortcut(QKeySequence(tr("Ctrl+O")));
	action_file_openfiles->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_openfiles, SIGNAL(triggered()), this, SLOT(actfunc_file_addfiles()));

	action_file_opendir = new QAction(tr("&Open directory..."), this);
	connect(action_file_opendir, SIGNAL(triggered()), this, SLOT(actfunc_file_adddir()));

	action_file_openurl = new QAction(tr("&Open url..."), this);
	connect(action_file_openurl, SIGNAL(triggered()), this, SLOT(actfunc_file_addurl()));

	action_file_info = new QAction(QIcon(":/images/info.png"), tr("&File properties"), this);
	action_file_info->setShortcut(QKeySequence(tr("F3")));
	action_file_info->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_info, SIGNAL(triggered()), this, SLOT(actfunc_file_info()));

	action_file_edit = new QAction(tr("&Edit ID3 info"), this);
	action_file_edit->setShortcut(QKeySequence(tr("F4")));
	action_file_edit->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_edit, SIGNAL(triggered()), this, SLOT(actfunc_file_edit()));

	action_file_rename = new QAction(tr("&Rename file / dir (by ID3)"), this);
	action_file_rename->setShortcut(QKeySequence(tr("Ctrl+E")));
	action_file_rename->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_rename, SIGNAL(triggered()), this, SLOT(actfunc_file_rename()));

	action_file_copy = new QAction(tr("&Copy file / dir on disk"), this);
	action_file_copy->setShortcut(QKeySequence(tr("Alt+F5")));
	action_file_copy->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_copy, SIGNAL(triggered()), this, SLOT(actfunc_file_copy()));

	action_file_move = new QAction(tr("&Move file / dir on disk"), this);
	action_file_move->setShortcut(QKeySequence(tr("Alt+F6")));
	action_file_move->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_move, SIGNAL(triggered()), this, SLOT(actfunc_file_move()));

	action_file_del = new QAction(tr("&Delete file / dir from disk"), this);
	action_file_del->setShortcut(QKeySequence(tr("Alt+F8")));
	action_file_del->setShortcutContext(Qt::WidgetShortcut);
	connect(action_file_del, SIGNAL(triggered()), this, SLOT(actfunc_file_del()));

	action_file_exit = new QAction(tr("E&xit"), this);
	action_file_exit->setShortcut(QKeySequence(tr("ESC")));
	action_file_exit->setShortcutContext(Qt::WidgetShortcut);
	action_file_exit->setToolTip(tr("Exit the application (ESC)"));
	connect(action_file_exit, SIGNAL(triggered()), this, SLOT(CloseWindowInternal()));

	action_play_start = new QAction(QIcon(":/images/player_play.png"), tr("&Play / Pause"), this);
	action_play_start->setShortcut(QKeySequence(tr("P")));
	action_play_start->setShortcutContext(Qt::WidgetShortcut);
	action_play_start->setToolTip(tr("Start/Pause playing ('P')" ));
	connect(action_play_start, SIGNAL(triggered()), this, SLOT(play_start_or_pause()));

	action_play_stop = new QAction(QIcon(":/images/player_stop.png"), tr("&Stop playing"), this);
	action_play_stop->setShortcut(QKeySequence(tr("S")));
	action_play_stop->setShortcutContext(Qt::WidgetShortcut);
	action_play_stop->setToolTip(tr("Stop playing ('S')"));
	connect(action_play_stop, SIGNAL(triggered()), this, SLOT(play_stop()));

	action_play_skipback = new QAction(QIcon(":/images/player_skip_back.png"), tr("&Skip back"), this);
	action_play_skipback->setShortcut(QKeySequence(tr("-")));
	action_play_skipback->setShortcutContext(Qt::WidgetShortcut);
	action_play_skipback->setToolTip(tr("Skip back ('-')" ));
	connect(action_play_skipback, SIGNAL(triggered()), this, SLOT(play_skip_back()));

	action_play_skipforward = new QAction(QIcon(":/images/player_skip_forward.png"), tr("&Skip forward"), this);
	action_play_skipforward->setShortcut(QKeySequence(tr("+")));
	action_play_skipforward->setShortcutContext(Qt::WidgetShortcut);
	action_play_skipforward->setToolTip(tr("Skip forward ('+')"));
	connect(action_play_skipforward, SIGNAL(triggered()), this, SLOT(play_skip_forward()));

	action_play_seekback = new QAction(QIcon(":/images/player_rewind.png"), tr("&Seek rewind (<-)"), this);
	action_play_seekback->setToolTip(tr("Seek rewind ('<-')" ));
	connect(action_play_seekback, SIGNAL(triggered()), this, SLOT(play_seek_back()));

	action_play_seekforward = new QAction(QIcon(":/images/player_forward.png"), tr("&Seek forward (->)"), this);
	action_play_seekforward->setToolTip(tr("Seek forward ('->')"));
	connect(action_play_seekforward, SIGNAL(triggered()), this, SLOT(play_seek_forward()));

	action_play_pausenext = new QAction(QIcon(":/images/player_pause.png"), tr("&Pause at next song"), this);
	action_play_pausenext->setShortcut(QKeySequence(tr("Ctrl+S")));
	action_play_pausenext->setShortcutContext(Qt::WidgetShortcut);
	action_play_pausenext->setCheckable(true);
	connect(action_play_pausenext, SIGNAL(triggered()), this, SLOT(actfunc_play_pausenext()));

	action_play_highlight = new QAction(QIcon(":/images/cd-rom.png"), tr("&Highlight scan"), this);
	action_play_highlight->setShortcut(QKeySequence(tr("d")));
	action_play_highlight->setShortcutContext(Qt::WidgetShortcut);
	action_play_highlight->setToolTip(tr("Highlight scan (plays 10 secs from every file) ('d')"));
	action_play_highlight->setCheckable(true);
	connect(action_play_highlight, SIGNAL(triggered()), this, SLOT(actfunc_play_highlight()));
	actmovie_play_highlight = new QMovie(":/images/cd-rom-anim.gif", NULL, this);
	if(actmovie_play_highlight->isValid())
	{
#if (QT_VERSION >= 0x050800)
		connect(actmovie_play_highlight, SIGNAL(frameChanged(int)), this, SLOT(actfunc_play_highlight_movie()));  // TODO: check
#else
		connect(actmovie_play_highlight, SIGNAL(frameChanged(int)), this, SLOT(actfunc_play_highlight_movie(int)));
#endif
		if(actmovie_play_highlight->loopCount() != -1)
			connect(actmovie_play_highlight, SIGNAL(finished()) ,actmovie_play_highlight, SLOT(start()));
	}
	else
	{
		mpxplay_debugf(DISPQT_DEBUG_ERROR, "ERROR: actmovie_play_highlight invalid!");
	}

	action_list_gotocurr = new QAction(QIcon(":/images/arrow_in.png"), tr("&Goto play-song"), this);
	action_list_gotocurr->setShortcut(QKeySequence(tr("L")));
	action_list_gotocurr->setShortcutContext(Qt::WidgetShortcut);
	action_list_gotocurr->setToolTip(tr("Goto current play-song ('L')"));
	connect(action_list_gotocurr, SIGNAL(triggered()), this, SLOT(actfunc_list_gotocurr()));

	action_list_comparedirs = new QAction(tr("&Compare dirs/lists"), this);
	action_list_comparedirs->setShortcut(QKeySequence(tr("Shift+F2")));
	action_list_comparedirs->setShortcutContext(Qt::WidgetShortcut);
	connect(action_list_comparedirs, SIGNAL(triggered()), this, SLOT(actfunc_list_comparedirs()));

	action_list_index_insert = new QAction(QIcon(":/images/cut.png"), tr("&Index insert in currsong (cut)"), this);
	action_list_index_insert->setShortcut(QKeySequence(tr("I")));
	action_list_index_insert ->setShortcutContext(Qt::WidgetShortcut);
	action_list_index_insert->setToolTip(tr("Insert index in current play-song (cut) ('I')"));
	connect(action_list_index_insert, SIGNAL(triggered()), this, SLOT(actfunc_list_index_insert()));

	action_list_index_remove = new QAction(tr("&Index remove (merge)"), this);
	action_list_index_remove->setShortcut(QKeySequence(tr("Ctrl+I")));
	action_list_index_remove->setShortcutContext(Qt::WidgetShortcut);
	action_list_index_remove->setToolTip(tr("Remove index from current play-song (merge) (ctrl-'I')"));
	connect(action_list_index_remove, SIGNAL(triggered()), this, SLOT(actfunc_list_index_remove()));

	action_list_replay = new QAction(QIcon(":/images/arrow_refresh.png"), tr("&Replay/repeat song/list"), this);
	action_list_replay->setShortcut(QKeySequence(tr("R")));
	action_list_replay->setShortcutContext(Qt::WidgetShortcut);
	action_list_replay->setToolTip(tr("Replay/repeat song/list ('R')"));
	action_list_replay->setCheckable(true);
	if(playreplay) {
		action_list_replay->setChecked(true);
		if(playreplay & REPLAY_SONG)
			action_list_replay->setIcon(QIcon(":/images/arrow_refresh1.png"));
	}
	connect(action_list_replay, SIGNAL(triggered()), this, SLOT(actfunc_list_replay()));

	action_list_random = new QAction(QIcon(":/images/arrow_switch.png"), tr("&Random play on/off"), this);
	action_list_random->setShortcut(QKeySequence(tr("N")));
	action_list_random->setShortcutContext(Qt::WidgetShortcut);
	action_list_random->setToolTip(tr("Random/Shuffle play ('N')"));
	action_list_random->setCheckable(true);
	if(playrand)
		action_list_random->setChecked(true);
	connect(action_list_random, SIGNAL(triggered()), this, SLOT(actfunc_list_random()));

	action_list_id3search = new QAction(QIcon(":/images/search.png") ,tr("&Search in list"), this);
	action_list_id3search->setToolTip(tr("Search by ID3 info in the current list"));
	action_list_id3search->setCheckable(true);
	connect(action_list_id3search, SIGNAL(triggered()), this, SLOT(actfunc_list_id3search()));

	action_list_subdirlist = new QAction(tr("&Subdirs <-> Sublist load"), this);
	action_list_subdirlist->setToolTip(tr("Load subdirs as sublist"));
	connect(action_list_subdirlist, SIGNAL(triggered()), this, SLOT(actfunc_list_subdirlist()));

	action_view_commander = new QAction(QIcon(":/images/android.png"), tr("&Commander / Player mode"), this);
	action_view_commander->setShortcut(QKeySequence(tr("E")));
	action_view_commander->setShortcutContext(Qt::WidgetShortcut);
	action_view_commander->setToolTip(tr("Commander / Player mode ('E')"));
	action_view_commander->setCheckable(true);
	if((desktopmode&DTM_MASK_COMMANDER)==DTM_MASK_COMMANDER)
		action_view_commander->setChecked(true);
	connect(action_view_commander, SIGNAL(triggered()), this, SLOT(actfunc_options_commandermode()));

	action_view_avmixer = new QAction(QIcon(":/images/mixer_green.png"), tr("&A/V mixer show/hide"), this);
	action_view_avmixer->setToolTip(tr("A/V mixer control"));
	action_view_avmixer->setCheckable(true);
	connect(action_view_avmixer, SIGNAL(triggered()), this, SLOT(actfunc_options_avmixer()));

	action_view_editorsw = new QAction(QIcon(":/images/list_green.png"), tr("&Playlist editor show / hide"), this);
	action_view_editorsw->setToolTip(tr("Playlist editor"));
	action_view_editorsw->setCheckable(true);
	connect(action_view_editorsw, SIGNAL(triggered()), this, SLOT(actfunc_view_editorsw()));

	action_view_videofs = new QAction(QIcon(":/images/monitor_green.png"), tr("&Fullscreen video switch"), this);
	action_view_videofs->setToolTip(tr("Fullscreen video switch (alt-Enter)"));
	action_view_videofs->setShortcut(QKeySequence(tr("Alt+Enter")));
	action_view_videofs->setShortcutContext(Qt::WidgetShortcut);
	connect(action_view_videofs, SIGNAL(triggered()), this, SLOT(actfunc_options_videofs()));

	action_view_mainwin_transparent = new QAction(tr("&Transparent video mode"), this);
	connect(action_view_mainwin_transparent, SIGNAL(triggered()), this, SLOT(actfunc_options_mainwin_transparent()));

	action_options_ftp_connect = new QAction(QIcon(":/images/ftp_connect.png"), tr("&FTP connect"), this);
	action_options_ftp_connect->setShortcut(QKeySequence(tr("Ctrl+F")));
	action_options_ftp_connect->setShortcutContext(Qt::WidgetShortcut);
	action_options_ftp_connect->setToolTip(tr("Open FTP connections (ctrl-'F')"));
	connect(action_options_ftp_connect, SIGNAL(triggered()), this, SLOT(actfunc_options_ftp_connect()));

	action_options_ftp_disconnect = new QAction(tr("&FTP disconnect"), this);
	action_options_ftp_disconnect->setShortcut(QKeySequence(tr("Ctrl+K")));
	action_options_ftp_disconnect->setShortcutContext(Qt::WidgetShortcut);
	connect(action_options_ftp_disconnect, SIGNAL(triggered()), this, SLOT(actfunc_options_ftp_disconnect()));

	action_options_configure = new QAction(QIcon(":/images/setting_tools.png"), tr("&Configure"), this);
	action_options_configure->setToolTip(tr("Configure program"));
	connect(action_options_configure, SIGNAL(triggered()), this, SLOT(actfunc_options_configure()));

	action_help_help = new QAction(tr("&Help (keys)"), this);
	connect(action_help_help, SIGNAL(triggered()), this, SLOT(actfunc_help_help()));

	action_help_about = new QAction(tr("&About MMC"), this);
	connect(action_help_about, SIGNAL(triggered()), this, SLOT(actfunc_help_about()));
}

//----------------------------------------------------------------------------------------------------------
DispQtMainwinMenubar::DispQtMainwinMenubar(MainWindow *main_window, QWidget *parent) : QMenuBar(parent)
{
	this->main_window = main_window;
	if(main_window->mainwin_is_translucent_enabled())
		this->menubar_set_style();
}

bool DispQtMainwinMenubar::event(QEvent *event)
{
	mpxplay_debugf(DISPQT_DEBUG_MENUBAR, "menu event: %d", event->type());
	switch(event->type()){
		case QEvent::Enter:
			this->main_window->action_play_pausenext->setChecked(funcbit_test(playcontrol, PLAYC_PAUSENEXT)? true : false);
			this->main_window->action_list_id3search->setChecked((mpxplay_control_keyboard_id3search_initialized())? true : false);
		case QEvent::MouseMove:
		case QEvent::StatusTip: emit this->main_window->signal_video_mainwin_wakeup(false, false); break;
	}
	return QMenuBar::event(event);
}

void DispQtMainwinMenubar::menubar_set_style(void)
{
	if(this->main_window->mainwin_is_translucent_enabled()) {
        setAttribute(Qt::WA_TranslucentBackground, true);
        setAttribute(Qt::WA_NoSystemBackground, false);
        setStyleSheet("DispQtMainwinMenubar { background: transparent; border-color: navy}"
        "QMenuBar::item { spacing: 0px; padding: 1px 10px; background: transparent; color : white; border-radius: 8px;}"
        //"QMenuBar::item { spacing: 0px; padding: 1px 10px; background: rgb(225,225,225,10%); color : white; border-radius: 8px;}"
        "QMenuBar::item:selected { background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
        	"stop:0 rgb(255,255,255,50%), stop: 0.25 rgb(200,200,200,40%), "
        	"stop:0.5 rgb(200,200,200,30%), stop:0.51 rgb(150,150,150,20%), stop:1 rgb(150,150,150,20%));"
        	"border-style: solid; border-width: 1px; border-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
        	"stop:0 rgb(250,250,250,90%), stop: 1 rgb(200,200,200,90%)); "
        	"}"
        	"QMenuBar::item:pressed {background: rgb(100,100,100,30%); border-color: rgb(150,150,150,60%); border-style:inset;}"
        );
    } else {
        setAttribute(Qt::WA_TranslucentBackground, false);
        setStyleSheet(QString());
    }
}

void MainWindow::createMenus()
{
	this->mainwin_menubar = new DispQtMainwinMenubar(this, this);
	this->setMenuBar(this->mainwin_menubar);

	fileMenu = menuBar()->addMenu(tr("File"));
	fileMenu->addAction(action_file_openfiles);
	fileMenu->addAction(action_file_opendir);
	fileMenu->addAction(action_file_openurl);
	fileMenu->addAction(action_file_info);
	fileMenu->addAction(action_file_edit);
	fileMenu->addAction(action_file_rename);
	fileMenu->addAction(action_file_copy);
	fileMenu->addAction(action_file_move);
	fileMenu->addAction(action_file_del);
	fileMenu->addSeparator();
	fileMenu->addAction(action_file_exit);

	playMenu = menuBar()->addMenu(tr("Play"));
	playMenu->addAction(action_play_start);
	playMenu->addAction(action_play_stop);
	playMenu->addAction(action_play_skipback);
	playMenu->addAction(action_play_skipforward);
	playMenu->addAction(action_play_pausenext);
	playMenu->addAction(action_play_highlight);

	listMenu = menuBar()->addMenu(tr("List"));
	listMenu->addAction(action_list_gotocurr);
	listMenu->addAction(action_list_comparedirs);
	listMenu->addAction(action_list_index_insert);
	listMenu->addAction(action_list_index_remove);
	listMenu->addAction(action_list_replay);
	listMenu->addAction(action_list_random);
	listMenu->addAction(action_list_id3search);
	listMenu->addAction(action_list_subdirlist);

	viewMenu = menuBar()->addMenu(tr("View"));
	viewMenu->addAction(action_view_commander);
	viewMenu->addAction(action_view_avmixer);
	viewMenu->addAction(action_view_editorsw);
	viewMenu->addAction(action_view_videofs);
	viewMenu->addAction(action_view_mainwin_transparent);

	toolsMenu = menuBar()->addMenu(tr("Tools"));
	toolsMenu->addAction(action_options_configure);
	toolsMenu->addAction(action_options_ftp_connect);
	toolsMenu->addAction(action_options_ftp_disconnect);

	menuBar()->addSeparator();

	helpMenu = menuBar()->addMenu(tr("Help"));
	helpMenu->addAction(action_help_help);
	helpMenu->addAction(action_help_about);
	helpMenu->addAction(tr("About Qt"), qApp, &QApplication::aboutQt);
}

void MainWindow::createToolBars(bool initial)
{
	if(initial){
		playToolBar = new QToolBar(tr("Play"), this);
		playToolBar->setParent(this);
		playToolBar->addAction(action_play_skipback);
		playToolBar->addAction(action_play_seekback);
		playToolBar->addAction(action_play_start);
		playToolBar->addAction(action_play_stop);
		playToolBar->addAction(action_play_seekforward);
		playToolBar->addAction(action_play_skipforward);

		QToolButton *button_rewind = dynamic_cast<QToolButton*>(playToolBar->widgetForAction(action_play_seekback));
		button_rewind->setAutoRepeat(true);
		button_rewind->setAutoRepeatDelay(100);
		button_rewind->setAutoRepeatInterval(1000/30);
		QToolButton* button_forward = dynamic_cast<QToolButton*>(playToolBar->widgetForAction(action_play_seekforward));
		button_forward->setAutoRepeat(true);
		button_forward->setAutoRepeatDelay(100);
		button_forward->setAutoRepeatInterval(1000/30);

		optionsToolBar = new QToolBar(tr("Options"), this);
		optionsToolBar->setParent(this);
		optionsToolBar->addAction(action_play_highlight);
		optionsToolBar->addAction(action_list_gotocurr);
		optionsToolBar->addAction(action_view_commander);
		optionsToolBar->addAction(action_view_avmixer);
		optionsToolBar->addAction(action_view_editorsw);
		optionsToolBar->addAction(action_view_videofs);
		optionsToolBar->addAction(action_list_replay);
		optionsToolBar->addAction(action_list_random);

		this->toolbar_widget = new QWidget;
		this->toolbar_layout = new QHBoxLayout;
		this->toolbar_layout->setMargin(0);
		this->toolbar_layout->addWidget(playToolBar, 0);
		this->toolbar_layout->addWidget(optionsToolBar, 1);
		this->toolbar_widget->setLayout(this->toolbar_layout);
	}

	if(this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_TOOLBAR){
		if(this->toolbar_widget->isHidden()){
			if(initial)
				this->main_layout->addWidget(this->toolbar_widget, 0, Qt::AlignCenter);
			else{
				this->main_layout->insertWidget(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_TOOLBAR), this->toolbar_widget, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_TOOLBAR), Qt::AlignCenter);
				this->toolbar_widget->show();
			}
		}
	} else {
		if(!this->toolbar_widget->isHidden()){
			this->toolbar_widget->hide();
			this->main_layout->removeWidget(this->toolbar_widget);
		}
	}
}

void MainWindow::createVideo(QWidget *parent)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	this->is_mainwin_on_video = false;
	if(gcfg->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_VIDEO) {
		if(!this->qt_video_player) {
			this->timer_mainwin_onvideo = new QTimer(this);
			this->qt_video_player = new DispQtVideoPlayer((MainWindow *)this, this);
			if(this->qt_video_player){
				connect(this->timer_mainwin_onvideo, SIGNAL(timeout()), this, SLOT(mainwindow_opacity_timed_change()));
				connect(this, SIGNAL(signal_video_mainwin_opacity_disable(bool)), this, SLOT(video_fullscreen_mainwin_opacity_disable(bool)));
				connect(this, SIGNAL(signal_video_fullscreen(bool)), this, SLOT(video_fullscreen_switch(bool)));
				connect(this, SIGNAL(signal_video_mainwin_wakeup(bool,bool)), this, SLOT(video_fullscreen_mainwin_wakeup(bool,bool)));
				this->mainwin_video_window_size_y = this->qt_video_player->video_get_value(DispQtVideoPlayer::VideoCtrlValue_Height);
			}
		}
	} else if(this->qt_video_player) {
		DispQtVideoPlayer *qt_video = this->qt_video_player;
		this->qt_video_player = NULL;
		this->timer_mainwin_onvideo->stop();
		disconnect(this->timer_mainwin_onvideo, SIGNAL(timeout()), this, SLOT(mainwindow_opacity_timed_change()));
		delete qt_video;
		disconnect(this, SIGNAL(signal_video_mainwin_opacity_disable(bool)), this, SLOT(video_fullscreen_mainwin_opacity_disable(bool)));
		disconnect(this, SIGNAL(signal_video_fullscreen(bool)), this, SLOT(video_fullscreen_switch(bool)));
		disconnect(this, SIGNAL(signal_video_mainwin_wakeup(bool,bool)), this, SLOT(video_fullscreen_mainwin_wakeup(bool,bool)));
		delete this->timer_mainwin_onvideo;
		this->timer_mainwin_onvideo = NULL;
		this->mainwin_video_window_size_y = 0;
	}
	this->mainwin_opacity_forbidd = false;
	this->mainwin_opacity_status_showout = false;
	mainwindow_opacity_setwindowopacity(gcfg->mainwin_opacity_general);
}

void MainWindow::createVideoControlbar(bool initial)
{
	if(initial){
		this->video_controlbar = new DispQtVideoControlbar(this, this);
		if(this->gui_config->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_CONTROLBAR)
			emit this->video_controlbar->signal_videoctrlbar_set_show(true);
	}
}

//---------------------------------------------------------------------------------
void MainWindow::createSeekbar(bool initial)
{
	struct mmc_dispqt_config_s *cfg = this->gui_config;
	if(cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR) {
		if(!this->mainwin_seekbar) {
			this->mainwin_seekbar = new DispQtMainwinSeekbar(this, this);
			this->main_layout->insertWidget(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_SEEKBAR), this->mainwin_seekbar, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_SEEKBAR));
		}
	} else {
		if(this->mainwin_seekbar){
			this->main_layout->removeWidget(this->mainwin_seekbar);
			delete this->mainwin_seekbar;
			this->mainwin_seekbar = NULL;
		}
	}
}

//---------------------------------------------------------------------------------

void MainWindow::event_mixer_dialog_close(void)
{
	struct mmc_dispqt_config_s *gcfg = this->gui_config;
	funcbit_disable(gcfg->mainwin_control, DISPQT_CONFIG_MAINWINCTRL_SHOW_AVMIXER);
	this->mixer_dialog = NULL;
	action_view_avmixer->setChecked(false);
	this->prev_mainwin_control = gcfg->mainwin_control;
}

void MainWindow::createAVmixer(bool initial)
{
	struct mmc_dispqt_config_s *cfg = this->gui_config;
	if(!initial && this->avmixer_create_lock)
		return;
	this->avmixer_create_lock = true;
	this->setUpdatesEnabled(false);
	bool enable = (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_AVMIXER)? true : false;
	if(this->mixer_widget && (!enable || !(cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_EMBEDD_AVMIXER))) {
		int mix_height = this->mixer_widget->height(), mainwin_height = this->height();
		this->main_layout->removeWidget(this->mixer_widget);
		if(!(this->windowState() & Qt::WindowMaximized)) {
			this->mainwin_geometry_resize(this->width(), mainwin_height - mix_height);
			mpxplay_debugf(DISPQT_DEBUG_MIXER,"mh:%d wh1:%d wh2:%d", mix_height, mainwin_height, this->height());
		}
		delete this->mixer_widget;
		this->mixer_widget = NULL;
	}
	if(this->mixer_dialog && (!enable || (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_EMBEDD_AVMIXER))) {
		delete this->mixer_dialog;
		this->mixer_dialog = NULL;
	}
	if(!this->mixer_widget && enable && (cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_EMBEDD_AVMIXER)) {
		this->mixer_widget = new DispQtAVMixerWidget(this, this);
		if(initial) {
			this->main_layout->addWidget(this->mixer_widget, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_AVMIXER), Qt::AlignHCenter);
		} else {
			if(!(this->windowState() & Qt::WindowMaximized))
				this->mainwin_geometry_resize(this->width(), this->height() + this->mixer_widget->height());
			this->main_layout->insertWidget(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_AVMIXER), this->mixer_widget, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_AVMIXER), Qt::AlignHCenter);
		}
	} else if(!this->mixer_dialog && (enable && !(cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_EMBEDD_AVMIXER))) {
		this->mixer_dialog = new DispQtAVMixerDialog(this, this);
		int opacity = (this->is_mainwin_on_video)? cfg->mainwin_opacity_onvideo_show : cfg->mainwin_opacity_general;
		this->mixer_dialog->setWindowOpacity((qreal)opacity / 100.0);
	}
	if(enable)
		funcbit_enable(cfg->mainwin_control, DISPQT_CONFIG_MAINWINCTRL_SHOW_AVMIXER);
	action_view_avmixer->setChecked(enable);
	this->setUpdatesEnabled(true);
	if(initial){
		connect(this, SIGNAL(signal_avmixer_set_avformat(bool)), this, SLOT(mainwin_avmixer_set_avformat(bool)));
		connect(this, SIGNAL(signal_avmixer_sliders_reload(bool)), this, SLOT(mainwin_avmixer_sliders_reload(bool)));
	}
	this->avmixer_create_lock = false;
}

void MainWindow::mainwin_avmixer_set_avformat(bool video)
{
	if(this->mixer_dialog)
		emit this->mixer_dialog->signal_avdialog_set_avformat(video);
	else if(this->mixer_widget)
		emit this->mixer_widget->signal_avmixer_set_avformat(video);
}
void MainWindow::mainwin_avmixer_sliders_reload(bool volume_only)
{
	if(this->mixer_dialog)
		emit this->mixer_dialog->signal_avdialog_sliders_reload(volume_only);
	else if(this->mixer_widget)
		emit this->mixer_widget->signal_avmixer_sliders_reload(volume_only);
	if(!volume_only){
		if(playcontrol & PLAYC_HIGHSCAN) {
			action_play_highlight->setChecked(true);
			actmovie_play_highlight->start();
		} else {
			actmovie_play_highlight->stop();
			action_play_highlight->setChecked(false);
			action_play_highlight->setIcon(QIcon(":/images/cd-rom.png"));
		}
		action_list_replay->setChecked((playreplay)? true : false);
    	if(playreplay & REPLAY_SONG)
    		action_list_replay->setIcon(QIcon(":/images/arrow_refresh1.png"));
    	else
    		action_list_replay->setIcon(QIcon(":/images/arrow_refresh.png"));
		action_list_random->setChecked((playrand)? true : false);
	}
}

void MainWindow::createEditor(bool initial)
{
	struct mmc_dispqt_config_s *cfg = this->gui_config;
	if(initial)
		PlaylistEditor = new PlaylistEditorWidget(this, this);
	if(cfg->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_EDITOR){
		if(initial) {
			this->main_layout->addWidget(this->PlaylistEditor, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_EDITOR));
			funcbit_enable(cfg->editor_flags, DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED);
		} else {
		    this->setUpdatesEnabled(false);
			if(!(this->windowState() & Qt::WindowMaximized)) {
				this->mainwin_geometry_resize(this->width(), this->height() + cfg->editor_size_y);
				funcbit_enable(cfg->editor_flags, DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED);
			}
			this->main_layout->insertWidget(this->mainwin_widget_index(DISPQT_MAINWIN_WIDGET_EDITOR), PlaylistEditor, this->mainwin_widget_stretch(DISPQT_MAINWIN_WIDGET_EDITOR));
		}
		if(!initial){
		    this->PlaylistEditor->show();
		    this->setUpdatesEnabled(true);
		}
		action_view_editorsw->setChecked(true);
		this->setFocusPolicy(Qt::NoFocus);
		PlaylistEditor->set_default_focus(mvps.psie);
		if(!initial)
		    refdisp |= RDT_EDITOR|RDT_TABINFOS;
	} else {
		if(!initial) {
			if(!(this->windowState() & Qt::WindowMaximized)) {
				cfg->editor_size_y = this->PlaylistEditor->height();
				if(this->is_mainwin_on_video)
					cfg->editor_size_y -= this->mainwin_video_window_size_y;
				if(cfg->editor_size_y < DISPQT_MAINWIN_SIZEY_EDITOR_MIN)
					cfg->editor_size_y = DISPQT_MAINWIN_SIZEY_EDITOR_MIN;
			}
			int mainwin_height = this->height();
			this->setUpdatesEnabled(false);
			this->PlaylistEditor->hide();
			this->main_layout->removeWidget(this->PlaylistEditor);
			if(!(this->windowState() & Qt::WindowMaximized)) {
				this->mainwin_geometry_resize(this->width(), mainwin_height - cfg->editor_size_y);
				funcbit_disable(cfg->editor_flags, DISPQT_CONFIG_EDITORFLAG_WIDGET_ADDED);
			}
			this->setUpdatesEnabled(true);
		} else
			this->PlaylistEditor->hide();
		action_view_editorsw->setChecked(false);
		this->setFocusPolicy(Qt::ClickFocus);
		this->setFocus();
	}
}

void MainWindow::createDialogHandler(QWidget *parent)
{
	this->dialog_handler = new DispQtTextwinGenerate((MainWindow *)this, parent);
}
//-----------------------------------------------------------------------------------------------
void MainWindow::mainwin_media_set_currfileinfos(struct dispqt_currfileinfo_s *cur)
{
	if(!cur)
		return;
	if(this->mainwin_seekbar && (this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR))
		this->mainwin_seekbar->mainwinseekbar_set_currfileinfos(cur);
	if(this->video_controlbar && (this->gui_config->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_CONTROLBAR))
		this->video_controlbar->videoctrlbar_set_currfileinfos(cur);
	this->mainwin_taskbar_set_currfileinfos(cur);
	this->action_play_skipback->setToolTip(QString::fromUtf8(cur->prev_title));
	this->action_play_skipforward->setToolTip(QString::fromUtf8(cur->next_title));
	free(cur);
}

void MainWindow::mainwin_media_set_timepos(int timepos_ms)
{
	if(this->mainwin_seekbar && (this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR))
		emit this->mainwin_seekbar->signal_mainwinseekbar_set_timepos(timepos_ms);
	if(this->video_controlbar && (this->gui_config->video_control & DISPQT_CONFIG_VIDEOCTRL_ENABLE_CONTROLBAR))
		emit this->video_controlbar->signal_videoctrlbar_set_timepos(timepos_ms);
	this->mainwin_taskbar_set_timepos(timepos_ms);
}

/*void MainWindow::mainwin_option_timemode_change(unsigned int mode)
{
	if(this->mainwin_seekbar && (this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_SEEKBAR))
		emit this->mainwin_seekbar->signal_mainwinseekbar_option_timemode_change(mode);
}*/

//-----------------------------------------------------------------------------------------------
void MainWindow::mainwin_statusbar_init(void)
{
	if(this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE){
		if(!this->action_statusbar_msg_dynamic) {
			bool lock_success = this->mutex_statusline.tryLock(DISPQT_MUTEX_TIMEOUT);
			this->action_statusbar_msg_dynamic = new QAction(this);
			this->act_statusbar_userdataid_msg = this->action_statusbar_msg_dynamic->registerUserData();
			connect(this, SIGNAL(signal_statusbar_msg_dynamic()), this, SLOT(mainwin_statusbar_msg_recv()));
			this->statusBar()->show();
			if(lock_success)
				this->mutex_statusline.unlock();
		}
	} else  if(this->action_statusbar_msg_dynamic) {
		bool lock_success = this->mutex_statusline.tryLock(DISPQT_MUTEX_TIMEOUT);
		disconnect(this, SIGNAL(signal_statusbar_msg_dynamic()), this, SLOT(mainwin_statusbar_msg_recv()));
		this->act_statusbar_userdataid_msg = 0;
		delete this->action_statusbar_msg_dynamic;
		this->action_statusbar_msg_dynamic = NULL;
		this->statusBar()->hide();
		if(lock_success)
			this->mutex_statusline.unlock();
		return;
	}

	if( (!(this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE) && (this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT))
	 || ((this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT) != (this->prev_mainwin_control & DISPQT_CONFIG_MAINWINCTRL_TRANSLUCENT))
	){
		this->mainwin_statusbar_style_apply();
	}

    mainwin_statusbar_msg_send((char *)"Ready");
}

void MainWindow::mainwin_statusbar_style_apply(void)
{
	if(!(this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE))
		return;
	bool lock_success = this->mutex_statusline.tryLock(DISPQT_MUTEX_TIMEOUT);
	if(this->mainwin_is_translucent_enabled())
		this->statusBar()->setStyleSheet("QStatusBar {color: white;} QStatusBar::item {color: white;}");
	else
		this->statusBar()->setStyleSheet(QString());
	if(lock_success)
		this->mutex_statusline.unlock();
}

void MainWindow::mainwin_statusbar_message(char *msg)
{
	if(!(this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE))
		return;
	bool lock_success = this->mutex_statusline.tryLock(DISPQT_MUTEX_TIMEOUT);
	this->str_statusline = QString::fromUtf8(msg);
	statusBar()->showMessage(this->str_statusline);
	if(lock_success)
		this->mutex_statusline.unlock();
}

void MainWindow::mainwin_statusbar_msg_recv(void)
{
	char *msg = (char *)this->action_statusbar_msg_dynamic->userData(this->act_statusbar_userdataid_msg);
	if(!msg)
		return;
	mainwin_statusbar_message(msg);
	this->action_statusbar_msg_dynamic->setUserData(this->act_statusbar_userdataid_msg, NULL);
	delete msg;
}

bool MainWindow::mainwin_statusbar_msg_send(char *msg)
{
	if(!(this->gui_config->mainwin_control & DISPQT_CONFIG_MAINWINCTRL_SHOW_STATUSLINE) || !this->action_statusbar_msg_dynamic)
		return true;
	if(this->action_statusbar_msg_dynamic->userData(this->act_statusbar_userdataid_msg))
		return false;
	unsigned int len = pds_strlen(msg);
	if(!len || (len > MAX_PATHNAMELEN))
		return true;
	char *dynmsg = new char[len + 4];
	if(!dynmsg)
		return true;
	memcpy(dynmsg, msg, len + 1);
	dynmsg[len] = 0;
	this->action_statusbar_msg_dynamic->setUserData(this->act_statusbar_userdataid_msg, (QObjectUserData *)dynmsg);
	emit this->signal_statusbar_msg_dynamic();
	return true;
}

//-------------------------------------------------------------------------------------
// taskbar control

void MainWindow::mainwin_taskbar_init(void)
{
	QWinTaskbarButton *taskbarButton = new QWinTaskbarButton(this);
	taskbarButton->setWindow(windowHandle());
	mainwin_taskbar_progress = taskbarButton->progress();
	mainwin_taskbar_progress->setRange(0, 100);
	mainwin_taskbar_progress->show();

	mainwin_taskbar_toolbar = new QWinThumbnailToolBar(this);
	mainwin_taskbar_toolbar->setWindow(windowHandle());

	mainwin_taskbar_button_skip_back = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_skip_back->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
	connect(mainwin_taskbar_button_skip_back, SIGNAL(clicked()), this, SLOT(play_skip_back()));

	mainwin_taskbar_button_seek_rewind = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_seek_rewind->setToolTip(tr("Rewind"));
	mainwin_taskbar_button_seek_rewind->setIcon(style()->standardIcon(QStyle::SP_MediaSeekBackward));
	connect(mainwin_taskbar_button_seek_rewind, SIGNAL(clicked()), this, SLOT(play_seek_faster_back()));

	mainwin_taskbar_button_play = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_play->setToolTip(tr("Play / Pause"));
	mainwin_taskbar_button_play->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
	connect(mainwin_taskbar_button_play, SIGNAL(clicked()), this, SLOT(play_start_or_pause()));

	mainwin_taskbar_button_stop = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_stop->setToolTip(tr("Stop"));
	mainwin_taskbar_button_stop->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
	connect(mainwin_taskbar_button_stop, SIGNAL(clicked()), this, SLOT(play_stop()));

	mainwin_taskbar_button_seek_forward = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_seek_forward->setToolTip(tr("Fast forward"));
	mainwin_taskbar_button_seek_forward->setIcon(style()->standardIcon(QStyle::SP_MediaSeekForward));
	connect(mainwin_taskbar_button_seek_forward, SIGNAL(clicked()), this, SLOT(play_seek_faster_forward()));

	mainwin_taskbar_button_skip_forward = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_skip_forward->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
	connect(mainwin_taskbar_button_skip_forward, SIGNAL(clicked()), this, SLOT(play_skip_forward()));

	mainwin_taskbar_button_fullscreen = new QWinThumbnailToolButton(mainwin_taskbar_toolbar);
	mainwin_taskbar_button_fullscreen->setToolTip(tr("Fullscreen video / Transparency off"));
	mainwin_taskbar_button_fullscreen->setIcon(style()->standardIcon(QStyle::SP_DesktopIcon));
	connect(mainwin_taskbar_button_fullscreen, SIGNAL(clicked()), this, SLOT(actfunc_options_videofs()));

	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_skip_back);
	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_seek_rewind);
	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_play);
	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_stop);
	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_seek_forward);
	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_skip_forward);
	mainwin_taskbar_toolbar->addButton(mainwin_taskbar_button_fullscreen);
}

void MainWindow::mainwin_taskbar_set_currfileinfos(struct dispqt_currfileinfo_s *cur)
{
	mainwin_taskbar_progress->setRange(0, max(100, (cur->currtimelen / 1000)));
	mainwin_taskbar_button_skip_back->setToolTip(QString::fromUtf8(cur->prev_title));
	mainwin_taskbar_button_skip_forward->setToolTip(QString::fromUtf8(cur->next_title));
}

void MainWindow::mainwin_taskbar_set_timepos(int new_timepos_ms)
{
	mainwin_taskbar_progress->setValue(new_timepos_ms / 1000);
}
