WQt4Gui.cpp 12.6 KB
Newer Older
1 2
//---------------------------------------------------------------------------
//
3
// Project: OpenWalnut ( http://www.openwalnut.org )
4
//
5 6
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
7
//
wiebel's avatar
wiebel committed
8
// This file is part of OpenWalnut.
9
//
wiebel's avatar
wiebel committed
10
// OpenWalnut is free software: you can redistribute it and/or modify
11 12 13 14
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
wiebel's avatar
wiebel committed
15
// OpenWalnut is distributed in the hope that it will be useful,
16 17 18 19 20
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
wiebel's avatar
wiebel committed
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 23 24
//
//---------------------------------------------------------------------------

ebaum's avatar
ebaum committed
25
#include <iostream>
26
#include <fstream>
27 28
#include <string>
#include <vector>
29

30
#include <boost/filesystem.hpp>
31
#include <boost/program_options.hpp>
32
#include <boost/shared_ptr.hpp>
33

34
#include <QtGui/QApplication>
35 36
#include <QtGui/QFileDialog>

Mathias Goldau's avatar
Mathias Goldau committed
37
#include "WMainWindow.h" // this has to be included before any other includes
38 39
#include "../../common/WConditionOneShot.h"
#include "../../common/WIOTools.h"
40
#include "../../common/WPreferences.h"
41
#include "../../common/WPathHelper.h"
Mathias Goldau's avatar
Mathias Goldau committed
42 43
#include "../../dataHandler/WDataHandler.h"
#include "../../dataHandler/WSubject.h"
44
#include "../../graphicsEngine/WGraphicsEngine.h"
Mathias Goldau's avatar
Mathias Goldau committed
45
#include "../../kernel/WKernel.h"
46
#include "../../kernel/WProjectFile.h"
47
#include "events/WModuleAssocEvent.h"
Mathias Goldau's avatar
Mathias Goldau committed
48
#include "events/WModuleCrashEvent.h"
49
#include "events/WModuleReadyEvent.h"
50
#include "events/WModuleRemovedEvent.h"
51 52
#include "events/WModuleConnectEvent.h"
#include "events/WModuleDisconnectEvent.h"
53
#include "events/WOpenCustomDockWidgetEvent.h"
Mathias Goldau's avatar
Mathias Goldau committed
54 55
#include "events/WRoiAssocEvent.h"
#include "events/WRoiRemoveEvent.h"
56
#include "events/WUpdateTextureSorterEvent.h"
57

Mathias Goldau's avatar
Mathias Goldau committed
58
#include "WQt4Gui.h"
ebaum's avatar
ebaum committed
59

60 61
WMainWindow* WQt4Gui::m_mainWindow = NULL;

Mathias Goldau's avatar
[ADD]  
Mathias Goldau committed
62 63
WQt4Gui::WQt4Gui( int argc, char** argv )
    : WGUI( argc, argv )
ebaum's avatar
ebaum committed
64 65 66
{
}

67
WQt4Gui::~WQt4Gui()
68
{
ebaum's avatar
ebaum committed
69
}
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
70

Mathias Goldau's avatar
[ADD]  
Mathias Goldau committed
71
bool WQt4Gui::parseOptions()
72
{
Mathias Goldau's avatar
Mathias Goldau committed
73 74
    namespace po = boost::program_options; // since the namespace is far to big we use a shortcut here
    po::options_description desc( "Allowed options" );
75 76 77

    desc.add_options()
        ( "help,h", "Prints this help message" )
78
        ( "project,p", po::value< std::string >(), "Project file to be loaded on startup." )
79 80
        ( "input,i", po::value< std::vector< std::string > >(), "Input data files that should be loaded automatically" )
        ( "timed-output,t", "Flag indicating if all log strings should have a time string preceding" );
81 82 83 84

    po::positional_options_description p;
    p.add( "input", -1 );

85 86
    try
    {
Mathias Goldau's avatar
[ADD]  
Mathias Goldau committed
87
        po::store( po::command_line_parser( m_argc, m_argv ).options( desc ).positional( p ).run(), m_optionsMap );
88
    }
Mathias Goldau's avatar
Mathias Goldau committed
89
    catch( const po::error &e )
90
    {
Mathias Goldau's avatar
Mathias Goldau committed
91
        std::cerr << e.what() << std::endl;
92 93 94 95 96 97 98 99 100 101
        return false;
    }

    po::notify( m_optionsMap );

    // print usage information if command line asks for help.
    if( m_optionsMap.count( "help" ) )
    {
        std::cout << desc << std::endl;
    }
102 103 104 105 106
    else if( m_optionsMap.count( "timed-output" ) )
    {
        WLogger::getLogger()->setDefaultFormat( "[%t] *%l [%s] %m \n" );
        wlog::info( "GUI" ) << "Timed output enabled";
    }
107 108 109
    return true;
}

