/***************************************************************************
 *   Copyright (C) 2008 by Peter Dahlberg   *
 *   pdahlberg@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include <QtGui>
#include "lsim.h"
#include "simulscene.h"

#include <QDockWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QActionGroup>
#include <QGroupBox>
#include <QDoubleSpinBox>
#include <QListView>
#include <QStringListModel>
#include <QLabel>
#include <QGridLayout>
#include <QListWidget>
#include "expdoublespinbox.h"
#include "homoefieldwidget.h"
#include "constants.h"
#include "homobfielditem.h"
#include "homoefielditem.h"
#include "stopperitem.h"


lsim::lsim() {
	gview = new GraphicsView(this,statusBar());
	setCentralWidget (gview);
	createScene();
	createActions();
	simulscene->setSceneMode(SimulScene::FieldItemEdit);
	createMenus();
	createToolBars();
	createStatusBar();
	createDocks();
	setMode(EditMode);
	connect(simulscene, SIGNAL(timeLineDurationChanged(int)),this, SLOT(timeLineDurationChangeWrapperToSec(int)));
}

void lsim::saveFileAs() {
	clearAnyFocus();
	simulscene->stopTimer();
	QFile file(QFileDialog::getSaveFileName(this, tr("Speichern unter..."),
                                               QString(), tr("lsim Dateien (*.lsm);;Alle Dateien (*)")));
	if (file.fileName() == "") return; //wenn keine datei gewaehlt

	QStringList fileNameSplit = file.fileName().split('.');
	if (fileNameSplit.count() > 0 && !file.exists()) { //.lsm anhaengen
		if (fileNameSplit.last() != "lsm") {
			QString fileName = file.fileName();
			if (fileName.endsWith('.')) fileName.append("lsm");
			else fileName.append(".lsm");
			file.setFileName(fileName);
		}
	}

	if(!file.open(QIODevice::WriteOnly)){ //wenn oeffnen fehl schlaegt
		QMessageBox::warning ( this, tr("Speichern Fehlgeschlagen"),
					 tr("Die Datei konnte leider nicht gespeichert werden"));
		return;
	}

	QDataStream out(&file);
	out.setVersion(QDataStream::Qt_4_4);
	QList<QVariant> simulSceneSaveList = simulscene->getSaveDataList();
	QList<QVariant> ProbeChargeItemSaveList = simulscene->getProbeChargeItem()->getSaveDataList();
	out << FILEMAGIC;
	out << FILEVERSION;
	out << simulSceneSaveList;
	out << ProbeChargeItemSaveList;

	QList<QGraphicsItem*> fields(simulscene->getFieldItemsInZOrder());
	for(int i = 0;i<fields.count();++i) {
		FieldItem* currItem = dynamic_cast<FieldItem*>(fields.at(i));
		QList<QVariant> fieldItemSaveList = currItem->getSaveDataList();
		out << fieldItemSaveList;
	}
	
	file.close();
}
void lsim::openFile() {
	QFile file(QFileDialog::getOpenFileName(this, tr("\326ffnen..."),
                                               QString(), tr("lsim Dateien (*.lsm);;Alle Dateien (*)")));
	if (file.fileName() == "") return; //wenn keine datei gewaehlt

	if(!file.open(QIODevice::ReadOnly)){ //wenn oeffnen fehl schlaegt
		displayOpenFailedBox();
		return;
	}
	resetAll();
	QDataStream in(&file);
	in.setVersion(QDataStream::Qt_4_4);
	qint32 magic;
	qint32 version;
	in >> magic;
	in >> version;
	if (magic != FILEMAGIC||version != FILEVERSION) {
		displayOpenFailedBox();
		return;
	}

	QList<QVariant> simulSceneSaveList;
	QList<QVariant> ProbeChargeItemSaveList;
	in >> simulSceneSaveList;
	in >> ProbeChargeItemSaveList;
	simulscene->setSaveDataList(simulSceneSaveList);
	simulscene->getProbeChargeItem()->setSaveDataList(ProbeChargeItemSaveList);
	while(!in.atEnd()) {
		QList<QVariant> fieldItemSaveList;
		in >> fieldItemSaveList;
		FieldItem* currItem;
		if (fieldItemSaveList.first() == HomoEFieldItem::Type) {
			currItem = new HomoEFieldItem(QRectF(0,0,0,0));
		} else if (fieldItemSaveList.first() == HomoBFieldItem::Type) {
			currItem = new HomoBFieldItem(QRectF(0,0,0,0));
		} else if (fieldItemSaveList.first() == StopperItem::Type) {
			currItem = new StopperItem(QPointF(0,0),QPointF(0,0));
		} else { 
			continue;
		}

		simulscene->connectNewFieldItem(currItem);
		simulscene->addItem(currItem);
		currItem->setSaveDataList(fieldItemSaveList);
	}

	file.close();
}

void lsim::displayOpenFailedBox() {
	QMessageBox::warning ( this, tr("\326ffnen Fehlgeschlagen"),
			tr("Die Datei konnte leider nicht ge\366ffnet werden"));
}

void lsim::closeEvent (QCloseEvent *event) {
	//event->ignore();
}



void lsim::about() {
	QString aboutString;
	aboutString += "lsim - Simulation von Bewegten Ladungen in elektrischen und magnetischen Feldern. \n";
	aboutString += "geschrieben 2008/2009 von Peter Dahlberg im Rahmen der Facharbeit\n";
	aboutString += "\n";
	aboutString += "Dieses Programm ist freie Software unter der GPL Version 2 oder h\366her (http://www.gnu.org/licenses/gpl2.txt)\n";
	aboutString += "\n";
	aboutString += "Die Verwendeten icons basieren auf dem KDE Oxygen icon theme und stehen unter LGPL (http://www.oxygen-icons.org und http://kde.org)\n";
	aboutString += "\n";
	aboutString += "Dieses Binary wurde kompiliert am "+QString(__DATE__) + " um " + QString(__TIME__) + " Uhr";
	QMessageBox::about (this, tr ("\334ber lsim"),
	               	aboutString);
}



void lsim::createActions() {
	QIcon fullScreenIcon = QIcon(":icons/view-fullscreen.svg");
	fullScreenIcon.addFile(":icons/view-restore.svg", QSize(),QIcon::Normal,QIcon::On);
	fullScreenIcon.addFile(":icons/view-restore.svg", QSize(),QIcon::Disabled,QIcon::On);
	fullScreenIcon.addFile(":icons/view-restore.svg", QSize(),QIcon::Active,QIcon::On);
	fullScreenIcon.addFile(":icons/view-restore.svg", QSize(),QIcon::Selected,QIcon::On);
	acts.fullScreenAct = new QAction (tr ("&Vollbild"), this);
	acts.fullScreenAct->setStatusTip (tr ("In den Vollbildmodus Wechseln"));
	acts.fullScreenAct->setIcon(fullScreenIcon);
	acts.fullScreenAct->setCheckable(true);
	acts.fullScreenAct->setShortcut(QKeySequence(Qt::Key_F11));
	connect (acts.fullScreenAct, SIGNAL (toggled(bool)), this, SLOT (goToFullscreen(bool)));
	connect (this, SIGNAL (fullScreenModeChanged(bool)), acts.fullScreenAct, SLOT (setChecked(bool)));

	acts.aboutAct = new QAction (tr ("&\334ber lsim"), this);
	acts.aboutAct->setStatusTip (tr (""));
	connect (acts.aboutAct, SIGNAL (triggered()), this, SLOT (about()));

	acts.fileSaveAsAct = new QAction (tr ("&Speichern..."), this);
	acts.fileSaveAsAct->setStatusTip (tr ("Die Anordnung speichern"));
	acts.fileSaveAsAct->setShortcut(QKeySequence::Save);
	acts.fileSaveAsAct->setIcon(QIcon(":icons/document-save.svg"));
	connect (acts.fileSaveAsAct, SIGNAL (triggered()), this, SLOT (saveFileAs()));

	acts.fileOpenAct = new QAction (tr ("&\326ffnen..."), this);
	acts.fileOpenAct->setStatusTip (tr ("Die Anordnung \366ffnen"));
	acts.fileOpenAct->setShortcut(QKeySequence::Open);
	acts.fileOpenAct->setIcon(QIcon(":icons/document-open.svg"));
	connect (acts.fileOpenAct, SIGNAL (triggered()), this, SLOT (openFile()));

	acts.aboutQtAct = new QAction (tr ("\334ber &Qt"), this);
	acts.aboutQtAct->setStatusTip (tr ("Show the Qt library's About box"));
	connect (acts.aboutQtAct, SIGNAL (triggered()), qApp, SLOT (aboutQt()));

	acts.oglEnable = new QAction (tr ("Opengl ein"), this);
	acts.oglEnable->setStatusTip (tr ("OGL ein"));
	connect (acts.oglEnable, SIGNAL (triggered()), gview, SLOT (enableOGLViewport()));

	acts.oglDisable = new QAction (tr ("Opengl aus"), this);
	acts.oglDisable->setStatusTip (tr ("OGL aus"));
	connect (acts.oglDisable, SIGNAL (triggered()), gview, SLOT (disableOGLViewport()));

	acts.calculate = new QAction (tr ("Berechnen"), this);
	acts.calculate->setStatusTip (tr ("Flugbahn berechnen"));
	connect (acts.calculate, SIGNAL (triggered()), this, SLOT (startCalculation()));

	acts.resetAct = new QAction (tr ("Alles Zur\374cksetzen"), this);
	acts.resetAct->setStatusTip (tr ("Alle Werte Zur\374cksetzen und alle Felder L\366schen"));
	acts.resetAct->setIcon(QIcon(":icons/document-revert.svg"));
	connect (acts.resetAct, SIGNAL (triggered()), this, SLOT (resetAllActionSlot()));

	acts.timerStart = new QAction (tr ("Timer Start"), this);
	acts.timerStart->setStatusTip (tr ("Timer starten"));
	connect (acts.timerStart, SIGNAL (triggered()), this, SLOT (startTimer()));

	acts.centerOnProbeAct = new QAction (tr ("Ladungstr\344ger Zentrieren"), this);
	acts.centerOnProbeAct->setStatusTip (tr ("Den Ladungstr\344ger Zentrieren"));
	acts.centerOnProbeAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
	connect (acts.centerOnProbeAct, SIGNAL (triggered()), gview, SLOT (centerOnProbe()));

	acts.timerStop = new QAction (tr ("Animation stoppen"), this);
	acts.timerStop->setStatusTip (tr ("Die Animation stoppen und Ladung an den Anfang zur\374cksetzen"));
	acts.timerStop->setIcon(QIcon(":icons/media-playback-stop.svg"));
	connect (acts.timerStop, SIGNAL (triggered()), simulscene, SLOT (stopTimer()));

	QIcon timerPauseIcon = QIcon(":icons/media-playback-start.svg");
	timerPauseIcon.addFile(":icons/media-playback-pause.svg", QSize(),QIcon::Normal,QIcon::On);
	timerPauseIcon.addFile(":icons/media-playback-pause.svg", QSize(),QIcon::Disabled,QIcon::On);
	timerPauseIcon.addFile(":icons/media-playback-pause.svg", QSize(),QIcon::Active,QIcon::On);
	timerPauseIcon.addFile(":icons/media-playback-pause.svg", QSize(),QIcon::Selected,QIcon::On);
	acts.timerPause = new QAction (tr ("Animation starten und pausieren"), this);
	acts.timerPause->setStatusTip (tr ("Animation starten oder unterwegs anhalten"));
	acts.timerPause->setIcon(timerPauseIcon);
	acts.timerPause->setCheckable(true);
	connect (acts.timerPause, SIGNAL (toggled(bool)), simulscene, SLOT (startPauseTimer(bool)));
	connect (simulscene, SIGNAL(timeLineInRunningState(bool)), acts.timerPause, SLOT(setChecked(bool)) );
	connect (acts.timerPause, SIGNAL (toggled(bool)), this , SLOT(clearAnyFocus()));
	//connect (acts.timerStop, SIGNAL (triggered(bool)), acts.timerPause, SLOT (setChecked(bool)));

	acts.exitAct = new QAction (tr ("Beenden"), this);
	acts.exitAct->setStatusTip (tr ("lsim beenden"));
	acts.exitAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
	acts.exitAct->setIcon(QIcon(":icons/application-exit.svg"));
	connect (acts.exitAct, SIGNAL (triggered()), qApp, SLOT (quit()));

	//up down actions
	acts.moveItemDown = new QAction (tr("Eine Stufe nach unten"), this);
	acts.moveItemDown->setStatusTip (tr ("Eine Stufe nach unten verschieben"));
	acts.moveItemDown->setIcon(QIcon(":icons/go-down.svg"));
	acts.moveItemDown->setEnabled(false);
	connect (acts.moveItemDown, SIGNAL (triggered()), simulscene, SLOT (moveSelectedFieldItemDown()));
	connect (acts.moveItemDown, SIGNAL (triggered()), this, SLOT (handleUpDownActionChanges()) );

	acts.moveItemUp = new QAction (tr("Eine Stufe nach oben"), this);
	acts.moveItemUp->setStatusTip (tr ("Eine Stufe nach oben verschieben"));
	acts.moveItemUp->setIcon(QIcon(":icons/go-up.svg"));
	acts.moveItemUp->setEnabled(false);
	connect (acts.moveItemUp, SIGNAL (triggered()), simulscene, SLOT (moveSelectedFieldItemUp()));
	connect (acts.moveItemUp, SIGNAL (triggered()), this, SLOT (handleUpDownActionChanges()) );

	acts.moveItemOnTop = new QAction (tr("Nach ganz oben verschieben"), this);
	acts.moveItemOnTop->setStatusTip (tr ("Nach ganz oben verschieben"));
	acts.moveItemOnTop->setIcon(QIcon(":icons/go-top.svg"));
	acts.moveItemOnTop->setEnabled(false);
	connect (acts.moveItemOnTop, SIGNAL (triggered()), simulscene, SLOT (moveSelectedFieldItemOnTop()));
	connect (acts.moveItemOnTop, SIGNAL (triggered()), this, SLOT (handleUpDownActionChanges()) );

	acts.moveItemOnBottom = new QAction (tr("Nach ganz unten verschieben"), this);
	acts.moveItemOnBottom->setStatusTip (tr ("Nach ganz unten verschieben"));
	acts.moveItemOnBottom->setIcon(QIcon(":icons/go-bottom.svg"));
	acts.moveItemOnBottom->setEnabled(false);
	//acts.moveItemOnBottom->setToolTip( tr ("Nach ganz unten absinken lassen"));
	connect (acts.moveItemOnBottom, SIGNAL (triggered()), simulscene, SLOT (moveSelectedFieldItemOnBottom()));
	connect (acts.moveItemOnBottom, SIGNAL (triggered()), this, SLOT (handleUpDownActionChanges()) );

	connect (simulscene, SIGNAL (selectionChanged ()), this, SLOT (handleUpDownActionChanges()) );

	//Edit, insert, Modechange

	acts.itemEditModeAct = new QAction (tr ("Felder Bearbeiten"), this);
	acts.itemEditModeAct->setStatusTip (tr ("Die Anordnung ver\344ndern"));
	acts.itemEditModeAct->setIcon(QIcon(":icons/edit-scene.svg"));
	acts.itemEditModeAct->setCheckable(true);
	acts.itemEditModeAct->setData(QVariant(SimulScene::FieldItemEdit));

	acts.insertEFieldItemAct = new QAction (tr ("Elektrisches Feld hizuf\374gen"), this);
	acts.insertEFieldItemAct->setStatusTip (tr ("Ein elekrisches Feld hizuf\374gen"));
	acts.insertEFieldItemAct->setIcon(QIcon(":icons/insert-efield.svg"));
	acts.insertEFieldItemAct->setCheckable(true);
	acts.insertEFieldItemAct->setData(QVariant(SimulScene::HomoEFieldItemInsert));

	acts.insertBFieldItemAct = new QAction (tr ("Magnetfeld hizuf\374gen"), this);
	acts.insertBFieldItemAct->setStatusTip (tr ("Ein magnetisches Feld hizuf\374gen"));
	acts.insertBFieldItemAct->setIcon(QIcon(":icons/insert-bfield.svg"));
	acts.insertBFieldItemAct->setCheckable(true);
	acts.insertBFieldItemAct->setData(QVariant(SimulScene::HomoBFieldItemInsert));

	acts.insertStopperItemAct = new QAction (tr ("Metallplatte hizuf\374gen"), this);
	acts.insertStopperItemAct->setStatusTip (tr ("Eine Metallplatte Hizuf\374gen, die die Ladung absorbiert"));
	acts.insertStopperItemAct->setIcon(QIcon(":icons/insert-stopper.svg"));
	acts.insertStopperItemAct->setCheckable(true);
	acts.insertStopperItemAct->setData(QVariant(SimulScene::StopperItemInsert));


	acts.probeChargeItemPlaceAct = new QAction (tr ("Probeladung platzieren"), this);
	acts.probeChargeItemPlaceAct->setStatusTip (tr ("Die Probeladung neu platzieren"));
	acts.probeChargeItemPlaceAct->setIcon(QIcon(":icons/place-charge.svg"));
	acts.probeChargeItemPlaceAct->setCheckable(true);
	acts.probeChargeItemPlaceAct->setData(QVariant(SimulScene::ProbeChargeItemPlace));
	
	modeChangeActGroup = new QActionGroup(this);
	modeChangeActGroup->addAction(acts.itemEditModeAct);
	modeChangeActGroup->addAction(acts.insertEFieldItemAct);
	modeChangeActGroup->addAction(acts.insertBFieldItemAct);
	modeChangeActGroup->addAction(acts.insertStopperItemAct);
	modeChangeActGroup->addAction(acts.probeChargeItemPlaceAct);
	connect (modeChangeActGroup, SIGNAL (triggered(QAction*)), this, SLOT (actModeSwitcher(QAction*)));
	connect (simulscene, SIGNAL(sceneModeChanged(int)) , this, SLOT(setSceneMode(int)));
	

	//Window Mode
	acts.editModeAct = new QAction (tr ("&Bearbeitungsmodus"), this);
	acts.editModeAct->setStatusTip (tr ("erm\366glicht das Bearbeiten der Anordnung"));
	acts.editModeAct->setIcon(QIcon(":icons/window-editmode.svg"));
	acts.editModeAct->setCheckable(true);
	acts.editModeAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E));
	acts.editModeAct->setData(QVariant(lsim::EditMode));

	acts.simulationModeAct = new QAction (tr ("&Simulationsmodus"), this);
	acts.simulationModeAct->setStatusTip (tr ("Berechnet die Flugbahn und wechselt in den Simulationsmodus"));
	acts.simulationModeAct->setIcon(QIcon(":icons/window-simulmode.svg"));
	acts.simulationModeAct->setCheckable(true);
	acts.simulationModeAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R));
	acts.simulationModeAct->setData(QVariant(lsim::SimulationMode));

	windowModeActGroup = new QActionGroup(this);
	windowModeActGroup->addAction(acts.editModeAct);
	windowModeActGroup->addAction(acts.simulationModeAct);
	connect (windowModeActGroup, SIGNAL (triggered(QAction*)), this, SLOT (actWindowModeSwitcher(QAction*)));
	//connect (simulscene, SIGNAL(sceneModeChanged(int)) , this, SLOT(setSceneMode(int)));

}

void lsim::createMenus() {
	fileMenu = menuBar()->addMenu(tr("&Datei"));

	fileMenu->addAction(acts.resetAct);
	fileMenu->addAction(acts.fileOpenAct);
	fileMenu->addAction(acts.fileSaveAsAct);
	fileMenu->addSeparator();
	fileMenu->addAction(acts.exitAct);

	//editMenu = menuBar()->addMenu(tr("&Bearbeiten"));


	viewMenu = menuBar()->addMenu(tr("&Ansicht"));
	viewMenu->addAction(acts.centerOnProbeAct);
	viewMenu->addSeparator();
	viewMenu->addAction(acts.editModeAct);
	viewMenu->addAction(acts.simulationModeAct);
	viewMenu->addSeparator();
	viewMenu->addAction(acts.fullScreenAct);

	helpMenu = menuBar()->addMenu (tr ("&Hilfe"));
	helpMenu->addAction (acts.aboutAct);
	helpMenu->addAction (acts.aboutQtAct);

}

void lsim::createToolBars() {
	windowModeBar = new QToolBar(tr("Modus"));
	windowModeBar->setIconSize(QSize(24,24));
	windowModeBar->addAction(acts.editModeAct);
	windowModeBar->addAction(acts.simulationModeAct);

	timerControlBar = new QToolBar (tr ("Timer"));
	timerControlBar->setIconSize(QSize(24,24));
	timerControlBar->addAction(acts.timerPause);
	timerControlBar->addAction(acts.timerStop);

	sceneModeBar = new QToolBar (tr ("Edit"));
	sceneModeBar->setIconSize(QSize(24,24));
	sceneModeBar->addAction(acts.itemEditModeAct);
	sceneModeBar->addAction(acts.insertEFieldItemAct);
	sceneModeBar->addAction(acts.insertBFieldItemAct);
	sceneModeBar->addAction(acts.insertStopperItemAct);
	sceneModeBar->addAction(acts.probeChargeItemPlaceAct);

	upDownBar = new QToolBar(tr("Feldanordnungsreihenfolge"));
	upDownBar->setIconSize(QSize(21,21));
	upDownBar->addAction(acts.moveItemOnBottom);
	upDownBar->addAction(acts.moveItemDown);
	upDownBar->addAction(acts.moveItemUp);
	upDownBar->addAction(acts.moveItemOnTop);

	addToolBar(windowModeBar);
}

void lsim::initWindowMode(WindowMode newMode) {
	removeToolBar(timerControlBar);
	removeToolBar(sceneModeBar);
	removeToolBar(upDownBar);
	removeDockWidget(fieldItemEditDock);
	removeDockWidget(probeItemDock);
	removeDockWidget(sceneDock);
	removeDockWidget(simulOptDock);
	removeDockWidget(simulDataDock);
	gview->setDragMode(QGraphicsView::NoDrag);
	gview->setInteractive(true);
	
	if (newMode == lsim::EditMode) {
		simulscene->clearFlightPath();
		acts.timerStop->trigger();

		addToolBar(sceneModeBar);
		addToolBar(upDownBar);
		addDockWidget(Qt::LeftDockWidgetArea,probeItemDock);
		addDockWidget(Qt::LeftDockWidgetArea,sceneDock);
		addDockWidget(Qt::LeftDockWidgetArea,fieldItemEditDock);
		tabifyDockWidget(probeItemDock,sceneDock);
		tabifyDockWidget(sceneDock,fieldItemEditDock);
		sceneDock->show();
		sceneModeBar->setVisible(true);
		upDownBar->setVisible(true);
		fieldItemEditDock->setVisible(true);
		probeItemDock->setVisible(true);
		sceneDock->setVisible(true);
		gview->centerOnProbe();

		

	} else if (newMode == lsim::SimulationMode) {
		addToolBar(timerControlBar);
		timerControlBar->setVisible(true);
		gview->setDragMode(QGraphicsView::ScrollHandDrag);
		gview->setInteractive (false);

		addDockWidget(Qt::LeftDockWidgetArea,simulOptDock);
		addDockWidget(Qt::LeftDockWidgetArea,simulDataDock);
		simulOptDock->setVisible(true);
		simulDataDock->setVisible(true);
		tabifyDockWidget(simulDataDock,simulOptDock);

		acts.itemEditModeAct->trigger();
		simulscene->clearSelection();
		acts.calculate->trigger();
		gview->centerOnProbe();

	}


}


void lsim::createStatusBar() {
	statusBar()->showMessage (tr ("Willkommen zu lsim"));
}

void lsim::createScene() {
	simulscene = new SimulScene();
	gview->setScene(simulscene);
	simulscene->addRect(-qApp->desktop()->screenGeometry().width(),-qApp->desktop()->screenGeometry().height(), qApp->desktop()->screenGeometry().width()*2, qApp->desktop()->screenGeometry().height()*2)->setVisible(false);
}

void lsim::createDocks() {

	//steps box
	QSpinBox *steps_box = new QSpinBox;
	steps_box->setRange(1, 5e+6);
	steps_box->setKeyboardTracking(false);
	steps_box->setValue(simulscene->getSteps());
	connect(steps_box, SIGNAL(valueChanged(int)),simulscene, SLOT(setSteps(int)));
	connect(simulscene, SIGNAL(stepsChanged(int)),steps_box, SLOT(setValue(int)));

	//time Per step Box
	ExpDoubleSpinBox *time_step_box = new ExpDoubleSpinBox;
	time_step_box->setRange(-pow(10,-100), pow(10,66));
	time_step_box->setDecimals(100);
	time_step_box->setDisplayDecimals(3);
	time_step_box->setKeyboardTracking(false);
	time_step_box->setSuffix(" s");
	time_step_box->setValue(simulscene->getTimePerStep());
	connect(time_step_box, SIGNAL(valueChanged(double)),simulscene, SLOT(setTimePerStep(double)));
	connect(simulscene, SIGNAL(timePerStepChanged(double)),time_step_box, SLOT(setValue( double )));


	//automatische Schrittlaengen-box
	ExpDoubleSpinBox *adaptive_step_length_box = new ExpDoubleSpinBox;
	adaptive_step_length_box->setRange(pow(10,-100), pow(10,66));
	adaptive_step_length_box->setDecimals(100);
	adaptive_step_length_box->setDisplayDecimals(3);
	adaptive_step_length_box->setSuffix(" px");
	adaptive_step_length_box->setKeyboardTracking(false);
	adaptive_step_length_box->setValue(simulscene->getProbeChargeItem()->getAdaptiveStepLength());
	connect(adaptive_step_length_box, SIGNAL(valueChanged(double)),simulscene->getProbeChargeItem(), SLOT(setAdaptiveStepLength(double)));
	connect(simulscene->getProbeChargeItem(), SIGNAL(adaptiveStepLengthChanged(double)),adaptive_step_length_box, SLOT(setValue( double )));

	//automatische schrittanpassungsbox
	QCheckBox *adaptive_time_step_box = new QCheckBox("");
	adaptive_time_step_box->setChecked(simulscene->getProbeChargeItem()->isAdaptiveStepControlEnabled());
	connect(adaptive_time_step_box, SIGNAL(toggled(bool)),simulscene->getProbeChargeItem(), SLOT(setAdaptiveStepControl(bool)));
	connect(simulscene->getProbeChargeItem(), SIGNAL(adaptiveStepControlChanged(bool)),adaptive_time_step_box, SLOT(setChecked(bool)));
	connect(adaptive_time_step_box, SIGNAL(toggled(bool)),adaptive_step_length_box, SLOT(setEnabled(bool)));

	//meterPerPixel Box
	ExpDoubleSpinBox *meter_per_px_box = new ExpDoubleSpinBox;
	meter_per_px_box->setRange(pow(10,-100), pow(10,66));
	meter_per_px_box->setDecimals(100);
	meter_per_px_box->setDisplayDecimals(3);
	meter_per_px_box->setSuffix(" m");
	meter_per_px_box->setKeyboardTracking(false);
	meter_per_px_box->setValue(simulscene->getMeterPerPx());
	connect(meter_per_px_box, SIGNAL(valueChanged(double)),simulscene, SLOT(setMeterPerPx(double)));
	connect(simulscene, SIGNAL(meterPerPxChanged(double)),meter_per_px_box, SLOT(setValue( double )));

	//description labels
	QLabel *time_per_step_label = new QLabel(tr("Zeit pro Schritt:"));
	QLabel *steps_label = new QLabel(tr("Maximale Schrittanzahl:"));
	QLabel *meter_per_pixel_label = new QLabel(tr("Ein Pixel entspricht:"));
	QLabel *adaptive_time_step_label = new QLabel(tr("Automatische Schrittl\344nge:"));
	QLabel *adaptive_time_step_box_label = new QLabel(tr("Schrittl\344nge:"));


	//Scene settings Layout
	QGridLayout *sceneGridLayout = new QGridLayout;
	sceneGridLayout->addWidget(steps_label,0,0,Qt::AlignRight);
	sceneGridLayout->addWidget(steps_box,0,1);
	sceneGridLayout->addWidget(time_per_step_label,1,0,Qt::AlignRight);
	sceneGridLayout->addWidget(time_step_box,1,1);
	sceneGridLayout->addWidget(adaptive_time_step_label,2,0,Qt::AlignRight);
	sceneGridLayout->addWidget(adaptive_time_step_box,2,1);
	sceneGridLayout->addWidget(adaptive_time_step_box_label,3,0,Qt::AlignRight);
	sceneGridLayout->addWidget(adaptive_step_length_box,3,1);
	sceneGridLayout->addWidget(meter_per_pixel_label,4,0,Qt::AlignRight);
	sceneGridLayout->addWidget(meter_per_px_box,4,1);



	QGroupBox *sceneGroupBox = new QGroupBox(tr("Allgemeines"));
	sceneGroupBox->setLayout(sceneGridLayout);

	QVBoxLayout *allgVBoxLayout = new QVBoxLayout();
	allgVBoxLayout->addWidget(sceneGroupBox);
	allgVBoxLayout->addStretch();

	QWidget *allgWidget = new QWidget;
	allgWidget->setLayout(allgVBoxLayout);
	
	sceneDock = new QDockWidget(tr("Allgemeines"), this);
	sceneDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
	sceneDock->setWidget((allgWidget));
	//sceneDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
	//addDockWidget(Qt::LeftDockWidgetArea, sceneDock);

	//**************************************************************************


	
	//FlugbahnAnzeigeBox
	QCheckBox *flight_path_box = new QCheckBox("");
	flight_path_box->setChecked(simulscene->isFlightPathVisible());
	connect(flight_path_box, SIGNAL(toggled(bool)),simulscene, SLOT(setFlightPathVisible(bool)));
	connect(simulscene, SIGNAL(flightPathVisibilityChanged(bool)),flight_path_box, SLOT(setChecked(bool)));

	//timer laenge Box
	QDoubleSpinBox *timer_box = new QDoubleSpinBox;
	timer_box->setRange(1.0, 1e+10);
	timer_box->setDecimals(3);
	//timer_box->setKeyboardTracking(false);
	timer_box->setValue(simulscene->getTimeLineDuration()/1000.0);
	timer_box->setSuffix(" s");
	connect(timer_box, SIGNAL(valueChanged(double)),this, SLOT(timeLineDurationSetWrapperToMsec(double)));
	connect(timer_box, SIGNAL(valueChanged(double)),acts.timerStop, SLOT(trigger()));
	//connect(timer_box, SIGNAL(valueChanged(int)),simulscene, SLOT(stopTimer()));
	connect(this, SIGNAL(timeLineDurationChangedSec(double)),timer_box, SLOT(setValue(double)));

	//geschwindigkeitsbox
	QDoubleSpinBox *simul_speed_box = new QDoubleSpinBox;
	simul_speed_box->setRange(0, 1e+10);
	simul_speed_box->setDecimals(3);
	//timer_box->setKeyboardTracking(false);
	simul_speed_box->setValue(simulscene->getPxPerSec());
	simul_speed_box->setSuffix(" px/s");
	connect(simul_speed_box, SIGNAL(valueChanged(double)),simulscene, SLOT(setPxPerSec(double)));
	connect(simulscene, SIGNAL(pxPerSecChanged(double)),simul_speed_box, SLOT(setValue(double)));

	//Echte simulationsdauer
	QLabel *real_simul_time_shower = new QLabel(tr("keine Daten"));
	real_simul_time_shower->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene, SIGNAL(realSimulTimeChanged(QString)),real_simul_time_shower, SLOT(setText(QString)));


	//description labels
	QLabel *flight_path_label = new QLabel(tr("Flugbahn anzeigen:"));
	QLabel *timer_label = new QLabel(tr("Dauer der Animation:"));
	QLabel *real_simul_time_label = new QLabel(tr("\"Reale\" Simulationsdauer:"));
	QLabel *simul_speed_label = new QLabel(tr("Simulationsgeschwindigkeit:"));

	//grid layout
	QGridLayout *simulOptGridLayout = new QGridLayout;
	simulOptGridLayout->addWidget(flight_path_label,3,0,Qt::AlignRight);
	simulOptGridLayout->addWidget(flight_path_box,3,1);
	simulOptGridLayout->addWidget(timer_label,4,0,Qt::AlignRight);
	simulOptGridLayout->addWidget(timer_box,4,1);
	simulOptGridLayout->addWidget(simul_speed_label,5,0,Qt::AlignRight);
	simulOptGridLayout->addWidget(simul_speed_box,5,1);
	simulOptGridLayout->addWidget(real_simul_time_label,6,0,Qt::AlignRight);
	simulOptGridLayout->addWidget(real_simul_time_shower,6,1);

	QGroupBox *simulOptGroupBox = new QGroupBox(tr("Allgemeines"));
	simulOptGroupBox->setLayout(simulOptGridLayout);

	QVBoxLayout *simulOptVBoxLayout = new QVBoxLayout();
	simulOptVBoxLayout->addWidget(simulOptGroupBox);
	simulOptVBoxLayout->addStretch();

	QWidget *simulOptWidget = new QWidget;
	simulOptWidget->setLayout(simulOptVBoxLayout);

	simulOptDock = new QDockWidget(tr("Allgemeines"), this);
	simulOptDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
	simulOptDock->setWidget(simulOptWidget);

	//************************************************************************


	//**************************************************************************
	//simuldatadock

	//labels position
	QLabel *xPxPosLabel = new QLabel("0,00 px");
	xPxPosLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene->getProbeChargeItem(), SIGNAL(ScenePosXChangedPixel(QString)),xPxPosLabel, SLOT(setText(QString)));

	QLabel *yPxPosLabel = new QLabel("0,00 px");
	yPxPosLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene->getProbeChargeItem(), SIGNAL(ScenePosYChangedPixel(QString)),yPxPosLabel, SLOT(setText(QString)));

	QLabel *xMPosLabel = new QLabel("0,00 m");
	xMPosLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene->getProbeChargeItem(), SIGNAL(ScenePosXChangedMeter(QString)),xMPosLabel, SLOT(setText(QString)));

	QLabel *yMPosLabel = new QLabel("0,00 m");
	yMPosLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene->getProbeChargeItem(), SIGNAL(ScenePosYChangedMeter(QString)),yMPosLabel, SLOT(setText(QString)));
	//grid layout
	QGridLayout *ProbePosGridLayout = new QGridLayout;
	ProbePosGridLayout->addWidget(new QLabel("x:"),0,0,Qt::AlignCenter);
	ProbePosGridLayout->addWidget(xPxPosLabel,0,1,Qt::AlignCenter);
	ProbePosGridLayout->addWidget(xMPosLabel,0,2,Qt::AlignCenter);
	ProbePosGridLayout->addWidget(new QLabel("y:"),1,0,Qt::AlignCenter);
	ProbePosGridLayout->addWidget(yPxPosLabel,1,1,Qt::AlignCenter);
	ProbePosGridLayout->addWidget(yMPosLabel,1,2,Qt::AlignCenter);

	QGroupBox *ProbePosGroupBox = new QGroupBox(tr("Position"));
	ProbePosGroupBox->setLayout(ProbePosGridLayout);

	//labels speed
	QLabel *xSpeedLabel = new QLabel("0,00 m/s");
	xSpeedLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene, SIGNAL(probeSpeedXChanged(QString)),xSpeedLabel, SLOT(setText(QString)));

	QLabel *ySpeedLabel = new QLabel("0,00 m/s");
	ySpeedLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene, SIGNAL(probespeedYChanged(QString)),ySpeedLabel, SLOT(setText(QString)));

	QLabel *gesSpeedLabel = new QLabel("0,00 m/s");
	gesSpeedLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
	connect(simulscene, SIGNAL(probeSpeedChanged(QString)),gesSpeedLabel, SLOT(setText(QString)));
	//grid layout
	QGridLayout *ProbeSpeedGridLayout = new QGridLayout;
	ProbeSpeedGridLayout->addWidget(new QLabel("x:"),0,0,Qt::AlignCenter);
	ProbeSpeedGridLayout->addWidget(xSpeedLabel,0,1,Qt::AlignCenter);
	ProbeSpeedGridLayout->addWidget(new QLabel("y:"),1,0,Qt::AlignCenter);
	ProbeSpeedGridLayout->addWidget(ySpeedLabel,1,1,Qt::AlignCenter);
	ProbeSpeedGridLayout->addWidget(new QLabel(tr("Betrag gesamt:")),2,0,Qt::AlignCenter);
	ProbeSpeedGridLayout->addWidget(gesSpeedLabel,2,1,Qt::AlignCenter);

	QGroupBox *ProbeSpeedGroupBox = new QGroupBox(tr("Geschwindigkeit"));
	ProbeSpeedGroupBox->setLayout(ProbeSpeedGridLayout);




	//Daten an aus box
	QCheckBox *data_on_off_box = new QCheckBox("");
	data_on_off_box->setChecked(simulscene->getScenePosLablesActive());
	connect(data_on_off_box, SIGNAL(toggled(bool)),simulscene, SLOT(setScenePosLablesActive(bool)));

	//Ausgrauen bei aus
	ProbePosGroupBox->setEnabled(simulscene->getScenePosLablesActive());
	ProbeSpeedGroupBox->setEnabled(simulscene->getScenePosLablesActive());
	connect(data_on_off_box, SIGNAL(toggled(bool)),ProbePosGroupBox, SLOT(setEnabled(bool)));
	connect(data_on_off_box, SIGNAL(toggled(bool)),ProbeSpeedGroupBox, SLOT(setEnabled(bool)));


	connect(simulscene, SIGNAL(scenePosLablesActiveChanged(bool)),data_on_off_box, SLOT(setChecked(bool)));

	QGridLayout *ProbeDisplayGridLayout = new QGridLayout;
	ProbeDisplayGridLayout->addWidget(new QLabel("Anzeige aktivieren"),0,0,Qt::AlignCenter);
	ProbeDisplayGridLayout->addWidget(data_on_off_box,0,1,Qt::AlignCenter);

	QGroupBox *dataDisplayGroupBox = new QGroupBox(tr(""));
	dataDisplayGroupBox->setLayout(ProbeDisplayGridLayout);



	QVBoxLayout *simulDataVBoxLayout = new QVBoxLayout();
	simulDataVBoxLayout->addWidget(dataDisplayGroupBox);
	simulDataVBoxLayout->addWidget(ProbePosGroupBox);
	simulDataVBoxLayout->addWidget(ProbeSpeedGroupBox);
	simulDataVBoxLayout->addStretch();

	QWidget *simulDataWidget = new QWidget;
	simulDataWidget->setLayout(simulDataVBoxLayout);

	simulDataDock = new QDockWidget(tr("Daten"), this);
	simulDataDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
	simulDataDock->setWidget(simulDataWidget);

	//************************************************************************



	fieldItemEditDock = new QDockWidget(tr("Feldeinstellungen"), this); 
	fieldItemEditDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
	fieldItemEditDock->setWidget(new QWidget);
	//fieldItemEditDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
	//addDockWidget(Qt::LeftDockWidgetArea, fieldItemEditDock);
	connect (simulscene, SIGNAL(selectionChanged ()) , this, SLOT(updateDockFieldWidget()));
	updateDockFieldWidget();


	probeItemDock = new QDockWidget(tr("Probleladung"), this);
	probeItemDock->setWidget(simulscene->getProbeDockWidget());
	//probeItemDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
	//addDockWidget(Qt::LeftDockWidgetArea, probeItemDock);



	//tabifyDockWidget(probeItemDock,fieldItemEditDock);
	//tabifyDockWidget(fieldItemEditDock, sceneDock);
	setDockOptions(QMainWindow::VerticalTabs);

}

void lsim::timeLineDurationChangeWrapperToSec(int length) {
	emit timeLineDurationChangedSec((double)length/1000.0);
}

void lsim::timeLineDurationSetWrapperToMsec(double length) {
	simulscene->setTimeLineDuration(int(length*1000));
}

void lsim::actModeSwitcher(QAction *action) {
	simulscene->setSceneMode((SimulScene::SceneMode)action->data().toInt());
}

void lsim::actWindowModeSwitcher(QAction *action) {
	setMode((lsim::WindowMode)action->data().toInt());
}

void lsim::setSceneMode(int mode) {
	for (int i=0;i < modeChangeActGroup->actions().count();++i){ //nur das aktuelle checked setzen
		if(modeChangeActGroup->actions().at(i)->data().toInt() == mode) {
			modeChangeActGroup->actions().at(i)->setChecked(true);
		} 
		else {
			modeChangeActGroup->actions().at(i)->setChecked(false);
		}
	}


/*
//Problem mit resizeRects, warum auch immer :(	
	//je nach sceneMode den cursor eintellen
	switch (mode) {
		case SimulScene::HomoEFieldItemInsert:
			gview->setCursor(Qt::CrossCursor);
			break;
		default:
			gview->unsetCursor();

	}*/

}


