/***************************************************************************** # Copyright (C) 1994-2008 by David Gordon. # All rights reserved. # # This software is part of a beta-test version of the Consed/Autofinish # package. It should not be redistributed or # used for any commercial purpose, including commercially funded # sequencing, without written permission from the author and the # University of Washington. # # This software is provided ``AS IS'' and any express or implied # warranties, including, but not limited to, the implied warranties of # merchantability and fitness for a particular purpose, are disclaimed. # In no event shall the authors or the University of Washington be # liable for any direct, indirect, incidental, special, exemplary, or # consequential damages (including, but not limited to, procurement of # substitute goods or services; loss of use, data, or profits; or # business interruption) however caused and on any theory of liability, # whether in contract, strict liability, or tort (including negligence # or otherwise) arising in any way out of the use of this software, even # if advised of the possibility of such damage. # # Building Consed from source is error prone and not simple which is # why I provide executables. Due to time limitations I cannot # provide any assistance in building Consed. Even if you do not # modify the source, you may introduce errors due to using a # different version of the compiler, a different version of motif, # different versions of other libraries than I used, etc. For this # reason, if you discover Consed bugs, I can only offer help with # those bugs if you first reproduce those bugs with an executable # provided by me--not an executable you have built. # # Modifying Consed is also difficult. Although Consed is modular, # some modules are used by many other modules. Thus making a change # in one place can have unforeseen effects on many other features. # It may takes months for you to notice these other side-effects # which may not seen connected at all. It is not feasable for me to # provide help with modifying Consed sources because of the # potentially huge amount of time involved. # #*****************************************************************************/ #include "guiNavigateByHighlyDiscrepantPositions.h" #include #include #include #include #include #include #include #include #include "hp_exception_kludge.h" #include "handleWindowManagerDelete2.h" #include #include "bIsNumericMaybeWithWhitespace.h" #include "bIsNumericDouble.h" #include "consedParameters.h" #include "popupErrorMessage.h" #include "gotoList.h" #include "consed.h" #include "please_wait.h" static void cbSearch( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiNavigateByHighlyDiscrepantPositions* pGuiNav = (guiNavigateByHighlyDiscrepantPositions*) pClientData; TRY_CATCH_WRAPPER( pGuiNav->userClickedSearch(); ); } static void cbDismiss( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiNavigateByHighlyDiscrepantPositions* pGuiNav = (guiNavigateByHighlyDiscrepantPositions*) pClientData; TRY_CATCH_WRAPPER( delete pGuiNav ); } static const int nRightPositionOfLabels = 70; static const int nLeftPositionOfInputFields = 80; #ifdef NO_POUND_POUND_MACROS #define makeLabelAndIntegerTextField( parameterNameWithoutPrefix, label ) \ Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \ "form", \ xmFormWidgetClass, \ widRowCol, \ XmNshadowThickness, 0, \ NULL ); \ \ Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \ label , \ xmLabelWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_FORM, \ XmNrightAttachment, XmATTACH_POSITION, \ XmNrightPosition, nRightPositionOfLabels, \ XmNalignment, XmALIGNMENT_END, \ NULL ); \ \ char sz ## parameterNameWithoutPrefix[200]; \ sprintf( sz ## parameterNameWithoutPrefix, "%d", \ consedParameters::pGetConsedParameters()->n ## parameterNameWithoutPrefix ## _ ); \ \ \ wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \ #parameterNameWithoutPrefix , \ xmTextFieldWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtraversalOn, True, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_POSITION, \ XmNleftPosition, nLeftPositionOfInputFields, \ XmNrightAttachment, XmATTACH_FORM, \ XmNvalue, sz ## parameterNameWithoutPrefix , \ NULL ); \ \ XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \ XmNactivateCallback, \ (XtCallbackProc )XmProcessTraversal, \ (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP ); #else #define makeLabelAndIntegerTextField( parameterNameWithoutPrefix, label ) \ Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \ "form", \ xmFormWidgetClass, \ widRowCol, \ XmNshadowThickness, 0, \ NULL ); \ \ Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \ ##label , \ xmLabelWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_FORM, \ XmNrightAttachment, XmATTACH_POSITION, \ XmNrightPosition, nRightPositionOfLabels, \ XmNalignment, XmALIGNMENT_END, \ NULL ); \ \ char sz ## parameterNameWithoutPrefix ## [200]; \ sprintf( sz ## parameterNameWithoutPrefix, "%d", \ consedParameters::pGetConsedParameters()->n ## parameterNameWithoutPrefix ## _ ); \ \ \ wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \ #parameterNameWithoutPrefix , \ xmTextFieldWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtraversalOn, True, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_POSITION, \ XmNleftPosition, nLeftPositionOfInputFields, \ XmNrightAttachment, XmATTACH_FORM, \ XmNvalue, sz ## parameterNameWithoutPrefix , \ NULL ); \ \ XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \ XmNactivateCallback, \ (XtCallbackProc )XmProcessTraversal, \ (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP ); #endif #ifdef NO_POUND_POUND_MACROS #define makeLabelAndDoubleTextField( parameterNameWithoutPrefix, label ) \ Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \ "form", \ xmFormWidgetClass, \ widRowCol, \ XmNshadowThickness, 0, \ NULL ); \ \ Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \ label , \ xmLabelWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_FORM, \ XmNrightAttachment, XmATTACH_POSITION, \ XmNrightPosition, nRightPositionOfLabels, \ XmNalignment, XmALIGNMENT_END, \ NULL ); \ \ char sz ## parameterNameWithoutPrefix[200]; \ sprintf( sz ## parameterNameWithoutPrefix, "%.1f", \ consedParameters::pGetConsedParameters()->d ## parameterNameWithoutPrefix ## _ ); \ \ \ wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \ #parameterNameWithoutPrefix , \ xmTextFieldWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtraversalOn, True, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_POSITION, \ XmNleftPosition, nLeftPositionOfInputFields, \ XmNrightAttachment, XmATTACH_FORM, \ XmNvalue, sz ## parameterNameWithoutPrefix , \ NULL ); \ \ XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \ XmNactivateCallback, \ (XtCallbackProc )XmProcessTraversal, \ (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP ); #else #define makeLabelAndDoubleTextField( parameterNameWithoutPrefix, label ) \ Widget wid ## parameterNameWithoutPrefix ## Form = XtVaCreateManagedWidget( \ "form", \ xmFormWidgetClass, \ widRowCol, \ XmNshadowThickness, 0, \ NULL ); \ \ Widget wid ## parameterNameWithoutPrefix ## Label = XtVaCreateManagedWidget( \ ##label , \ xmLabelWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_FORM, \ XmNrightAttachment, XmATTACH_POSITION, \ XmNrightPosition, nRightPositionOfLabels, \ XmNalignment, XmALIGNMENT_END, \ NULL ); \ \ char sz ## parameterNameWithoutPrefix ## [200]; \ sprintf( sz ## parameterNameWithoutPrefix, "%.1f", \ consedParameters::pGetConsedParameters()->d ## parameterNameWithoutPrefix ## _ ); \ \ \ wid ## parameterNameWithoutPrefix ## _ = XtVaCreateManagedWidget( \ #parameterNameWithoutPrefix , \ xmTextFieldWidgetClass, \ wid ## parameterNameWithoutPrefix ## Form, \ XmNtraversalOn, True, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_POSITION, \ XmNleftPosition, nLeftPositionOfInputFields, \ XmNrightAttachment, XmATTACH_FORM, \ XmNvalue, sz ## parameterNameWithoutPrefix , \ NULL ); \ \ XtAddCallback( wid ## parameterNameWithoutPrefix ## _, \ XmNactivateCallback, \ (XtCallbackProc )XmProcessTraversal, \ (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP ); #endif #define checkIfNumeric( Parameter ) \ szValue = XmTextFieldGetString( wid ## Parameter ## _ );\ soValue = szValue; \ XtFree( szValue ); \ int nPerhaps ## Parameter; \ if ( !bIsNumericMaybeWithWhitespace( soValue, nPerhaps ## Parameter ) ) { \ RWCString soError = #Parameter " must be numeric but instead is: \""; \ soError += soValue; \ soError += "\""; \ popupErrorMessage( soError ); \ return; \ } #define checkIfNumericDouble( AssemblyViewParameter ) \ szValue = XmTextFieldGetString( wid ## AssemblyViewParameter ## _ );\ soValue = szValue; \ XtFree( szValue ); \ double dPerhaps ## AssemblyViewParameter; \ if ( !bIsNumericDouble( soValue, dPerhaps ## AssemblyViewParameter ) ) { \ RWCString soError = #AssemblyViewParameter " must be numeric but instead is: \""; \ soError += soValue; \ soError += "\""; \ popupErrorMessage( soError ); \ return; \ } guiNavigateByHighlyDiscrepantPositions :: ~guiNavigateByHighlyDiscrepantPositions() { XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); } void guiNavigateByHighlyDiscrepantPositions :: createWindow() { widPopupShell_ = XtVaCreatePopupShell( "Navigate by Highly Discrepant Regions", topLevelShellWidgetClass, GuiApp::pGetGuiApp()->widGetTopLevel(), XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, NULL ); handleWindowManagerDelete2( widPopupShell_, cbDismiss, this ); int nArgs = 0; Arg aArg[30]; Widget widForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widPopupShell_, XmNancestorSensitive, True, NULL ); widDismiss_ = XtVaCreateManagedWidget( "Dismiss", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 70, NULL ); XtAddCallback( widDismiss_, XmNactivateCallback, cbDismiss, this ); widSearch_ = XtVaCreateManagedWidget( "Search", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 10, NULL ); XtAddCallback( widSearch_, XmNactivateCallback, cbSearch, this ); Widget widRowCol = XtVaCreateManagedWidget( "rowcol", xmRowColumnWidgetClass, widForm, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widDismiss_, NULL ); makeLabelAndIntegerTextField( NavigateByHighlyDiscrepantPositionsMinDiscrepantReads, "minimum # of discrepant reads" ); makeLabelAndIntegerTextField( NavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage, "maximum depth of coverage" ); makeLabelAndIntegerTextField( NavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality, "ignore bases below this quality" ); // bool Widget widJustListIndelsForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widRowCol, XmNshadowThickness, 0, NULL ); Widget widJustListIndelsLabel = XtVaCreateManagedWidget( "Just list indels", xmLabelWidgetClass, widJustListIndelsForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, nRightPositionOfLabels, XmNalignment, XmALIGNMENT_END, NULL ); widJustListIndelsRadioBox_ = XmCreateRadioBox( widJustListIndelsForm, "radio", NULL, 0 ); XtVaSetValues( widJustListIndelsRadioBox_, XmNtraversalOn, True, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, nLeftPositionOfInputFields, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNorientation, XmHORIZONTAL, NULL ); widJustListIndelsTrue_ = XtVaCreateManagedWidget( "True", xmToggleButtonWidgetClass, widJustListIndelsRadioBox_, XmNset, ( pCP->bNavigateByHighlyDiscrepantPositionsJustListIndels_ ? True : False ), NULL ); Widget widJustListIndelsFalseButton = XtVaCreateManagedWidget( "False", xmToggleButtonWidgetClass, widJustListIndelsRadioBox_, XmNset, ( pCP->bNavigateByHighlyDiscrepantPositionsJustListIndels_ ? False : True ), NULL ); XtManageChild( widJustListIndelsRadioBox_ ); // pCP->bNavigateByHighlyDiscrepantPositionsIgnoreOtherReadsStartingAtSameLocation_ Widget widCountOnlyOnceMultipleReadsThatStartAtSameLocationForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widRowCol, XmNshadowThickness, 0, NULL ); Widget widCountOnlyOnceMultipleReadsThatStartAtSameLocationLabel = XtVaCreateManagedWidget( "Count only first of multiple reads starting at same location", xmLabelWidgetClass, widCountOnlyOnceMultipleReadsThatStartAtSameLocationForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, nRightPositionOfLabels, XmNalignment, XmALIGNMENT_END, NULL ); widCountOnlyOnceMultipleReadsThatStartAtSameLocationBox_ = XmCreateRadioBox( widCountOnlyOnceMultipleReadsThatStartAtSameLocationForm, "radio", NULL, 0 ); XtVaSetValues( widCountOnlyOnceMultipleReadsThatStartAtSameLocationBox_, XmNtraversalOn, True, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, nLeftPositionOfInputFields, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNorientation, XmHORIZONTAL, NULL ); widCountOnlyOnceMultipleReadsThatStartAtSameLocationTrue_ = XtVaCreateManagedWidget( "True", xmToggleButtonWidgetClass, widCountOnlyOnceMultipleReadsThatStartAtSameLocationBox_, XmNset, ( pCP->bNavigateByHighlyDiscrepantPositionsIgnoreOtherReadsStartingAtSameLocation_ ? True : False ), NULL ); Widget widCountOnlyOnceMultipleReadsThatStartAtSameLocationFalse = XtVaCreateManagedWidget( "False", xmToggleButtonWidgetClass, widCountOnlyOnceMultipleReadsThatStartAtSameLocationBox_, XmNset, ( pCP->bNavigateByHighlyDiscrepantPositionsIgnoreOtherReadsStartingAtSameLocation_ ? False : True ), NULL ); XtManageChild( widCountOnlyOnceMultipleReadsThatStartAtSameLocationBox_ ); // pCP->bNavigateByHighlyDiscrepantPositionsIgnoreIfNOrXInConsensus_ Widget widIgnoreIfListedBasesInConsensusForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widRowCol, XmNshadowThickness, 0, NULL ); widIgnoreIfTheseBasesInConsensus_ = XtVaCreateManagedWidget( "NavigateByHighlyDiscrepantPositionsIgnoreIfTheseBasesInConsensusTextField", xmTextFieldWidgetClass, widIgnoreIfListedBasesInConsensusForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, nRightPositionOfLabels, XmNvalue, pCP->soNavigateByHighlyDiscrepantPositionsIgnoreIfTheseBasesInConsensus_.data(), NULL ); Widget widIgnoreIfListedBasesInConsensusLabel = XtVaCreateManagedWidget( "Ignore location if consensus base is one of:", xmLabelWidgetClass, widIgnoreIfListedBasesInConsensusForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, widIgnoreIfTheseBasesInConsensus_, XmNalignment, XmALIGNMENT_END, NULL ); widIgnoreIfListedBasesInConsensusBox_ = XmCreateRadioBox( widIgnoreIfListedBasesInConsensusForm, "radio2", NULL, 0 ); XtVaSetValues( widIgnoreIfListedBasesInConsensusBox_, XmNtraversalOn, True, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, nLeftPositionOfInputFields, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNorientation, XmHORIZONTAL, NULL ); widIgnoreIfListedBasesInConsensusBoxTrue_ = XtVaCreateManagedWidget( "True", xmToggleButtonWidgetClass, widIgnoreIfListedBasesInConsensusBox_, XmNset, ( pCP->bNavigateByHighlyDiscrepantPositionsIgnoreIfListedBasesInConsensus_ ? True : False ), NULL ); Widget widIgnoreIfListedBasesInConsensusBoxFalse = XtVaCreateManagedWidget( "False", xmToggleButtonWidgetClass, widIgnoreIfListedBasesInConsensusBox_, XmNset, ( pCP->bNavigateByHighlyDiscrepantPositionsIgnoreIfListedBasesInConsensus_ ? False : True ), NULL ); XtManageChild( widIgnoreIfListedBasesInConsensusBox_ ); XtPopup( widPopupShell_, XtGrabNone ); } void guiNavigateByHighlyDiscrepantPositions :: userClickedSearch() { char* szValue; RWCString soValue; checkIfNumeric( NavigateByHighlyDiscrepantPositionsMinDiscrepantReads ); pCP->nNavigateByHighlyDiscrepantPositionsMinDiscrepantReads_ = nPerhapsNavigateByHighlyDiscrepantPositionsMinDiscrepantReads; checkIfNumeric( NavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage ); pCP->nNavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage_ = nPerhapsNavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage; checkIfNumeric( NavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality ); pCP->nNavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality_ = nPerhapsNavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality; pCP->bNavigateByHighlyDiscrepantPositionsJustListIndels_ = ( XmToggleButtonGetState( widJustListIndelsTrue_ ) == True ) ? true : false; pCP->bNavigateByHighlyDiscrepantPositionsIgnoreIfListedBasesInConsensus_ = ( XmToggleButtonGetState( widIgnoreIfListedBasesInConsensusBoxTrue_ ) == True ) ? true : false; pCP->soNavigateByHighlyDiscrepantPositionsIgnoreIfTheseBasesInConsensus_ = XmTextFieldGetString( widIgnoreIfTheseBasesInConsensus_ ); PleaseWait* pPleaseWait = new PleaseWait(); gotoList* pGotoList = new gotoList(); for( int nContig = 0; nContig < ConsEd::pGetAssembly()->nNumContigs(); ++nContig ) { Contig* pContig = ConsEd::pGetAssembly()->pGetContig( nContig ); pContig->navigateByHighlyDiscrepantPositions( pCP->nNavigateByHighlyDiscrepantPositionsMinDiscrepantReads_, pCP->nNavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage_, pCP->nNavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality_, pCP->bNavigateByHighlyDiscrepantPositionsJustListIndels_, pCP->bNavigateByHighlyDiscrepantPositionsIgnoreOtherReadsStartingAtSameLocation_, pCP->bNavigateByHighlyDiscrepantPositionsIgnoreIfListedBasesInConsensus_, pCP->soNavigateByHighlyDiscrepantPositionsIgnoreIfTheseBasesInConsensus_, true, // bGotoListNotArrays pGotoList ); } RWCString soTitle; RWCString soFirstLine; RWCString soSecondLine; soTitle = "Highly Discrepant Positions"; soFirstLine = "min # of discrepant reads: " + RWCString( (long) pCP->nNavigateByHighlyDiscrepantPositionsMinDiscrepantReads_ ) + ", min quality: " + RWCString( (long) pCP->nNavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality_ ) + ", \"r\": base of reference seq"; soSecondLine = "max depth of coverage: " + RWCString( (long) pCP->nNavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage_ ); if ( pCP->bNavigateByHighlyDiscrepantPositionsJustListIndels_ ) { soSecondLine += " just indels"; } soSecondLine += " and ignoring reference seq"; RWCString soThirdLine = " A C G T * pos contig"; ConsEd::pGetConsEd()->addGuiMultiContigNavigator( new guiMultiContigNavigator( soTitle, soFirstLine, soSecondLine, 75, // nWidthInChars "", NULL, NULL, NULL, pGotoList, NULL, soThirdLine ) ); delete pPleaseWait; delete this; }