110 111 112 113 114
void WQt4Gui::moduleError( boost::shared_ptr< WModule > module, const WException& exception )
{
    QCoreApplication::postEvent( m_mainWindow, new WModuleCrashEvent( module, exception.what() ) );
}

115 116 117 118 119
WMainWindow* WQt4Gui::getMainWindow()
{
    return m_mainWindow;
}

120 121
int WQt4Gui::run()
{
Mathias Goldau's avatar
[ADD]  
Mathias Goldau committed
122
    bool parsingSuccessful = parseOptions();
123 124 125

    if( !parsingSuccessful )
    {
126 127
        return 1;
    }
128

129
    // exit as fast as possible if command line asked for help. The ,essage has been printed by parseOptions().
130 131
    if( m_optionsMap.count( "help" ) )
    {
132
        return 1;
133 134
    }

135 136
    // init logger
    m_loggerConnection = WLogger::getLogger()->subscribeSignal( WLogger::AddLog, boost::bind( &WQt4Gui::slotAddLog, this, _1 ) );
137
    wlog::info( "GUI" ) << "Bringing up GUI";
138

139 140
    // the call path of the application
    boost::filesystem::path walnutBin = boost::filesystem::path( std::string( m_argv[0] ) );
141 142 143 144

    // setup path helper which provides several paths to others
    WPathHelper::getPathHelper()->setAppPath( walnutBin.parent_path() );

145
    // init preference system
146
    WPreferences::setPreferenceFile( WPathHelper::getConfigFile() );
147

Mathias Goldau's avatar
[ADD]  
Mathias Goldau committed
148
    QApplication appl( m_argc, m_argv, true );
149

150
    // startup graphics engine
151
    m_ge = WGraphicsEngine::getGraphicsEngine();
152

153
    // and startup kernel
154
    m_kernel = boost::shared_ptr< WKernel >( WKernel::instance( m_ge, shared_from_this() ) );
155
    m_kernel->run();
156 157 158
    t_ModuleErrorSignalHandlerType func = boost::bind( &WQt4Gui::moduleError, this, _1, _2 );
    m_kernel->getRootContainer()->addDefaultNotifier( WM_ERROR, func );

159
    // create the window
160
    m_mainWindow = new WMainWindow();
161
    m_mainWindow->setupGUI();
162
    m_mainWindow->show();
163

164
    // connect out loader signal with kernel
165 166 167
#ifdef _WIN32
    getLoadButtonSignal()->connect( boost::bind( &WKernel::loadDataSetsSynchronously, m_kernel, _1 ) );
#else
168
    getLoadButtonSignal()->connect( boost::bind( &WKernel::loadDataSets, m_kernel, _1 ) );
169
#endif
170

171 172 173
    WCondition::t_ConditionNotifierType newDatasetSignal = boost::bind( &WQt4Gui::slotUpdateTextureSorter, this );
    WDataHandler::getDefaultSubject()->getListChangeCondition()->subscribeSignal( newDatasetSignal );

174
    // bind the GUI's slot with the ready signal
175 176

    // Assoc Event
177
    t_ModuleGenericSignalHandlerType assocSignal = boost::bind( &WQt4Gui::slotAddDatasetOrModuleToTree, this, _1 );
178
    m_kernel->getRootContainer()->addDefaultNotifier( WM_ASSOCIATED, assocSignal );
179 180

    // Ready Event
181
    t_ModuleGenericSignalHandlerType readySignal = boost::bind( &WQt4Gui::slotActivateDatasetOrModuleInTree, this, _1 );
182
    m_kernel->getRootContainer()->addDefaultNotifier( WM_READY, readySignal );
183 184

    // Remove Event
185
    t_ModuleGenericSignalHandlerType removedSignal = boost::bind( &WQt4Gui::slotRemoveDatasetOrModuleInTree, this, _1 );
186 187
    m_kernel->getRootContainer()->addDefaultNotifier( WM_REMOVED, removedSignal );

188 189 190 191 192 193 194 195
    // Connect Event
    t_GenericSignalHandlerType connectionEstablishedSignal = boost::bind( &WQt4Gui::slotConnectionEstablished, this, _1, _2 );
    m_kernel->getRootContainer()->addDefaultNotifier( CONNECTION_ESTABLISHED, connectionEstablishedSignal );

    // Disconnect Event
    t_GenericSignalHandlerType connectionClosedSignal = boost::bind( &WQt4Gui::slotConnectionClosed, this, _1, _2 );
    m_kernel->getRootContainer()->addDefaultNotifier( CONNECTION_CLOSED, connectionClosedSignal );

196 197 198 199
    boost::shared_ptr< boost::function< void( osg::ref_ptr< WROI > ) > > assocRoiSignal;
    assocRoiSignal =
        boost::shared_ptr< boost::function< void( osg::ref_ptr< WROI > ) > >(
            new boost::function< void( osg::ref_ptr< WROI > ) > ( boost::bind( &WQt4Gui::slotAddRoiToTree, this, _1 ) ) );
200
    m_kernel->getRoiManager()->addAddNotifier( assocRoiSignal );
201 202 203 204 205 206


    boost::shared_ptr< boost::function< void( osg::ref_ptr< WROI > ) > > removeRoiSignal;
    removeRoiSignal =
        boost::shared_ptr< boost::function< void( osg::ref_ptr< WROI > ) > >(
            new boost::function< void( osg::ref_ptr< WROI > ) > ( boost::bind( &WQt4Gui::slotRemoveRoiFromTree, this, _1 ) ) );
207
    m_kernel->getRoiManager()->addRemoveNotifier( removeRoiSignal );
208 209

    // now we are initialized
210
    m_isInitialized( true );
211

212 213 214
    // check if we want to load data due to command line and call the respective function
    if( m_optionsMap.count("input") )
    {
215
        m_kernel->loadDataSets( m_optionsMap["input"].as< std::vector< std::string > >() );
216 217
    }

218 219 220 221 222
    // Load project file
    if( m_optionsMap.count("project") )
    {
        try
        {
223 224
            boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                    new WProjectFile( m_optionsMap["project"].as< std::string >() )
225
            );
226

227
            // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
228
            proj->load();
229
        }
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
230
        catch( const WException& e )
231 232 233 234 235 236
        {
            wlog::error( "GUI" ) << "Project file \"" << m_optionsMap["project"].as< std::string >() << "\" could not be loaded. Message: " <<
                e.what();
        }
    }