lsim::~lsim() {

}



/*!
    \fn lsim::updateDockFieldWidget()
 */
void lsim::updateDockFieldWidget() {

	QLabel* currLabel = new QLabel(tr("Bitte ein Feld ausw\344hlen"));
	currLabel->setWordWrap(true);
	currLabel->setAlignment(Qt::AlignCenter);
	QWidget *currDockWidget =currLabel;//simulscene->getFieldListWidget();
	if(simulscene->selectedItems().count() == 1) {
		QGraphicsItem *currItem = simulscene->selectedItems().first();
		if (FieldItem::isFieldItem(currItem)) {
			FieldItem *currFieldItem = qgraphicsitem_cast<FieldItem *>(currItem);
			currDockWidget  = currFieldItem->getDockWidget();
		}
	}

	fieldItemEditDock->setWidget(currDockWidget);
}

void lsim::clearAnyFocus() {
	if( qApp->focusWidget() !=0) qApp->focusWidget()->clearFocus();
}

void lsim::startCalculation() {
	clearAnyFocus();
	
	if (simulscene->getMeterPerPx() == 0) {
		QMessageBox::critical (this,tr("B\366ser Fehler!"),tr("Die Wegl\344nge pro Pixel darf nicht 0 sein!"));
		setMode(EditMode);
		return;
	}

	if (simulscene->getProbeChargeItem()->getMasse(0) == 0) {
		QMessageBox::critical (this,tr("B\366ser Fehler!"),tr("Die Masse der Probeladung darf nicht 0 sein!"));
		setMode(EditMode);
		return;
	}
	if (simulscene->getProbeChargeItem()->getAdaptiveStepLength() == 0) {
		QMessageBox::critical (this,tr("B\366ser Fehler!"),tr("Die Schrittweite darf nicht 0 sein!"));
		setMode(EditMode);
		return;
	}

	statusBar()->showMessage(tr("Berechne Flugbahn. Bitte Warten ..."));
	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

	simulscene->startCalculation();

	QApplication::restoreOverrideCursor();
	statusBar()->clearMessage();
}
void lsim::startTimer() {
	clearAnyFocus();
	simulscene->startTimer();
}
void lsim::handleDockLocationChange() {
	
}

