sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "LogViewWindow.h" sl@0: sl@0: // User includes sl@0: #include "logclientop.h" sl@0: #include "logclipanic.h" sl@0: #include "LogViewWindowChangeObserver.h" sl@0: sl@0: // Constants sl@0: const TInt KWindowSlideSize = 2; sl@0: sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: // -----> CLogViewWindow (source) sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: CLogViewWindow::CLogViewWindow(RLogSession& aSession, TLogViewId aViewId, TInt aWindowSize, MLogViewChangeObserver* aCascadeObserver, TInt aPriority) sl@0: : CLogActive(aPriority), iSession(aSession), iViewId(aViewId), iWindowSize(aWindowSize), iCascadeObserver(aCascadeObserver), iEvents(aWindowSize) sl@0: { sl@0: Reset(); sl@0: } sl@0: sl@0: CLogViewWindow::~CLogViewWindow() sl@0: { sl@0: Cancel(); sl@0: // sl@0: delete iWindowChangeObserver; sl@0: delete iWindowPreparer; sl@0: delete iWindowFetcher; sl@0: delete iWindowLockObserver; sl@0: // sl@0: iEvents.ResetAndDestroy(); sl@0: iEvents.Close(); sl@0: } sl@0: sl@0: void CLogViewWindow::ConstructL(CLogPackage& aPackage) sl@0: { sl@0: iWindowPreparer = new(ELeave) CLogViewSetupClientOp(iSession, aPackage, CActive::EPriorityStandard); sl@0: // sl@0: iWindowFetcher = new(ELeave) CLogViewWindowFetcher(iSession, iViewId, *this, CActive::EPriorityIdle + 1); sl@0: iWindowFetcher->ConstructL(); sl@0: // sl@0: iWindowLockObserver = new(ELeave) CLogViewWindowLockObserver(iSession, iViewId, *this, CActive::EPriorityHigh); sl@0: iWindowLockObserver->ConstructL(); sl@0: // sl@0: iWindowChangeObserver = new(ELeave) CLogViewWindowChangeObserver(*this); sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: TInt CLogViewWindow::Setup(const CLogFilterList& aFilterList, TInt aParam, TLogFilterConstructionType aFilterConstructionType) sl@0: { sl@0: Reset(); sl@0: iViewRecordCount = iWindowPreparer->Start(iViewId, aFilterList, aParam, aFilterConstructionType); sl@0: return iViewRecordCount; sl@0: } sl@0: sl@0: TBool CLogViewWindow::NavigateL(TLogNavigation aNavigate, TRequestStatus& aStatus) sl@0: { sl@0: // Check why we're already active sl@0: switch(iState) sl@0: { sl@0: case EStateIdle: sl@0: case EStateLocked: sl@0: __ASSERT_DEBUG(!IsActive(), Panic(ELogWindowStateMachineNavigationError1)); sl@0: break; sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: case EStateNavigateWithinWindow: sl@0: // We're trying to catch up with some changes.. use the requested sl@0: // window as the new window, but refetch everything. sl@0: __ASSERT_DEBUG(IsActive(), Panic(ELogWindowStateMachineNavigationError2)); sl@0: SilentCancel(); sl@0: iWindow = iWindowFetcher->RequestedWindow(); sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: // Perform boundary checks sl@0: TInt cursorPos = CalculateCursorPosition(aNavigate); sl@0: if (cursorPos < 0 || cursorPos >= iViewRecordCount) sl@0: { sl@0: // Can't navigate to the specified position sl@0: return EFalse; sl@0: } sl@0: sl@0: // Check whether the cursor position falls within the view window sl@0: if (iWindow.iValid && iWindow.Contains(cursorPos)) sl@0: { sl@0: // Can return event from window sl@0: CompleteRequest(cursorPos); sl@0: ChangeState(EStateNavigateWithinWindow); sl@0: } sl@0: else sl@0: { sl@0: // Have to fetch a new window. Work it out... sl@0: TLogWindowAndCursor window; sl@0: CalculateWindowForCursorPosition(cursorPos, window); sl@0: window.iCursorPosition = cursorPos; sl@0: iWindowFetcher->PrepareToFetchWindowL(window); sl@0: // sl@0: CompleteRequest(KErrNone); sl@0: ChangeState(EStateFetchingWindow); sl@0: } sl@0: sl@0: // Okay to (try to) navigate here sl@0: Queue(aStatus); sl@0: return ETrue; sl@0: } sl@0: sl@0: void CLogViewWindow::RemoveFromWindowIfPresentL(TLogId aId) sl@0: { sl@0: TInt index = FindEvent(aId); sl@0: if (index >= 0) sl@0: { sl@0: // Ignore next window removal event (since we're proactively removing sl@0: // the event from the client side without server prompting). sl@0: iWindowChangeObserver->IgnoreNextEventL(aId, CLogViewWindowChangeObserver::ELogEventTypeDelete); sl@0: sl@0: // Delete item sl@0: RemoveEvent(index); sl@0: sl@0: // Map onto full view position sl@0: index += iWindow.iLower; sl@0: sl@0: // Update window - when removing the last event from the window, we must sl@0: // ensure we mark the window as invalid. sl@0: if (iWindow.AdjustForItemDeletion(index) == TLogWindowAndCursor::EWindowAffected && iEvents.Count() == 0) sl@0: { sl@0: iWindow.Reset(); sl@0: } sl@0: } sl@0: // sl@0: --iViewRecordCount; sl@0: } sl@0: sl@0: MLogViewChangeObserverInternal& CLogViewWindow::ChangeObserver() sl@0: { sl@0: __ASSERT_ALWAYS(iWindowChangeObserver, Panic(ELogWindowNoChangeObserver)); sl@0: return *iWindowChangeObserver; sl@0: } sl@0: sl@0: const CLogEvent& CLogViewWindow::CurrsorEvent() const sl@0: { sl@0: // Map the cursor position to fall within the window sl@0: const TInt mappedIndex = iWindow.WindowIndexFromCursorPosition(); sl@0: const TInt count = iEvents.Count(); sl@0: __ASSERT_ALWAYS(mappedIndex >= 0 && mappedIndex < count, Panic(ELogWindowCursorCalculationOutOfBounds)); sl@0: return *iEvents[mappedIndex]; sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::HandleWindowLockStatusChangeL(TLogViewLockStatus aStatus) sl@0: { sl@0: switch(aStatus) sl@0: { sl@0: case ELogViewWindowLocked: sl@0: SilentCancel(); sl@0: iState = EStateLocked; sl@0: break; sl@0: case ELogViewWindowOpen: sl@0: if (iState == EStateLocked) sl@0: iState = EStateIdle; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: // The window is never valid after a change in lock status sl@0: iWindow.iValid = EFalse; sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::HandleFetchedWindowItemL(TInt /*aItemIndex*/, CLogEvent* aEvent) sl@0: { sl@0: // IMPROVEMENT: could use aItemIndex as the insertion point? sl@0: User::LeaveIfError(iEvents.Append(aEvent)); sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::HandleLogViewChangeEventAddedL(TLogId aId, TInt aViewIndex, TInt aChangeIndex, TInt aTotalChangeCount) sl@0: { sl@0: /////////////////////////////////////// sl@0: // USE CASE 1: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item X is added => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 7 sl@0: // View Contents: X A B C D E F G sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 2: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item X is added => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 7 sl@0: // View Contents: X A B C D E F G sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 3: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item X is added => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 7 sl@0: // View Contents: X A B C D E F G sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 4: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, change item Z so that it now appears in the view sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 7 sl@0: // View Contents: A B C Z D E F G sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 5: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, change item Z so that it now appears in the view sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 7 sl@0: // View Contents: A B C Z D E F G sl@0: // sl@0: /////////////////////////////////////// sl@0: //RDebug::Print(_L("CLogViewWindow::HandleLogViewChangeEventAddedL() - aId: %3d, aViewIndex: %3d, aChangeIndex: %3d, aTotalChangeCount: %d, cursorPos: %3d, window: (%3d, %3d), viewCount: %3d, iState: %d"), aId, aViewIndex, aChangeIndex, aTotalChangeCount, iWindow.iCursorPosition, iWindow.iLower, iWindow.iUpper, iViewRecordCount, iState); sl@0: sl@0: // Must compare against the current window (if this object is idle) or against sl@0: // the window fetcher's window if it is in the process of making a fetch sl@0: TLogWindowAndCursor currentWindow; sl@0: switch(iState) sl@0: { sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: currentWindow = iWindowFetcher->RequestedWindow(); sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: case EStateIdle: sl@0: case EStateLocked: sl@0: currentWindow = iWindow; sl@0: break; sl@0: } sl@0: sl@0: // If the addition took place after the window, then we do nothing (except update the sl@0: // total view record count) sl@0: if (aViewIndex <= currentWindow.iUpper) sl@0: { sl@0: // If the addition took place before our window, or at the very start, then we simply need to adjust sl@0: // the window & cursor position. If the window fetcher was active then this will affect the window sl@0: // being fetched - in this case, we MUST refetch the whole window. sl@0: if (iState == EStateIdle && aViewIndex <= currentWindow.iLower) sl@0: { sl@0: iWindow.AdjustForItemAddition(aViewIndex); sl@0: } sl@0: else sl@0: { sl@0: // If the addition took place within the window, then we have to refetch the window sl@0: TBool refetch = ETrue; sl@0: TLogWindowAndCursor newWindow; sl@0: // sl@0: switch(iState) sl@0: { sl@0: case EStateIdle: sl@0: newWindow = iWindow; sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: // Since we complete our own request status with the new cursor position, sl@0: // we can use that here as the desired cursor position after the fetch sl@0: newWindow = iWindow; sl@0: newWindow.iCursorPosition = iStatus.Int(); sl@0: break; sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: newWindow = iWindowFetcher->RequestedWindow(); sl@0: break; sl@0: case EStateLocked: sl@0: // Don't need to do anything. When the view is unlocked, we refetch anyway sl@0: refetch = EFalse; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: // sl@0: if (refetch) sl@0: { sl@0: newWindow.AdjustForItemAddition(aViewIndex); sl@0: RefetchL(newWindow, newWindow.iCursorPosition); sl@0: } sl@0: } sl@0: } sl@0: sl@0: // Increase the total view size sl@0: ++iViewRecordCount; sl@0: sl@0: if (iCascadeObserver) sl@0: iCascadeObserver->HandleLogViewChangeEventAddedL(aId, aViewIndex, aChangeIndex, aTotalChangeCount); sl@0: } sl@0: sl@0: void CLogViewWindow::HandleLogViewChangeEventChangedL(TLogId aId, TInt aViewIndex, TInt aChangeIndex, TInt aTotalChangeCount) sl@0: { sl@0: //RDebug::Print(_L("CLogViewWindow::HandleLogViewChangeEventChangedL() - aId: %3d, aViewIndex: %3d, aChangeIndex: %3d, aTotalChangeCount: %d, cursorPos: %3d, window: (%3d, %3d), viewCount: %3d, iState: %d"), aId, aViewIndex, aChangeIndex, aTotalChangeCount, iWindow.iCursorPosition, iWindow.iLower, iWindow.iUpper, iViewRecordCount, iState); sl@0: sl@0: // Must compare against the current window (if this object is idle) or against sl@0: // the window fetcher's window if it is in the process of making a fetch sl@0: TLogWindowAndCursor currentWindow; sl@0: switch(iState) sl@0: { sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: currentWindow = iWindowFetcher->RequestedWindow(); sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: case EStateIdle: sl@0: case EStateLocked: sl@0: currentWindow = iWindow; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: // If the event that changed was within the view, then we have to refetch it sl@0: if (currentWindow.Contains(aViewIndex)) sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EStateIdle: sl@0: RefetchL(iWindow, iWindow.iCursorPosition); sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: // Since we complete our own request status with the new cursor position, sl@0: // we can use that here as the desired cursor position after the fetch sl@0: RefetchL(iWindow, iStatus.Int()); sl@0: break; sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: RefetchL(iWindowFetcher->RequestedWindow(), iWindowFetcher->RequestedWindow().iCursorPosition); sl@0: break; sl@0: case EStateLocked: sl@0: // Don't need to do anything. When the view is unlocked, we refetch anyway sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (iCascadeObserver) sl@0: iCascadeObserver->HandleLogViewChangeEventChangedL(aId, aViewIndex, aChangeIndex, aTotalChangeCount); sl@0: } sl@0: sl@0: void CLogViewWindow::HandleLogViewChangeEventDeletedL(TLogId aId, TInt aViewIndex, TInt aChangeIndex, TInt aTotalChangeCount) sl@0: { sl@0: /////////////////////////////////////// sl@0: // USE CASE 1: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item 5 is deleted => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 sl@0: // View Contents: A B C D E G sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 2: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item 4 is deleted => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 sl@0: // View Contents: A B C D F G sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 3: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item 6 is deleted => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 sl@0: // View Contents: A B C D E F sl@0: // sl@0: /////////////////////////////////////// sl@0: // USE CASE 4: sl@0: /////////////////////////////////////// sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 6 sl@0: // View Contents: A B C D E F G sl@0: // sl@0: // Then, item 6 is deleted => sl@0: // sl@0: // Cursor position: * sl@0: // View Index: 0 1 2 3 4 5 sl@0: // View Contents: B C D E F G sl@0: // sl@0: /////////////////////////////////////// sl@0: //RDebug::Print(_L("CLogViewWindow::HandleLogViewChangeEventDeletedL() - aId: %3d, aViewIndex: %3d, aChangeIndex: %3d, aTotalChangeCount: %d, cursorPos: %3d, window: (%3d, %3d), viewCount: %3d, iState: %d"), aId, aViewIndex, aChangeIndex, aTotalChangeCount, iWindow.iCursorPosition, iWindow.iLower, iWindow.iUpper, iViewRecordCount, iState); sl@0: sl@0: // Must compare against the current window (if this object is idle) or against sl@0: // the window fetcher's window if it is in the process of making a fetch sl@0: TLogWindowAndCursor currentWindow; sl@0: switch(iState) sl@0: { sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: currentWindow = iWindowFetcher->RequestedWindow(); sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: case EStateIdle: sl@0: case EStateLocked: sl@0: currentWindow = iWindow; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: // Does the change alter our current window in any way? sl@0: if (aViewIndex <= currentWindow.iUpper) sl@0: { sl@0: TBool refetch = ETrue; sl@0: TLogWindowAndCursor newWindow; sl@0: // sl@0: switch(iState) sl@0: { sl@0: case EStateIdle: sl@0: FindAndRemoveEvent(aId); sl@0: sl@0: // When removing the last event from the window, we must ensure we mark sl@0: // the window as invalid. sl@0: if (iWindow.AdjustForItemDeletion(aViewIndex) == TLogWindowAndCursor::EWindowAffected && iEvents.Count() == 0) sl@0: { sl@0: iWindow.Reset(); sl@0: } sl@0: sl@0: refetch = EFalse; sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: newWindow = iWindow; sl@0: newWindow.iCursorPosition = iStatus.Int(); sl@0: break; sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: newWindow = iWindowFetcher->RequestedWindow(); sl@0: break; sl@0: case EStateLocked: sl@0: // Don't need to do anything. When the view is unlocked, we refetch anyway sl@0: refetch = EFalse; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: // sl@0: if (refetch) sl@0: { sl@0: newWindow.AdjustForItemDeletion(aViewIndex); sl@0: RefetchL(newWindow, newWindow.iCursorPosition); sl@0: } sl@0: } sl@0: sl@0: // Reduce the total view size sl@0: --iViewRecordCount; sl@0: sl@0: if (iCascadeObserver) sl@0: iCascadeObserver->HandleLogViewChangeEventDeletedL(aId, aViewIndex, aChangeIndex, aTotalChangeCount); sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::HandleLogViewChangeEventLogClearedL() sl@0: { sl@0: Cancel(); sl@0: Reset(); sl@0: sl@0: // This event type is not cascaded to the client of the log engine sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::DoRunL() sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EStateFetchingWindow: sl@0: StateHandleWindowFetchStarting(); sl@0: break; sl@0: case EStateProcessingWindow: sl@0: StateHandleWindowFetchedL(); sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: StateHandleNavigation(); sl@0: break; sl@0: case EStateIdle: sl@0: case EStateLocked: sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void CLogViewWindow::DoCancel() sl@0: { sl@0: if(iState == EStateProcessingWindow) sl@0: { sl@0: iWindowFetcher->Cancel(); sl@0: } sl@0: CLogActive::DoCancel(); sl@0: } sl@0: sl@0: void CLogViewWindow::DoComplete(TInt& aComplete) sl@0: { sl@0: switch(iState) sl@0: { sl@0: default: sl@0: case EStateIdle: sl@0: break; sl@0: case EStateNavigateWithinWindow: sl@0: if (aComplete < KErrNone) sl@0: { sl@0: // Reset to known state sl@0: iState = EStateIdle; sl@0: } sl@0: break; sl@0: case EStateFetchingWindow: sl@0: case EStateProcessingWindow: sl@0: if (aComplete < KErrNone) sl@0: { sl@0: // Reset to known state sl@0: iState = EStateIdle; sl@0: iWindow = iWindowFetcher->RequestedWindow(); sl@0: } sl@0: break; sl@0: case EStateLocked: sl@0: aComplete = KErrAccessDenied; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::StateHandleWindowFetchStarting() sl@0: { sl@0: iEvents.ResetAndDestroy(); sl@0: iWindowFetcher->Start(iStatus); sl@0: ChangeState(EStateProcessingWindow); sl@0: SetActive(); sl@0: } sl@0: sl@0: void CLogViewWindow::StateHandleWindowFetchedL() sl@0: { sl@0: const TInt count = iEvents.Count(); sl@0: const TInt expected = iWindowFetcher->RequestedWindow().Range(); sl@0: if (expected != count) sl@0: User::Leave(KErrGeneral); sl@0: // sl@0: iWindow = iWindowFetcher->RequestedWindow(); sl@0: CompleteRequest(iWindow.iCursorPosition); sl@0: ChangeState(EStateNavigateWithinWindow); sl@0: } sl@0: sl@0: void CLogViewWindow::StateHandleNavigation() sl@0: { sl@0: const TInt cursorPos = iStatus.Int(); sl@0: __ASSERT_ALWAYS(iWindow.Contains(cursorPos), Panic(ELogWindowNavigationOutsideWindow)); sl@0: iWindow.iCursorPosition = cursorPos; sl@0: ChangeState(EStateIdle); sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogViewWindow::CompleteRequest(TInt aCompletionCode) sl@0: { sl@0: if (!IsActive() || (IsActive() && iStatus == KRequestPending)) sl@0: { sl@0: TRequestStatus* status = &iStatus; sl@0: User::RequestComplete(status, aCompletionCode); sl@0: if (!IsActive()) sl@0: SetActive(); sl@0: } sl@0: } sl@0: sl@0: void CLogViewWindow::CalculateWindowForCursorPosition(TInt aCursorPosition, TLogWindow& aWindow) const sl@0: { sl@0: aWindow.iLower = Max(0, aCursorPosition - KWindowSlideSize - 1); sl@0: aWindow.iUpper = Min(iViewRecordCount - 1, aWindow.iLower + iWindowSize - 1); sl@0: } sl@0: sl@0: void CLogViewWindow::Reset() sl@0: { sl@0: Cancel(); sl@0: // sl@0: iViewRecordCount = 0; sl@0: iWindow.Reset(); sl@0: iEvents.ResetAndDestroy(); sl@0: iState = EStateIdle; sl@0: } sl@0: sl@0: void CLogViewWindow::SilentCancel() sl@0: { sl@0: iWindowFetcher->SilentCancel(); sl@0: } sl@0: sl@0: void CLogViewWindow::RefetchL(const TLogWindow& aWindow, TInt aCursor) sl@0: { sl@0: SilentCancel(); sl@0: // sl@0: TLogWindowAndCursor newWindow(aWindow, aCursor); sl@0: iWindowFetcher->PrepareToFetchWindowL(newWindow); sl@0: CompleteRequest(KErrNone); sl@0: ChangeState(EStateFetchingWindow); sl@0: } sl@0: sl@0: void CLogViewWindow::ChangeState(TWindowState aNewState) sl@0: { sl@0: iState = aNewState; sl@0: } sl@0: sl@0: void CLogViewWindow::RemoveEvent(TInt aIndex) sl@0: { sl@0: CLogEvent* event = iEvents[aIndex]; sl@0: delete event; sl@0: iEvents.Remove(aIndex); sl@0: } sl@0: sl@0: TInt CLogViewWindow::CalculateCursorPosition(TLogNavigation aNavigate) const sl@0: { sl@0: TInt position = 0; sl@0: switch(aNavigate) sl@0: { sl@0: case ELogNavigateForwards: sl@0: position = iWindow.iCursorPosition + 1; sl@0: break; sl@0: case ELogNavigateBackwards: sl@0: position = iWindow.iCursorPosition - 1; sl@0: break; sl@0: case ELogNavigateFirst: sl@0: position = 0; sl@0: break; sl@0: case ELogNavigateLast: sl@0: position = iViewRecordCount - 1; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: return position; sl@0: } sl@0: sl@0: TInt CLogViewWindow::FindEvent(TLogId aId) sl@0: { sl@0: const TInt count = iEvents.Count(); sl@0: for(TInt i=0; iId() == aId) sl@0: return i; sl@0: } sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: TInt CLogViewWindow::FindAndRemoveEvent(TLogId aId) sl@0: { sl@0: TInt index = FindEvent(aId); sl@0: if (index >= 0) sl@0: { sl@0: RemoveEvent(index); sl@0: index += iWindow.iLower; sl@0: } sl@0: return index; sl@0: }