237
    // run
238 239 240 241 242 243
    int qtRetCode = appl.exec();

    // signal everybody to shut down properly.
    WKernel::getRunningKernel()->wait( true );
    WKernel::getRunningKernel()->getGraphicsEngine()->wait( true );

244 245
    m_loggerConnection.disconnect();

246
    return qtRetCode;
247 248
}

249 250 251
void WQt4Gui::slotUpdateTextureSorter()
{
    // create a new event for this and insert it into event queue
252
    QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WUpdateTextureSorterEvent() );
253 254
}

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
255
void WQt4Gui::slotAddLog( const WLogEntry& /*entry*/ )
256
{
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
257
    // TODO(rfrohl): create a new event for this and insert it into event queue
258 259
}

260
void WQt4Gui::slotAddDatasetOrModuleToTree( boost::shared_ptr< WModule > module )
261
{
262
    // create a new event for this and insert it into event queue
263
    QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleAssocEvent( module ) );
264 265
}

266
void WQt4Gui::slotAddRoiToTree( osg::ref_ptr< WROI > roi )
schurade's avatar
schurade committed
267
{
268
    QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WRoiAssocEvent( roi ) );
schurade's avatar
schurade committed
269 270
}

271
void WQt4Gui::slotRemoveRoiFromTree( osg::ref_ptr< WROI > roi )
272
{
273
    QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WRoiRemoveEvent( roi ) );