void lsim::handleUpDownActionChanges() {
	if (simulscene->selectedItems().isEmpty() || 
	    simulscene->selectedItems().first()->zValue() == simulscene->getHighestZIndexFieldItems() ) {
		acts.moveItemUp->setEnabled(false);
		acts.moveItemOnTop->setEnabled(false);
	} else {
		acts.moveItemUp->setEnabled(true);
		acts.moveItemOnTop->setEnabled(true);
	}

	if (simulscene->selectedItems().isEmpty() || 
	    simulscene->selectedItems().first()->zValue() == simulscene->getLowestZIndexFieldItems() ) {
		acts.moveItemDown->setEnabled(false);
		acts.moveItemOnBottom->setEnabled(false);
	} else {
		acts.moveItemDown->setEnabled(true);
		acts.moveItemOnBottom->setEnabled(true);
	}	
}

lsim::WindowMode lsim::getMode() const {
	return myMode;
}


void lsim::setMode ( const WindowMode& theValue ) {
	//if(myMode == theValue) return;
	myMode = theValue;
	initWindowMode(theValue);
	for (int i=0;i < windowModeActGroup->actions().count();++i){ //nur das aktuelle checked setzen
		if(windowModeActGroup->actions().at(i)->data().toInt() == myMode) {
			windowModeActGroup->actions().at(i)->setChecked(true);
		} 
		else {
			windowModeActGroup->actions().at(i)->setChecked(false);
		}
	}
	emit windowModeChanged(theValue);
}

void lsim::resetAllActionSlot() {
	QMessageBox::StandardButton button = QMessageBox::question ( this, tr("Frage"), tr("Wirklich Zur\374cksetzen?"), QMessageBox::Yes|QMessageBox::No) ;
	if (button==QMessageBox::Yes) resetAll();
}

void lsim::resetAll() {
	setMode(EditMode);
	simulscene->resetScene();
	gview->centerOn(0,0);

}

void lsim::goToFullscreen(bool yesno) {
	if (yesno && windowState() == Qt::WindowFullScreen) return;
	if (!yesno && windowState() != Qt::WindowFullScreen) return;

	setWindowState(windowState() ^ Qt::WindowFullScreen);
	//qDebug()<< (windowState() == Qt::WindowFullScreen);
	emit fullScreenModeChanged(windowState() == Qt::WindowFullScreen);
}
