1 // Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "CAM_Application.h"
25 #include "CAM_Study.h"
26 #include "CAM_Module.h"
28 #include <SUIT_Tools.h>
29 #include <SUIT_Desktop.h>
30 #include <SUIT_Session.h>
31 #include <SUIT_MessageBox.h>
32 #include <SUIT_ResourceMgr.h>
34 #include <KERNEL_version.h>
35 #include <GUI_version.h>
38 #include <QApplication>
42 #include <QMutexLocker>
44 #include <QTextStream>
56 #include <utilities.h>
63 BusyLocker( bool& busy ) : myPrev( busy ), myBusy( busy ) { myBusy = true; }
64 ~BusyLocker() { myBusy = myPrev; }
72 \brief Create new instance of CAM_Application.
73 \return new instance of CAM_Application class
75 extern "C" CAM_EXPORT SUIT_Application* createApplication()
77 return new CAM_Application();
81 \class CAM_Application
82 \brief Introduces an application class which provides modular architecture.
84 This class defines multi-modular application configuration and behaviour.
85 Each module (CAM_Module) can have own data model, document windows and
88 An application provides all necessary functionality for modules management,
91 - modules activation/deactivation
95 CAM_Application::ModuleInfoList CAM_Application::myInfoList;
100 Read modules list (from command line or from resource file).
101 If \a autoLoad parameter is \c true all the modules will be loaded
102 immediately after application starting, otherwise each module will
103 be loaded by demand (with activateModule()).
105 \param autoLoad auto loading flag
107 CAM_Application::CAM_Application( const bool autoLoad )
110 myAutoLoad( autoLoad ),
119 Does nothing currently.
121 CAM_Application::~CAM_Application()
123 for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); it != myModules.end(); ++it )
129 \brief Start an application.
131 Load all modules, if "auto loading" flag has been set to \c true.
133 \sa CAM_Application()
135 void CAM_Application::start()
138 for ( ModuleInfoList::iterator it = myInfoList.begin();
139 it != myInfoList.end(); ++it )
141 if ( (*it).status == stUnknown )
142 (*it).status = checkModule( (*it).title ) ? stReady : stInaccessible;
149 STD_Application::start();
153 \brief Get active module.
154 \return active module or 0 if there are no any
156 CAM_Module* CAM_Application::activeModule() const
162 \brief Get the module with specified name.
163 \return module or 0 if not found
165 CAM_Module* CAM_Application::module( const QString& modName ) const
168 for ( QList<CAM_Module*>::const_iterator it = myModules.begin();
169 it != myModules.end() && !mod; ++it )
170 if ( (*it)->moduleName() == modName )
176 \brief Get all loaded modules.
177 \return list of modules
179 CAM_Application::ModuleList CAM_Application::modules() const
185 \brief Get all loaded modules.
186 \param returning list of modules
188 void CAM_Application::modules( CAM_Application::ModuleList& out ) const
192 for ( QList<CAM_Module*>::const_iterator it = myModules.begin();
193 it != myModules.end(); ++it )
198 \brief Get names of all modules.
200 Get loaded modules names if \a loaded is \c true,
201 otherwise get all avaiable modules names.
203 \param lst output list of modules names
204 \param loaded boolean flag, defines what modules names to return
206 void CAM_Application::modules( QStringList& lst, const bool loaded ) const
212 for ( QList<CAM_Module*>::const_iterator it = myModules.begin();
213 it != myModules.end(); ++it )
214 lst.append( (*it)->moduleName() );
218 for ( ModuleInfoList::const_iterator it = myInfoList.begin();
219 it != myInfoList.end(); ++it )
220 if ( (*it).status != stNoGui )
221 lst.append( (*it).title );
226 \brief Add module \a mod to the modules list.
228 Performes module initialization. Does nothing if the module
231 \param mod module being added
232 \sa CAM_Module::initialize()
234 void CAM_Application::addModule( CAM_Module* mod )
236 if ( !mod || myModules.contains( mod ) )
239 mod->initialize( this );
241 QMap<CAM_Module*, int> map;
244 for ( ModuleInfoList::const_iterator it = myInfoList.begin();
245 it != myInfoList.end(); ++it )
247 if ( (*it).title == mod->moduleName() )
248 newList.append( mod );
251 CAM_Module* curMod = module( (*it).title );
253 newList.append( curMod );
257 for ( QList<CAM_Module*>::const_iterator it = myModules.begin();
258 it != myModules.end(); ++it )
260 if ( !newList.contains( *it ) )
261 newList.append( *it );
264 if ( !newList.contains( mod ) )
265 newList.append( mod );
273 \brief Load modules from the modules information list.
275 If some module can not be loaded, an error message is shown.
277 void CAM_Application::loadModules()
279 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end(); ++it )
281 CAM_Module* mod = loadModule( (*it).title );
285 QString wrn = tr( "Can not load module %1" ).arg( (*it).title );
286 if ( desktop() && desktop()->isVisible() )
287 SUIT_MessageBox::critical( desktop(), tr( "Loading modules" ), wrn );
289 qWarning( qPrintable( wrn ) );
295 \brief Load module \a modName.
297 The function prints warning message if:
298 - modules information list is empty
299 - modules information list does not include specified module info
300 - module library can not be loaded by some reason
302 \param modName module name
303 \return module object pointer or 0 if module could not be loaded
305 CAM_Module* CAM_Application::loadModule( const QString& modName, const bool showMsg )
307 if ( myInfoList.isEmpty() )
309 qWarning( qPrintable( tr( "Modules configuration is not defined." ) ) );
313 QString libName = moduleLibrary( modName );
314 if ( libName.isEmpty() )
316 qWarning( qPrintable( tr( "Information about module \"%1\" doesn't exist." ).arg( modName ) ) );
321 GET_MODULE_FUNC crtInst = 0;
322 GET_VERSION_FUNC getVersion = 0;
326 LPTSTR str_libname = new TCHAR[libName.length() + 1];
327 str_libname[libName.toWCharArray(str_libname)] = '\0';
329 QByteArray arr = libName.toLatin1();
330 LPTSTR str_libname = arr.constData();
332 HINSTANCE modLib = ::LoadLibrary( str_libname );
339 ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
340 FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
342 QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
344 QString out_err = (LPTSTR)lpMsgBuf;
346 err = QString( "Failed to load %1. %2" ).arg( libName ).arg(out_err);
347 ::LocalFree( lpMsgBuf );
351 crtInst = (GET_MODULE_FUNC)::GetProcAddress( modLib, GET_MODULE_NAME );
355 ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
356 FORMAT_MESSAGE_IGNORE_INSERTS, 0, ::GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, 0 );
358 QString out_err = QString::fromWCharArray((LPTSTR)lpMsgBuf);
360 QString out_err = (LPTSTR)lpMsgBuf;
363 err = QString( "Failed to find %1 function. %2" ).arg( GET_MODULE_NAME ).arg( out_err );
364 ::LocalFree( lpMsgBuf );
367 getVersion = (GET_VERSION_FUNC)::GetProcAddress( modLib, GET_VERSION_NAME );
370 void* modLib = dlopen( libName.toUtf8(), RTLD_LAZY | RTLD_GLOBAL );
372 err = QString( "Can not load library %1. %2" ).arg( libName ).arg( dlerror() );
375 crtInst = (GET_MODULE_FUNC)dlsym( modLib, GET_MODULE_NAME );
377 err = QString( "Failed to find function %1. %2" ).arg( GET_MODULE_NAME ).arg( dlerror() );
379 getVersion = (GET_VERSION_FUNC)dlsym( modLib, GET_VERSION_NAME );
383 CAM_Module* module = crtInst ? crtInst() : 0;
386 module->setModuleName( modName );
387 module->setName( moduleName( modName ) );
390 if ( !err.isEmpty() && showMsg ) {
391 if ( desktop() && desktop()->isVisible() )
392 SUIT_MessageBox::warning( desktop(), tr( "Error" ), err );
394 qWarning( qPrintable( err ) );
397 char* version = getVersion ? getVersion() : 0;
400 for ( ModuleInfoList::iterator it = myInfoList.begin(); it != myInfoList.end(); ++it ) {
401 if ( (*it).title == modName ) {
402 if( (*it).version.isEmpty() ) {
403 (*it).version = QString(version);
414 \brief Activate module \a modName.
415 \param modName module name
416 \return \c true, if module is loaded and activated successfully and \c false otherwise
418 bool CAM_Application::activateModule( const QString& modName )
420 if ( (!modName.isEmpty() && !activeStudy()) || myBlocked )
423 // VSR 25/10/2011: prevent nested activation/deactivation
424 // See issues 0021307, 0021373
425 BusyLocker lock( myBlocked );
427 QString name = modName;
428 if ( !name.isEmpty() && !moduleTitle( modName ).isEmpty() )
429 name = moduleTitle( modName );
432 if ( !name.isEmpty() )
434 setProperty("activateModule", true);
435 CAM_Module* mod = module( name );
437 mod = loadModule( name );
441 res = activateModule( mod );
442 setProperty("activateModule", QVariant());
445 res = activateModule( 0 );
451 \brief Activate module \a mod.
453 Shows error message if module could not be activated in the current study.
455 \param mod module object pointer
456 \return \c true, if module is loaded and activated successfully and \c false otherwise
458 bool CAM_Application::activateModule( CAM_Module* mod )
460 if ( mod && !activeStudy() )
463 if ( myModule == mod )
468 if ( myModule->deactivateModule( activeStudy() ) )
470 logUserEvent( tr( "MODULE_DEACTIVATED" ).arg( myModule->moduleName() ) );
472 moduleDeactivated( myModule );
478 // Connect the module to the active study
479 myModule->connectToStudy( dynamic_cast<CAM_Study*>( activeStudy() ) );
480 if ( myModule->activateModule( activeStudy() ) )
482 logUserEvent( tr( "MODULE_ACTIVATED" ).arg( myModule->moduleName() ) );
486 myModule->setMenuShown( false );
487 myModule->setToolShown( false );
488 QString wrn = tr( "ERROR_ACTIVATE_MODULE_MSG" ).arg( myModule->moduleName() );
489 if ( desktop() && desktop()->isVisible() )
490 SUIT_MessageBox::critical( desktop(), tr( "ERROR_TLT" ), wrn );
492 qWarning( qPrintable( wrn ) );
498 updateCommandsStatus();
504 \brief Load module \a modName and activate its operation, corresponding to \a actionId.
505 This method is dedicated to run operations of some module from any other module.
506 \param modName module name
507 \param actionId is a numerical unique operation identifier
508 \return \c true in case of success and \c false otherwise
510 bool CAM_Application::activateOperation( const QString& modName, int actionId )
512 CAM_Module* mod = loadModule(modName, false);
515 return mod->activateOperation(actionId);
521 \brief Load module \a modName and activate its operation, corresponding to \a actionId.
522 This method is dedicated to run operations of some module from any other module.
523 \param modName module name
524 \param actionId is a string unique operation identifier
525 \return \c true in case of success and \c false otherwise
527 bool CAM_Application::activateOperation( const QString& modName, const QString& actionId )
529 CAM_Module* mod = loadModule(modName, false);
532 return mod->activateOperation(actionId);
538 \brief Load module \a modName and activate its operation,
539 corresponding to \a actionId and \a pluginName.
540 This method is dedicated to run operations of some module from any other module.
541 \param modName module name
542 \param actionId is a string unique operation identifier
543 \param pluginName is a name of a plugin where the operation is implemented
544 \return \c true in case of success and \c false otherwise
546 bool CAM_Application::activateOperation( const QString& modName,
547 const QString& actionId,
548 const QString& pluginName )
550 CAM_Module* mod = loadModule(modName, false);
553 return mod->activateOperation(actionId, pluginName);
559 \brief Create new study.
560 \return study object pointer
562 SUIT_Study* CAM_Application::createNewStudy()
564 return new CAM_Study( this );
568 \brief Update menu commands status.
570 void CAM_Application::updateCommandsStatus()
572 STD_Application::updateCommandsStatus();
574 if ( activeModule() )
575 activeModule()->updateCommandsStatus();
579 \brief Prepare application to study closing.
581 Closes all modules in study \a theDoc.
585 void CAM_Application::beforeCloseDoc( SUIT_Study* theDoc )
587 for ( QList<CAM_Module*>::iterator it = myModules.begin(); it != myModules.end(); ++it )
588 (*it)->studyClosed( theDoc );
591 void CAM_Application::afterCloseDoc()
596 \brief Set active study.
597 \param study study to be made active
599 void CAM_Application::setActiveStudy( SUIT_Study* study )
601 STD_Application::setActiveStudy( study );
605 \brief Check module availability.
607 The method can be redefined in successors. Default implementation returns \c true.
609 \param title module title
610 \return \c true if module is accessible; \c false otherwise
612 bool CAM_Application::checkModule( const QString& )
618 \brief Callback function, called when the module is added to the application.
620 This virtual method can be re-implemented in the successors. Base implementation
623 \param mod module being added
625 void CAM_Application::moduleAdded( CAM_Module* /*mod*/ )
630 \brief Callback function, called when the module is just deactivated.
632 This virtual method can be re-implemented in the successors. Base implementation
635 \param mod module just deactivated
637 void CAM_Application::moduleDeactivated( CAM_Module* /*mod*/ )
642 \brief Get module name by its title (user name).
643 \param title module title (user name)
644 \return module name or null QString if module is not found
646 QString CAM_Application::moduleName( const QString& title )
649 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
651 if ( (*it).title == title )
658 \brief Get module title (user name) by its name.
659 \param name module name
660 \return module title (user name) or null QString if module is not found
662 QString CAM_Application::moduleTitle( const QString& name )
665 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
667 if ( (*it).name == name )
674 \brief Get module icon name.
675 \param name module name or title
676 \return module icon or null QString if module is not found
678 QString CAM_Application::moduleIcon( const QString& name )
681 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
683 if ( (*it).name == name || (*it).title == name )
690 \brief Get module description.
691 \param name module name or title
692 \return module description or null QString if description is not provided in config file.
694 QString CAM_Application::moduleDescription( const QString& name )
697 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isNull(); ++it )
699 if ( (*it).name == name || (*it).title == name )
700 res = tr((*it).description.toUtf8());
706 \brief Get module library name by its title (user name).
707 \param title module name or title
708 \param full if \c true, return full library name, otherwise return its internal name
709 \return module library name or null QString if module is not found
711 QString CAM_Application::moduleLibrary( const QString& name, const bool full )
714 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
716 if ( (*it).name == name || (*it).title == name )
719 if ( !res.isEmpty() && full )
720 res = SUIT_Tools::library( res );
725 \brief Get displayer proxy for given module, by its title (user name).
726 \param name module name or title
727 \return name of module which provides displayer for requested module
729 QString CAM_Application::moduleDisplayer( const QString& name )
733 if ( !name.isEmpty() )
735 for ( ModuleInfoList::const_iterator it = myInfoList.begin(); it != myInfoList.end() && res.isEmpty(); ++it )
737 if ( (*it).title == name || (*it).name == name ) {
738 res = (*it).displayer;
749 \brief Read modules information list
751 This function first tries to get the modules names list by parsing
752 the application command line arguments, looking for the
753 "--modules ( <mod_name>[:<mod_name>...] )" option.
754 List of modules is separated by colon symbol (":").
756 If "--modules" command line option is not used, the list of modules
757 is retrieved from the application resource file: parameter "modules" of
758 the section "launch".
760 Then the information about each module (module title (user name),
761 library name) is retrieved from the corresponding section of resource
762 file with help of resources manager.
764 Shows the warning message, if module information list is empty.
768 void CAM_Application::readModuleList()
770 if ( !myInfoList.isEmpty() )
773 // we cannot use own resourceMgr() as this method can be called from constructor
774 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
778 QString args = QApplication::arguments().join( " " );
780 QRegExp rx1("--modules=([\\w,]*)");
781 rx1.setMinimal( false );
782 QRegExp rx2("--modules\\s+\\(\\s*(.*)\\s*\\)");
783 rx2.setMinimal( true );
787 int pos1 = rx1.indexIn( args, pos );
788 int pos2 = rx2.indexIn( args, pos );
789 if ( pos1 != -1 && pos2 != -1 ) {
790 modules = pos1 < pos2 ? rx1.cap( 1 ) : rx2.cap(1);
791 pos = pos1 < pos2 ? pos1 + rx1.matchedLength() : pos2 + rx2.matchedLength();
793 else if ( pos1 != -1 ) {
794 modules = rx1.cap( 1 );
795 pos = pos1 + rx1.matchedLength();
797 else if ( pos2 != -1 ) {
798 modules = rx2.cap( 1 );
799 pos = pos2 + rx2.matchedLength();
806 QStringList mods = modules.split( QRegExp( "[:|,\\s]" ), QString::SkipEmptyParts );
807 for ( int i = 0; i < mods.count(); i++ ) {
808 if ( !mods[i].trimmed().isEmpty() )
809 modList.append( mods[i].trimmed() );
813 if ( modList.isEmpty() ) {
814 QString mods = resMgr->stringValue( "launch", "modules", QString() );
815 modList = mods.split( ",", QString::SkipEmptyParts );
818 // extra modules loaded manually on previous session
821 foreach ( QString modName, modList )
822 appendModuleInfo( modName.trimmed() );
824 if ( myInfoList.isEmpty() ) {
825 if ( desktop() && desktop()->isVisible() )
826 SUIT_MessageBox::warning( desktop(), tr( "Warning" ), tr( "Modules list is empty" ) );
829 printf( "****************************************************************\n" );
830 printf( "* Warning: modules list is empty.\n" );
831 printf( "****************************************************************\n" );
836 bool CAM_Application::appendModuleInfo( const QString& modName )
838 MESSAGE("Start to append module info for a given module name: ");
839 SCRUTE(modName.toStdString());
841 if ( modName.isEmpty() )
842 return false; // empty module name
844 if ( !moduleTitle( modName ).isEmpty() )
845 return false; // already added
847 if ( modName == "KERNEL" || modName == "GUI" )
848 return false; // skip KERNEL and GUI modules
850 // we cannot use own resourceMgr() as this method can be called from constructor
851 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
855 // module internal name
858 inf.version = resMgr->stringValue( modName, "version", QString() ).trimmed();
859 // displayer, if module does not have GUI, displayer may be delegated to other module
860 inf.displayer = resMgr->stringValue( modName, "displayer", QString() ).trimmed();
862 // "gui" option explicitly says that module has GUI
863 // Now trying to get the "gui" option value, we always get a default one,
864 // then we can't rely on it.
865 bool hasGui = resMgr->booleanValue(modName, "gui", false);
867 // Additional check if the module actually has a title and icon.
868 // Module with GUI must explicitly specify title (GUI name).
869 inf.title = resMgr->stringValue(modName, "name", QString()).trimmed();
870 const bool hasTitle = !inf.title.isEmpty();
873 if (hasGui && !hasTitle)
875 MESSAGE("Invalid config! The module has gui option, but doesn't have a title.");
879 // While we can't rely on gui option, use a title to make a decision about gui.
882 // status; if module has GUI, availability will be checked on activation
883 inf.status = hasGui ? stUnknown : stNoGui;
888 inf.icon = resMgr->stringValue( modName, "icon", QString() ).trimmed();
889 // description, for Info panel
890 inf.description = resMgr->stringValue( modName, "description", QString() );
891 // library; if not specified, we use internal module name
892 inf.library = SUIT_Tools::libraryName( resMgr->stringValue( modName, "library", QString() ).trimmed() );
893 if ( inf.library.isEmpty() )
894 inf.library = modName;
897 // At this point we should have only valid inf object.
898 myInfoList.append(inf);
900 SCRUTE(inf.name.toStdString());
901 SCRUTE(inf.version.toStdString());
902 SCRUTE(inf.displayer.toStdString());
904 SCRUTE(inf.title.toStdString());
905 SCRUTE(inf.icon.toStdString());
906 SCRUTE(inf.description.toStdString());
907 SCRUTE(inf.library.toStdString());
912 void CAM_Application::removeModuleInfo( const QString& modName )
914 QMutableListIterator<ModuleInfo> it( myInfoList );
915 while ( it.hasNext() )
917 ModuleInfo info = it.next();
918 if ( info.name == modName )
927 \brief Add common menu items to the popup menu.
929 Menu items list is defined by the active module.
931 \param type popup menu context
932 \param menu popup menu
933 \param title popup menu title, which can be set by the module if required
935 void CAM_Application::contextMenuPopup( const QString& type, QMenu* menu, QString& title )
937 // to do : add common items for popup menu ( if they are exist )
938 if ( activeModule() )
939 activeModule()->contextMenuPopup( type, menu, title );
943 \brief Create new empty study.
945 void CAM_Application::createEmptyStudy()
947 /*SUIT_Study* study = */activeStudy();
948 STD_Application::createEmptyStudy();
952 \brief Return information about version of the each module.
954 CAM_Application::ModuleShortInfoList CAM_Application::getVersionInfo()
956 ModuleShortInfoList info;
958 ModuleShortInfo kernel;
959 kernel.name = "KERNEL";
960 kernel.version = KERNEL_VERSION_STR;
965 gui.version = GUI_VERSION_STR;
968 for(int i = 0; i < myInfoList.size(); i++) {
969 ModuleShortInfo infoItem;
970 infoItem.name = myInfoList.at(i).title.isEmpty() ? myInfoList.at(i).name : myInfoList.at(i).title;
971 infoItem.version = myInfoList.at(i).version;
972 info.append(infoItem);
978 \brief Abort active operations if there are any
980 Iterates through all modules and asks each of them if there are pending operations that cannot be aborted.
982 \return \c false if some operation cannot be aborted
984 bool CAM_Application::abortAllOperations()
987 for ( QList<CAM_Module*>::const_iterator it = myModules.begin(); it != myModules.end() && aborted; ++it )
989 aborted = (*it)->abortAllOperations();
995 \brief Log GUI event.
996 \param eventDescription GUI event description.
998 void CAM_Application::logUserEvent( const QString& eventDescription )
1000 static QString guiLogFile; // null string means log file was not initialized yet
1001 static QMutex aGUILogMutex;
1003 if ( guiLogFile.isNull() )
1005 // log file was not initialized yet, try to do that by parsing command line arguments
1006 guiLogFile = ""; // empty string means initialization was done but log file was not set
1007 QStringList args = QApplication::arguments();
1008 for ( int i = 1; i < args.count(); i++ )
1010 QRegExp rxs ( "--gui-log-file=(.+)" );
1011 if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 )
1013 QString file = rxs.capturedTexts()[1];
1014 QFileInfo fi ( file );
1015 if ( !fi.isDir() && fi.dir().exists() )
1017 guiLogFile = fi.absoluteFilePath();
1018 if ( fi.exists() ) {
1019 QFile file ( guiLogFile );
1020 file.remove(); // remove probably existing log file, to start with empty one
1027 if ( !guiLogFile.isEmpty() ) // non-empty string means log file was already initialized
1029 QMutexLocker aLocker( &aGUILogMutex );
1030 QFile file ( guiLogFile );
1031 if ( file.open( QFile::Append ) ) // append to log file
1033 QDateTime current = QDateTime::currentDateTime();
1034 QTextStream stream( &file );
1035 stream << current.toString("yyyyMMdd-hhmmss") << ": " << eventDescription << endl;
1042 \brief Log given action.
1043 \param action GUI action being logged.
1044 \param moduleName optional name of module, owning an action
1046 void CAM_Application::logAction( QAction* action, const QString& moduleName )
1048 QString text = action->toolTip();
1049 if ( text.isEmpty() )
1050 text = action->text();
1051 if ( text.isEmpty() )
1052 text = action->iconText();
1053 if ( !text.isEmpty() )
1055 QStringList message;
1056 if ( !moduleName.isEmpty() )
1057 message << moduleName;
1058 if ( action->isCheckable() )
1060 message << tr( "ACTION_TOGGLED" );
1061 message << ( action->isChecked() ? tr( "ACTION_ON" ) : tr( "ACTION_OFF" ) );
1065 message << tr( "ACTION_TRIGGERED" );
1068 logUserEvent( message.join( ": " ) );