274 275
}

276
void WQt4Gui::slotActivateDatasetOrModuleInTree( boost::shared_ptr< WModule > module )
277 278
{
    // create a new event for this and insert it into event queue
279
    QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleReadyEvent( module ) );
280
    QCoreApplication::postEvent( m_mainWindow, new WModuleReadyEvent( module ) );
281 282
}

283
void WQt4Gui::slotRemoveDatasetOrModuleInTree( boost::shared_ptr< WModule > module )
284 285
{
    // create a new event for this and insert it into event queue
286 287 288 289 290
    if( module->getName() == "Data Module" )
    {
        boost::shared_ptr< WMData > dataModule = boost::shared_dynamic_cast< WMData >( module );
        WAssert( dataModule, "Internal failure." );
    }
291
    QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleRemovedEvent( module ) );
292
    QCoreApplication::postEvent( m_mainWindow, new WModuleRemovedEvent( module ) );
293 294
}

295 296 297
void WQt4Gui::slotConnectionEstablished( boost::shared_ptr<WModuleConnector> in, boost::shared_ptr<WModuleConnector> out )
{
    // create a new event for this and insert it into event queue
298 299
    if ( in->isInputConnector() )
    {
300
        QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleConnectEvent( in, out ) );
301 302 303
    }
    else
    {
304
        QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleConnectEvent( out, in ) );
305
    }
306 307 308 309 310
}

void WQt4Gui::slotConnectionClosed( boost::shared_ptr<WModuleConnector> in, boost::shared_ptr<WModuleConnector> out )
{
    // create a new event for this and insert it into event queue
311 312
    if ( in->isInputConnector() )
    {
313
        QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleDisconnectEvent( in, out ) );
314 315 316
    }
    else
    {
317
        QCoreApplication::postEvent( m_mainWindow->getControlPanel(), new WModuleDisconnectEvent( out, in ) );
318
    }
319 320
}

321 322
boost::shared_ptr< WModule > WQt4Gui::getSelectedModule()
{
323
    return m_mainWindow->getControlPanel()->getSelectedModule();
324 325
}

schurade's avatar
schurade committed
326
boost::signals2::signal1< void, std::vector< std::string > >* WQt4Gui::getLoadButtonSignal()
327
{
328
    return m_mainWindow->getLoaderSignal();
329 330
}

331
boost::shared_ptr< WCustomWidget > WQt4Gui::openCustomWidget( std::string title, WGECamera::ProjectionMode projectionMode,
332
    boost::shared_ptr< WCondition > shutdownCondition )
333
{
334 335 336 337
    WConditionSet conditionSet;
    conditionSet.setResetable( true, false );
    conditionSet.add( shutdownCondition );

338 339
    boost::shared_ptr< WFlag< boost::shared_ptr< WCustomWidget > > > widgetFlag(
        new WFlag< boost::shared_ptr< WCustomWidget > >( new WConditionOneShot, boost::shared_ptr< WCustomWidget >() ) );
340 341
    conditionSet.add( widgetFlag->getCondition() );

342
    QCoreApplication::postEvent( m_mainWindow, new WOpenCustomDockWidgetEvent( title, projectionMode, widgetFlag ) );
343 344 345

    conditionSet.wait();
    return widgetFlag->get();
346 347 348 349
}

void WQt4Gui::closeCustomWidget( std::string title )
{
350
    m_mainWindow->closeCustomDockWidget( title );
351
}