--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/heapanalyser/UI/UIs/Graphical/Wizard/HASetupWizard.cs Tue Jun 15 12:47:20 2010 +0300
@@ -0,0 +1,594 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* - Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* - Neither the name of Nokia Corporation nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+using System;
+using System.IO;
+using System.Drawing;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Data;
+using System.Management;
+using System.Text;
+using SymbianUtils.Settings;
+using SymbianUtilsUi.Dialogs;
+using HeapAnalyser.Engine;
+using HeapAnalyser.Engine.Types;
+using HeapLib;
+using HeapLib.Constants;
+using HeapLib.Reconstructor;
+using HeapLib.Reconstructor.Misc;
+using HeapLib.Reconstructor.DataSources;
+using HeapLib.Reconstructor.DataSources.Analyser;
+using HeapUiLib.Dialogs;
+using SymbianWizardLib.Engine;
+using SymbianWizardLib.GUI;
+using SymbianDebugLib.Engine;
+using SymbianDebugLibUi.Controls;
+
+namespace HeapAnalyser.UIs.Graphical.Wizard
+{
+ public partial class HASetupWizard : Form
+ {
+ #region Constructors & destructors
+ public HASetupWizard( XmlSettings aSettings, HeapWizardEngine aEngine )
+ {
+ iSettings = aSettings;
+ iEngine = aEngine;
+ //
+ InitializeComponent();
+ }
+ #endregion
+
+ #region Form event handlers
+ private void Form_Load( object sender, System.EventArgs e )
+ {
+ // Set up version information
+ iLbl_Version.Text = HeapLibConstants.Version + " " + HeapLibConstants.Copyright;
+ iSettings[ "Wizard", "DialogResult"] = DialogResult.None.ToString();
+ //
+ Setup_OpType();
+ //
+ Setup_SourceData_LogFileName();
+ Setup_SourceData_HeapDataComparison();
+ Setup_SourceData_HeapCSVComparison();
+ //
+ Setup_Cmn_Symbolics();
+ Setup_Cmn_Filters();
+ //
+ Setup_Output_Directory();
+ Setup_Output_File();
+ }
+
+ private void Form_Closing( object sender, System.ComponentModel.CancelEventArgs e )
+ {
+ iSettings.Store();
+ }
+
+ private void iWizard_WizardClosedFromAuxillary( SymWizardClosureEvent aEventArgs )
+ {
+ iSettings[ "Wizard", "DialogResult"] = DialogResult.Cancel.ToString();
+ }
+
+ private void iWizard_WizardClosedFromFinish( SymWizardClosureEvent aEventArgs )
+ {
+ iSettings[ "Wizard", "DialogResult"] = DialogResult.OK.ToString();
+ }
+ #endregion
+
+ #region Pages
+
+ #region Page [Operation type]
+ private void Setup_OpType()
+ {
+ string opType = iSettings[ "Wizard", "OperationType" ];
+
+ // Make sure something is selected
+ if ( opType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps.ToString() )
+ {
+ iPG1_RB_OpType_CompareHeapDump.Checked = true;
+ }
+ else if ( opType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapCSV.ToString() )
+ {
+ iPG1_RB_OpType_CompareCSV.Checked = true;
+ }
+ else
+ {
+ // Default
+ iPG1_RB_OpType_HeapViewer.Checked = true;
+ }
+ }
+
+ private void iPG1_OpType_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ if ( iPG1_RB_OpType_HeapViewer.Checked )
+ {
+ iEngine.OperationType = HeapWizardEngine.TOperationType.EOperationTypeAnalyseAndView;
+ aEventArgs.SuggestedNewPage = iPG_SourceData_Log;
+ }
+ else if ( iPG1_RB_OpType_CompareHeapDump.Checked )
+ {
+ iEngine.OperationType = HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps;
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareHeapData;
+ }
+ else if ( iPG1_RB_OpType_CompareCSV.Checked )
+ {
+ iEngine.OperationType = HeapWizardEngine.TOperationType.EOperationTypeCompareHeapCSV;
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareCSV;
+ }
+
+ Setup_Output_File_Dynamic();
+ Setup_Output_Directory_Dynamic();
+
+ iSettings[ "Wizard", "OperationType" ] = iEngine.OperationType.ToString();
+ }
+ #endregion
+
+ #region Page [SourceData - Log file name]
+ private void Setup_SourceData_LogFileName()
+ {
+ iSettings.Load( "Wizard", iPG_SourceData_Log_FB );
+ }
+
+ private void iPG_SourceData_Log_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ string logFileName = iPG_SourceData_Log_FB.EntityName;
+
+ if ( !iPG_SourceData_Log_FB.IsValid )
+ {
+ aEventArgs.SuggestedNewPage = iPG_SourceData_Log;
+ }
+ else
+ {
+ iSettings.Save( "Wizard", iPG_SourceData_Log_FB );
+ //
+ iEngine.HeapDataOptions = new Options();
+ //
+ DataSourceAnalyser analyser = HeapReconstructorDataSourceAnalyserDialog.Analyse( logFileName );
+ SeedAnalysisFiltersAfterDataSourceScan( analyser.DataSources, iPG302_Combo_Filter );
+
+ // Only allowed to continue if we found a valid source
+ if ( iPG302_Combo_Filter.Items.Count > 0 )
+ {
+ aEventArgs.SuggestedNewPage = iPG_Cmn_Symbolics;
+ }
+ else
+ {
+ aEventArgs.SuggestedNewPage = aEventArgs.CurrentPage;
+ }
+ }
+ }
+ #endregion
+
+ #region Page [SourceData - Heap data comparison source files]
+ private void Setup_SourceData_HeapDataComparison()
+ {
+ iSettings.Load( "Wizard", iPG202_TB_LogFile1 );
+ iSettings.Load( "Wizard", iPG202_TB_LogFile2 );
+
+ // Start off with the combo's disabled
+ iPG202_Combo_ThreadName1.Enabled = false;
+ iPG202_Combo_ThreadName2.Enabled = false;
+
+ // We queue these up so that the scan occurs only after the page is actually displayed.
+ this.iPG202_TB_LogFile1.FileSelectionChanged += new SymbianUtilsUi.Controls.SymbianFileControl.FileSelectionChangedHandler( this.iPG202_TB_LogFile1_FileSelectionChanged );
+ this.iPG202_TB_LogFile2.FileSelectionChanged += new SymbianUtilsUi.Controls.SymbianFileControl.FileSelectionChangedHandler( this.iPG202_TB_LogFile2_FileSelectionChanged );
+ }
+
+ private void iPG202_TB_LogFile1_FileSelectionChanged( SymbianUtilsUi.Controls.SymbianFileControl aSelf, string aFileName )
+ {
+ DataSourceAnalyser analyser = HeapReconstructorDataSourceAnalyserDialog.Analyse( aFileName );
+ SeedAnalysisFiltersAfterDataSourceScan( analyser.DataSources, iPG202_Combo_ThreadName1 );
+
+ iPG_SourceData_CompareHeapData_GP_Log2.Enabled = ( iPG202_Combo_ThreadName1.Items.Count > 0 );
+ }
+
+ private void iPG202_TB_LogFile2_FileSelectionChanged( SymbianUtilsUi.Controls.SymbianFileControl aSelf, string aFileName )
+ {
+ DataSourceAnalyser analyser = HeapReconstructorDataSourceAnalyserDialog.Analyse( aFileName );
+
+ // Get the master thread name
+ string threadName = ThreadNameFromFilterCombo( iPG202_Combo_ThreadName1 );
+
+ if ( threadName != string.Empty )
+ {
+ }
+ else
+ {
+ analyser.DataSources.Clear();
+ }
+
+ // Seed combobox with filter options
+ SeedAnalysisFiltersAfterDataSourceScan( analyser.DataSources, iPG202_Combo_ThreadName2 );
+ }
+
+ private void iPG_SourceData_CompareHeapData_PageShownFromButtonNext( SymWizardPage aSender )
+ {
+ if ( iPG202_TB_LogFile1.EntityName != string.Empty && File.Exists( iPG202_TB_LogFile1.EntityName ) )
+ {
+ iPG202_TB_LogFile1_FileSelectionChanged( iPG202_TB_LogFile1, iPG202_TB_LogFile1.EntityName );
+ }
+ if ( iPG202_TB_LogFile2.EntityName != string.Empty && File.Exists( iPG202_TB_LogFile2.EntityName ) )
+ {
+ iPG202_TB_LogFile2_FileSelectionChanged( iPG202_TB_LogFile2, iPG202_TB_LogFile2.EntityName );
+ }
+ }
+
+ private void iPG202_SourceData_Comparison_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ iEngine.ComparisonEngineData.DataSource1 = DataSourceFromFilterCombo( iPG202_Combo_ThreadName1 );
+ iEngine.ComparisonEngineData.DataSource2 = DataSourceFromFilterCombo( iPG202_Combo_ThreadName2 );
+ //
+ if ( !( iPG202_TB_LogFile1.IsValid && iPG202_TB_LogFile2.IsValid ) )
+ {
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareHeapData;
+ }
+ else if ( iEngine.ComparisonEngineData.DataSource1 == null )
+ {
+ iPG202_TB_LogFile1.SetError( "Select a valid MemSpy heap data log" );
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareHeapData;
+ }
+ else if ( iEngine.ComparisonEngineData.DataSource2 == null )
+ {
+ iPG202_TB_LogFile2.SetError( "Select a valid MemSpy heap data log" );
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareHeapData;
+ }
+ else
+ {
+ // Get both data sources and check thread names are common
+ DataSource ds1 = (DataSource ) iPG202_Combo_ThreadName1.SelectedItem;
+ DataSource ds2 = (DataSource) iPG202_Combo_ThreadName2.SelectedItem;
+ //
+ if ( ds1.ThreadName.ToLower() != ds2.ThreadName.ToLower() )
+ {
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareHeapData;
+ iErrorProvider.SetError( iPG202_Combo_ThreadName2, "Thread names differ" );
+ }
+ else
+ {
+ iSettings.Save( "Wizard", iPG202_TB_LogFile1 );
+ iSettings.Save( "Wizard", iPG202_TB_LogFile2 );
+
+ iErrorProvider.Clear();
+ aEventArgs.SuggestedNewPage = iPG_Cmn_Symbolics;
+ }
+ }
+ }
+ #endregion
+
+ #region Page [SourceData - Heap CSV comparison source files]
+ private void Setup_SourceData_HeapCSVComparison()
+ {
+ iSettings.Load( "PG_SourceData_CompareCSV_Files", iPG_SourceData_CompareCSV_Files );
+ }
+
+ private void iPG_SourceData_CompareCSV_PageClosedFromButtonNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ // Check we have at least one valid file.
+ if ( iPG_SourceData_CompareCSV_Files.FileNames.Count == 0 )
+ {
+ aEventArgs.SuggestedNewPage = iPG_SourceData_CompareCSV;
+ }
+ else
+ {
+ iSettings.Save( "PG_SourceData_CompareCSV_Files", iPG_SourceData_CompareCSV_Files );
+ iEngine.ComparisonEngineCSV.SourceFileNames = iPG_SourceData_CompareCSV_Files.FileNames;
+ aEventArgs.SuggestedNewPage = iPG_OutputToDirectory;
+ }
+ }
+ #endregion
+
+ #region Page [Cmn - Symbolics]
+ private void Setup_Cmn_Symbolics()
+ {
+ iPG301_DebugControl.Engine = iEngine.DebugEngine;
+ }
+
+ private void iPG301_AnalysisSymbolics_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ string errorText = string.Empty;
+ if ( iPG301_DebugControl.IsReadyToPrime( out errorText ) )
+ {
+ iPG301_DebugControl.Prime();
+
+ if ( iEngine.OperationType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps )
+ {
+ aEventArgs.SuggestedNewPage = iPG_OutputToFile;
+ }
+ else
+ {
+ // If there is only one thread available, then there's no point
+ // asking the user to pick it...
+ int number = 0;
+ bool okayToProceed = SetDataSourceFromFirstAvailableThread( out number );
+ if ( okayToProceed && number == 1 )
+ {
+ aEventArgs.SuggestedNewPage = iPG_Final;
+ }
+ else
+ {
+ aEventArgs.SuggestedNewPage = iPG_Cmn_Filters;
+ }
+ }
+
+ // Also save debug engine configuration
+ iPG301_DebugControl.XmlSettingsSave();
+ }
+ else
+ {
+ MessageBox.Show( errorText, "Error" );
+ aEventArgs.SuggestedNewPage = iPG_Cmn_Symbolics;
+ }
+ }
+ #endregion
+
+ #region Page [Cmn - Heap thread filter]
+ private void Setup_Cmn_Filters()
+ {
+ }
+
+ private void iPG302_Cmn_Filters_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ if ( SetDataSourceFromFirstAvailableThread() )
+ {
+ // Clear any error
+ iErrorProvider.SetError( iPG302_Combo_Filter, string.Empty );
+
+ // Decide where to go next...
+ aEventArgs.SuggestedNewPage = iPG_Final;
+ }
+ else
+ {
+ iErrorProvider.SetError( iPG302_Combo_Filter, "No thread's were detected. Is the log corrupt?" );
+ aEventArgs.SuggestedNewPage = iPG_Cmn_Filters;
+ }
+ }
+ #endregion
+
+ #region Page [Output - Directory]
+ private void Setup_Output_Directory()
+ {
+ iSettings.Load( "Wizard", iPG_OutputToDirectory_FB );
+ }
+
+ private void Setup_Output_Directory_Dynamic()
+ {
+ iHeader_OutputToDirectory.Title = "Save CSV Comparsion Reports";
+ iHeader_OutputToDirectory.Description += "Microsoft Excel comparison reports";
+ }
+
+ private void iPG_OutputToDirectory_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ if ( !iPG_OutputToDirectory_FB.IsValid )
+ {
+ aEventArgs.SuggestedNewPage = iPG_OutputToDirectory;
+ }
+ else
+ {
+ string dir = iPG_OutputToDirectory_FB.EntityName;
+ iEngine.ComparisonEngineCSV.OutputDirectory = dir;
+ iSettings.Save( "Wizard", iPG_OutputToDirectory_FB );
+ aEventArgs.SuggestedNewPage = iPG_Final;
+ }
+ }
+ #endregion
+
+ #region Page [Output - File]
+ private void Setup_Output_File()
+ {
+ iSettings.Load( "Wizard", iPG_OutputToFile_FB );
+ }
+
+ private void Setup_Output_File_Dynamic()
+ {
+ if ( iEngine.OperationType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps )
+ {
+ iHeader_OutputToFile.Title = "Save Heap Dump Comparison to Microsoft Excel";
+ iHeader_OutputToFile.Description += "Microsoft Excel comparison report";
+ }
+ }
+
+ private void iPG500_Comparison_Output_CloseFromNext( SymWizardPageTransitionEvent aEventArgs )
+ {
+ if ( iPG_OutputToFile_FB.IsValid )
+ {
+ iSettings.Save( "Wizard", iPG_OutputToFile_FB );
+ //
+ if ( iEngine.OperationType == HeapWizardEngine.TOperationType.EOperationTypeCompareHeapDumps )
+ {
+ iEngine.ComparisonEngineData.OutputFileName = iPG_OutputToFile_FB.EntityName;
+ }
+ //
+ aEventArgs.SuggestedNewPage = iPG_Final;
+ }
+ else
+ {
+ aEventArgs.SuggestedNewPage = iPG_OutputToFile;
+ }
+ }
+ #endregion
+
+ #endregion
+
+ #region Internal methods
+ private bool SetDataSourceFromFirstAvailableThread()
+ {
+ int number;
+ return SetDataSourceFromFirstAvailableThread( out number );
+ }
+
+ private bool SetDataSourceFromFirstAvailableThread( out int aNumberOfDataSources )
+ {
+ bool okayToProceed = false;
+
+ // Must be at least one thread selected
+ DataSource dataSource = (DataSource) iPG302_Combo_Filter.SelectedItem;
+ if ( dataSource == null || iPG302_Combo_Filter.Items.Count == 0 )
+ {
+ // Can't do anything at this point... Let a later page
+ // handle this scenario.
+ aNumberOfDataSources = 0;
+ }
+ else
+ {
+ aNumberOfDataSources = iPG302_Combo_Filter.Items.Count;
+ iEngine.AnalysisEngine.DataSource = dataSource;
+
+ // Save setting for filter thread
+ iSettings[ "Wizard", iPG302_Combo_Filter.Name ] = iPG302_Combo_Filter.Text;
+
+ // Good to go
+ okayToProceed = true;
+ }
+
+ return okayToProceed;
+ }
+
+ private void SeedAnalysisFiltersAfterDataSourceScan( DataSourceCollection aSources, ComboBox aCombo )
+ {
+ // Thread filtering - seed with detected threads
+ aCombo.BeginUpdate();
+ aCombo.Items.Clear();
+ foreach ( DataSource source in aSources )
+ {
+ bool allowSource = true;
+ bool containsErrors = CheckSourceForErrors( source, out allowSource );
+ if ( !containsErrors || allowSource )
+ {
+ aCombo.Items.Add( source );
+ }
+ }
+
+ // Make sure something is selected
+ if ( aCombo.Items.Count > 0 )
+ {
+ iErrorProvider.SetError( aCombo, string.Empty );
+
+ int selectedThreadIndex = 0;
+
+ // If the user has picked a thread previously, try to select the same one
+ // again this time.
+ string lastSelectedThread = iSettings[ "Wizard", aCombo.Name ];
+ if ( lastSelectedThread.Length > 0 )
+ {
+ int index = aSources.IndexOf( lastSelectedThread );
+ if ( index >= 0 )
+ {
+ selectedThreadIndex = index;
+ }
+ }
+
+ // Now pick the thread...
+ aCombo.SelectedIndex = selectedThreadIndex;
+ }
+ else
+ {
+ iErrorProvider.SetError( aCombo, "No thread's were detected. Is the log corrupt?" );
+ }
+
+ aCombo.Enabled = ( aCombo.Items.Count > 1 );
+ aCombo.EndUpdate();
+ }
+
+ private bool CheckSourceForErrors( DataSource aSource, out bool aAllowSourceAnyway )
+ {
+ aAllowSourceAnyway = false;
+ string description = string.Empty;
+ //
+ bool errorsDetected = aSource.ErrorsDetected( out description );
+ if ( errorsDetected )
+ {
+ StringBuilder msg = new StringBuilder();
+ msg.Append( "File: " + aSource.FileName );
+ msg.Append( System.Environment.NewLine );
+ msg.Append( "Thread: " + aSource.ThreadName );
+ msg.Append( System.Environment.NewLine );
+ msg.Append( System.Environment.NewLine );
+ msg.Append( description );
+ msg.Append( System.Environment.NewLine );
+ msg.Append( "You are recommended to save the heap data to zip and contact" );
+ msg.Append( "your support provider." );
+ msg.Append( System.Environment.NewLine );
+ msg.Append( System.Environment.NewLine );
+ msg.Append( "Do you want to allow this data anyway?" );
+ //
+ string title = string.Format( "Errors Detected - {0}", aSource.ThreadName );
+ DialogResult result = MessageBox.Show( msg.ToString(), title, MessageBoxButtons.YesNo );
+ aAllowSourceAnyway = ( result == DialogResult.Yes );
+ }
+ //
+ return errorsDetected;
+ }
+
+ private static DataSource DataSourceFromFilterCombo( ComboBox aCombo )
+ {
+ DataSource ret = null;
+ //
+ int index = aCombo.SelectedIndex;
+ if ( index >= 0 && index < aCombo.Items.Count )
+ {
+ object obj = aCombo.Items[ index ];
+ if ( obj is DataSource )
+ {
+ ret = (DataSource) obj;
+ }
+ }
+ //
+ return ret;
+ }
+
+ private static string ThreadNameFromFilterCombo( ComboBox aCombo )
+ {
+ string ret = string.Empty;
+ //
+ DataSource ds = DataSourceFromFilterCombo( aCombo );
+ if ( ds != null )
+ {
+ ret = ds.ThreadName;
+ }
+ //
+ return ret;
+ }
+ #endregion
+
+ #region Data members
+ private readonly HeapWizardEngine iEngine;
+ private readonly XmlSettings iSettings;
+ #endregion
+ }
+}