00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "mainwindow.h"
00021
00022 #include <QtCore/QVariantList>
00023
00024 #include <KFileDialog>
00025 #include <KStandardAction>
00026 #include <KActionCollection>
00027 #include <KAction>
00028 #include <KStatusBar>
00029 #include <KMessageBox>
00030 #include <KConfigDialog>
00031 #include <KLocalizedString>
00032 #include <KPluginSelector>
00033 #include <KRun>
00034 #include <KRecentFilesAction>
00035 #include <KDE/KTabWidget>
00036 #include <KDE/KToolBar>
00037 #include <KDE/KRichTextEdit>
00038
00039 #include <core/debughelper.h>
00040 #include <engine/game.h>
00041 #include <engine/gameproject.h>
00042 #include <engine/scene.h>
00043
00044 #include "lib/plugin.h"
00045 #include "lib/pluginmanager.h"
00046 #include "lib/objectmanager.h"
00047 #include "lib/historymanager.h"
00048 #include "lib/selectionmanager.h"
00049 #include "lib/dockmanager.h"
00050 #include "lib/filemanager.h"
00051
00052 #include "gluoncreatorsettings.h"
00053 #include "dialogs/configdialog.h"
00054 #include <QVBoxLayout>
00055 #include <KParts/PartManager>
00056
00057 using namespace GluonCreator;
00058
00059 class MainWindow::MainWindowPrivate
00060 {
00061 public:
00062 MainWindowPrivate()
00063 {
00064 viewPart = 0;
00065 }
00066
00067 bool modified;
00068 QString fileName;
00069 KRecentFilesAction* recentFiles;
00070 ProjectSelectionDialog* projectDialog;
00071
00072 KParts::ReadOnlyPart* viewPart;
00073 };
00074
00075 MainWindow::MainWindow( const QString& fileName )
00076 : KParts::MainWindow(),
00077 d( new MainWindowPrivate )
00078 {
00079 d->modified = false;
00080
00081 GluonCore::GluonObjectFactory::instance()->loadPlugins();
00082
00083 PluginManager::instance()->setParent( this );
00084 ObjectManager::instance()->setParent( this );
00085 HistoryManager::instance()->setParent( this );
00086 SelectionManager::instance()->setParent( this );
00087 DockManager::instance()->setParent( this );
00088 FileManager::instance()->setParent( this );
00089 DockManager::instance()->setMainWindow( this );
00090
00091 setDockNestingEnabled( true );
00092 setCorner( Qt::TopLeftCorner, Qt::LeftDockWidgetArea );
00093 setCorner( Qt::BottomLeftCorner, Qt::LeftDockWidgetArea );
00094 setCorner( Qt::TopRightCorner, Qt::RightDockWidgetArea );
00095 setCorner( Qt::BottomRightCorner, Qt::RightDockWidgetArea );
00096
00097 PluginManager::instance()->setMainWindow( this );
00098 PluginManager::instance()->loadPlugins();
00099
00100 setupActions();
00101 setupGUI();
00102
00103 d->projectDialog = new ProjectSelectionDialog( this );
00104 d->projectDialog->setModal( true );
00105 connect( d->projectDialog, SIGNAL( accepted() ), SLOT( projectDialogClosed() ) );
00106
00107 DockManager::instance()->setDocksEnabled( false );
00108 DockManager::instance()->setDocksLocked( GluonCreator::Settings::lockLayout() );
00109
00110 KTabWidget* tab = new KTabWidget( this );
00111 tab->setCloseButtonEnabled( true );
00112 tab->setMovable( true );
00113 tab->setEnabled( false );
00114
00115 KService::Ptr viewerService = KService::serviceByDesktopName( "gluon_viewer_part" );
00116 if( viewerService )
00117 {
00118 d->viewPart = viewerService->createInstance<KParts::ReadOnlyPart>( 0, QVariantList() << QString( "autoplay=false" ) );
00119 if( d->viewPart )
00120 {
00121 d->viewPart->widget()->setObjectName( "gluon_viewer_part" );
00122 tab->addTab( d->viewPart->widget(), i18nc( "View Game Tab", "View" ) );
00123 }
00124 }
00125
00126 if( !d->viewPart )
00127 {
00128 KMessageBox::error( this, "Could not load the Viewer part. Is it installed correctly?" );
00129 }
00130
00131 tab->addTab( new QWidget(), i18nc( "Edit Game Tab", "Edit" ) );
00132 setCentralWidget( tab );
00133
00134 FileManager::instance()->setTabWidget( tab );
00135 connect( FileManager::instance()->partManager(), SIGNAL( activePartChanged( KParts::Part* ) ), this, SLOT( createGUI( KParts::Part* ) ) );
00136 FileManager::instance()->partManager()->addPart( d->viewPart );
00137
00138 if( fileName.isEmpty() )
00139 {
00140 showNewProjectDialog();
00141 }
00142 else
00143 {
00144 openProject( fileName );
00145 }
00146 }
00147
00148 MainWindow::~MainWindow()
00149 {
00150 d->recentFiles->saveEntries( KGlobal::config()->group( "Recent Files" ) );
00151 GluonCreator::Settings::setLockLayout( actionCollection()->action( "lockLayout" )->isChecked() );
00152 GluonCreator::Settings::self()->writeConfig();
00153 GluonEngine::Game::instance()->stopGame();
00154 }
00155
00156 void MainWindow::openProject( KUrl url )
00157 {
00158 openProject( url.path() );
00159 }
00160
00161 void MainWindow::openProject( const QString& fileName )
00162 {
00163 if( !fileName.isEmpty() && QFile::exists( fileName ) && d->viewPart )
00164 {
00165 statusBar()->showMessage( i18n( "Opening project..." ) );
00166
00167 d->viewPart->openUrl( KUrl( fileName ) );
00168 GluonEngine::Game::instance()->initializeAll();
00169 GluonEngine::Game::instance()->drawAll();
00170
00171 d->fileName = fileName;
00172
00173 d->recentFiles->addUrl( KUrl( fileName ) );
00174
00175 actionCollection()->action( KStandardAction::name( KStandardAction::Save ) )->setEnabled( true );
00176 actionCollection()->action( KStandardAction::name( KStandardAction::SaveAs ) )->setEnabled( true );
00177 actionCollection()->action( "newObject" )->setEnabled( true );
00178 actionCollection()->action( "newScene" )->setEnabled( true );
00179 actionCollection()->action( "playPauseGame" )->setEnabled( true );
00180 actionCollection()->action( "addAsset" )->setEnabled( true );
00181 actionCollection()->action( "chooseEntryPoint" )->setEnabled( true );
00182
00183 DockManager::instance()->setDocksEnabled( true );
00184
00185 if( centralWidget() )
00186 centralWidget()->setEnabled( true );
00187
00188 statusBar()->showMessage( i18n( "Project successfully opened" ) );
00189 setCaption( i18n( "%1 - Gluon Creator", fileName.section( '/', -1 ) ) );
00190 HistoryManager::instance()->clear();
00191 connect( HistoryManager::instance(), SIGNAL( historyChanged( const QUndoCommand* ) ), SLOT( historyChanged() ) );
00192 }
00193 else
00194 {
00195 statusBar()->showMessage( i18n( "Unable to open project file..." ) );
00196 }
00197 }
00198
00199 void MainWindow::saveProject()
00200 {
00201 saveProject( d->fileName );
00202 }
00203
00204 void MainWindow::saveProject( const QString& fileName )
00205 {
00206 if( !fileName.isEmpty() )
00207 {
00208 statusBar()->showMessage( i18n( "Saving project..." ) );
00209 GluonEngine::Game::instance()->gameProject()->setFilename( QUrl( fileName ) );
00210 QDir::setCurrent( KUrl( fileName ).directory() );
00211 if( !GluonEngine::Game::instance()->gameProject()->saveToFile() )
00212 {
00213 KMessageBox::error( this, i18n( "Could not save file." ) );
00214 return;
00215 }
00216 statusBar()->showMessage( i18n( "Project successfully saved." ) );
00217 setCaption( i18n( "%1 - Gluon Creator", fileName.section( '/', -1 ) ) );
00218 HistoryManager::instance()->setClean();
00219
00220 d->recentFiles->addUrl( KUrl( fileName ) );
00221 }
00222 else
00223 {
00224 saveProjectAs();
00225 }
00226 }
00227
00228 void MainWindow::saveProjectAs()
00229 {
00230 d->fileName = KFileDialog::getSaveFileName( KUrl(), i18n( "*.gluon|Gluon Project Files" ) );
00231 if( !d->fileName.isEmpty() ) saveProject();
00232 }
00233
00234 void MainWindow::setupActions()
00235 {
00236 KStandardAction::openNew( this, SLOT( showNewProjectDialog() ), actionCollection() );
00237 KStandardAction::open( this, SLOT( showOpenProjectDialog() ), actionCollection() );
00238 KStandardAction::save( this, SLOT( saveProject() ), actionCollection() )->setEnabled( false );
00239 KStandardAction::saveAs( this, SLOT( saveProjectAs() ), actionCollection() )->setEnabled( false );;
00240 KStandardAction::quit( this, SLOT( close() ), actionCollection() );
00241 KStandardAction::preferences( this, SLOT( showPreferences() ), actionCollection() );
00242
00243 KAction* undo = KStandardAction::undo( HistoryManager::instance(), SLOT( undo() ), actionCollection() );
00244 undo->setEnabled( false );
00245 connect( HistoryManager::instance(), SIGNAL( canUndoChanged( bool ) ), undo, SLOT( setEnabled( bool ) ) );
00246
00247 KAction* redo = KStandardAction::redo( HistoryManager::instance(), SLOT( redo() ), actionCollection() );
00248 redo->setEnabled( false );
00249 connect( HistoryManager::instance(), SIGNAL( canRedoChanged( bool ) ), redo, SLOT( setEnabled( bool ) ) );
00250
00251 connect( HistoryManager::instance(), SIGNAL( cleanChanged( bool ) ), SLOT( cleanChanged( bool ) ) );
00252
00253 d->recentFiles = KStandardAction::openRecent( this, SLOT( openProject( KUrl ) ), actionCollection() );
00254 d->recentFiles->loadEntries( KGlobal::config()->group( "Recent Files" ) );
00255
00256 KAction* newObject = new KAction( KIcon( "document-new" ), i18n( "New Object" ), actionCollection() );
00257 actionCollection()->addAction( "newObject", newObject );
00258 newObject->setEnabled( false );
00259 connect( newObject, SIGNAL( triggered( bool ) ), ObjectManager::instance(), SLOT( createNewGameObject() ) );
00260
00261 KAction* newScene = new KAction( KIcon( "document-new" ), i18n( "New Scene" ), actionCollection() );
00262 actionCollection()->addAction( "newScene", newScene );
00263 newScene->setEnabled( false );
00264 connect( newScene, SIGNAL( triggered( bool ) ), ObjectManager::instance(), SLOT( createNewScene() ) );
00265
00266 KAction* play = new KAction( KIcon( "media-playback-start" ), i18n( "Play Game" ), actionCollection() );
00267 actionCollection()->addAction( "playPauseGame", play );
00268 play->setCheckable( true );
00269 play->setEnabled( false );
00270 connect( play, SIGNAL( triggered( bool ) ), SLOT( playPauseGame( bool ) ) );
00271
00272 KAction* stop = new KAction( KIcon( "media-playback-stop" ), i18n( "Stop Game" ), actionCollection() );
00273 actionCollection()->addAction( "stopGame", stop );
00274 stop->setEnabled( false );
00275 connect( stop, SIGNAL( triggered( bool ) ), SLOT( stopGame() ) );
00276
00277 KAction* addAsset = new KAction( KIcon( "document-new" ), i18n( "Add Assets..." ), actionCollection() );
00278 actionCollection()->addAction( "addAsset", addAsset );
00279 addAsset->setEnabled( false );
00280 connect( addAsset, SIGNAL( triggered( bool ) ), SLOT( addAsset() ) );
00281
00282 KAction* chooseEntryPoint = new KAction( KIcon( "media-playback-start" ), i18n( "Set current scene as entry point" ), actionCollection() );
00283 actionCollection()->addAction( "chooseEntryPoint", chooseEntryPoint );
00284 chooseEntryPoint->setEnabled( false );
00285 connect( chooseEntryPoint, SIGNAL( triggered( bool ) ), SLOT( chooseEntryPoint() ) );
00286
00287 KAction* lockLayout = new KAction( KIcon( "object-locked" ), i18n( "Lock layout" ), actionCollection() );
00288 actionCollection()->addAction( "lockLayout", lockLayout );
00289 lockLayout->setCheckable( true );
00290 lockLayout->setChecked( GluonCreator::Settings::lockLayout() );
00291 connect( lockLayout, SIGNAL( triggered( bool ) ), DockManager::instance(), SLOT( setDocksLocked( bool ) ) );
00292 }
00293
00294 void MainWindow::showPreferences()
00295 {
00296 if( KConfigDialog::showDialog( "settings" ) )
00297 {
00298 return;
00299 }
00300 ConfigDialog* dialog = new ConfigDialog( this, "settings", GluonCreator::Settings::self() );
00301 dialog->setAttribute( Qt::WA_DeleteOnClose );
00302 dialog->show();
00303 }
00304
00305 void MainWindow::playPauseGame( bool checked )
00306 {
00307 if( checked )
00308 {
00309 if( GluonEngine::Game::instance()->isRunning() )
00310 {
00311 actionCollection()->action( "playPauseGame" )->setIcon( KIcon( "media-playback-pause" ) );
00312 actionCollection()->action( "playPauseGame" )->setText( i18n( "Pause Game" ) );
00313 GluonEngine::Game::instance()->setPause( false );
00314 }
00315 else
00316 {
00317 actionCollection()->action( "playPauseGame" )->setIcon( KIcon( "media-playback-pause" ) );
00318 actionCollection()->action( "playPauseGame" )->setText( i18n( "Pause Game" ) );
00319 actionCollection()->action( "stopGame" )->setEnabled( true );
00320
00321 QString currentSceneName = GluonEngine::Game::instance()->currentScene()->fullyQualifiedName();
00322 saveProject();
00323
00324
00325 setFocus();
00326
00327
00328
00329 GluonEngine::Game::instance()->runGame();
00330
00331
00332 actionCollection()->action( "playPauseGame" )->setEnabled( true );
00333 actionCollection()->action( "playPauseGame" )->setIcon( KIcon( "media-playback-start" ) );
00334 actionCollection()->action( "playPauseGame" )->setText( i18n( "Play Game" ) );
00335 actionCollection()->action( "playPauseGame" )->setChecked( false );
00336 actionCollection()->action( "stopGame" )->setEnabled( false );
00337
00338 openProject( d->fileName );
00339
00340 DEBUG_BLOCK;
00341 DEBUG_TEXT( currentSceneName );
00342 GluonEngine::Game::instance()->setCurrentScene( currentSceneName );
00343 }
00344 }
00345 else
00346 {
00347 actionCollection()->action( "playPauseGame" )->setIcon( KIcon( "media-playback-start" ) );
00348 actionCollection()->action( "playPauseGame" )->setText( i18n( "Play Game" ) );
00349 GluonEngine::Game::instance()->setPause( true );
00350 }
00351 }
00352
00353 void MainWindow::stopGame()
00354 {
00355 GluonEngine::Game::instance()->stopGame();
00356 }
00357
00358 void MainWindow::historyChanged()
00359 {
00360 GluonEngine::Game::instance()->drawAll();
00361 GluonEngine::Game::instance()->currentScene()->savableDirty = true;
00362 d->modified = true;
00363
00364 setCaption( i18n( "%1 [modified]", d->fileName.isEmpty() ? i18n( "New Project" ) : d->fileName.section( '/', -1 ) ) );
00365 }
00366
00367 void MainWindow::cleanChanged( bool clean )
00368 {
00369 if( clean )
00370 {
00371 d->modified = false;
00372 setCaption( i18n( "%1", d->fileName.isEmpty() ? i18n( "New Project" ) : d->fileName.section( '/', -1 ) ) );
00373 }
00374 }
00375
00376 bool MainWindow::queryClose()
00377 {
00378 if( d->modified )
00379 {
00380 int code = KMessageBox::questionYesNoCancel( this, i18n( "The project has been changed. Do you want to save before closing?" ), i18n( "Save Before Closing?" ),
00381 KStandardGuiItem::save(), KStandardGuiItem::dontSave() );
00382
00383 if( code == KMessageBox::Cancel )
00384 return false;
00385
00386 if( code == KMessageBox::No )
00387 return true;
00388
00389 saveProject();
00390 return true;
00391 }
00392
00393 return true;
00394 }
00395
00396 void MainWindow::addAsset()
00397 {
00398 QStringList assets = KFileDialog::getOpenFileNames();
00399
00400 foreach( const QString & asset, assets )
00401 {
00402 ObjectManager::instance()->createNewAsset( asset );
00403 }
00404 }
00405
00406 void MainWindow::chooseEntryPoint()
00407 {
00408 if( GluonEngine::Game::instance()->gameProject() )
00409 {
00410 if( GluonEngine::Game::instance()->currentScene() )
00411 {
00412 GluonEngine::Game::instance()->gameProject()->setEntryPoint( GluonEngine::Game::instance()->currentScene() );
00413 }
00414 }
00415 }
00416
00417 void GluonCreator::MainWindow::showNewProjectDialog()
00418 {
00419 d->projectDialog->setPage( ProjectSelectionDialog::NewProjectPage );
00420 d->projectDialog->show();
00421 }
00422
00423 void GluonCreator::MainWindow::showOpenProjectDialog()
00424 {
00425 d->projectDialog->setPage( ProjectSelectionDialog::OpenProjectPage );
00426 d->projectDialog->show();
00427 }
00428
00429 void GluonCreator::MainWindow::projectDialogClosed()
00430 {
00431 openProject( d->projectDialog->fileName() );
00432 }