Files
UnrealEngineUWP/Engine/Source/Developer/MessageLog/Private/Model/MessageLogListingModel.h

163 lines
5.0 KiB
C
Raw Normal View History

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
#pragma once
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3209340 on 2016/11/23 by Ben.Marsh Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h. Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms. * Every header now includes everything it needs to compile. * There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first. * There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h. * Every .cpp file includes its matching .h file first. * This helps validate that each header is including everything it needs to compile. * No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more. * You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there. * There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible. * No engine code explicitly includes a precompiled header any more. * We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies. * PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files. Tool used to generate this transform is at Engine\Source\Programs\IncludeTool. [CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
#include "CoreMinimal.h"
#include "Containers/List.h"
#include "Logging/TokenizedMessage.h"
/** Define the container type for all the messages */
typedef TArray< TSharedRef<FTokenizedMessage> > MessageContainer;
/** This class represents a set of rich tokenized messages for a particular system */
class FMessageLogListingModel : public TSharedFromThis< FMessageLogListingModel >
{
protected:
struct FPage
{
FPage( const FText& InTitle )
: Title( InTitle )
{
}
/** The title of this page */
FText Title;
/** The list of messages in this log listing */
MessageContainer Messages;
};
public:
virtual ~FMessageLogListingModel() {}
/**
* Factory method which creates a new FMessageLogListingModel object
*
* @param InLogName The name of the log
*/
static TSharedRef< FMessageLogListingModel > Create( const FName& InLogName )
{
TSharedRef< FMessageLogListingModel > NewLogListing( new FMessageLogListingModel( InLogName ) );
return NewLogListing;
}
/** Broadcasts whenever the message log listing changes */
DECLARE_EVENT( FMessageLogListingModel, FChangedEvent )
FChangedEvent& OnChanged() { return ChangedEvent; }
/** Retrieves the name identifier for this log listing */
const FName& GetName() const { return LogName; }
/** Returns the message at the specified index */
const TSharedPtr<FTokenizedMessage> GetMessageAtIndex( const uint32 PageIndex, const int32 MessageIndex ) const;
/** Tries to find the first message that matches the message data */
const TSharedPtr<FTokenizedMessage> GetMessageFromData( const FTokenizedMiscData& MessageData ) const;
/** Gets all messages as a string */
FText GetAllMessagesAsText(const uint32 PageIndex) const;
/** Obtains a const iterator to the message data structure */
MessageContainer::TConstIterator GetMessageIterator(uint32 PageIndex) const;
/** Replaces the message at the given index */
int32 ReplaceMessage( const TSharedRef< FTokenizedMessage >& NewMessage, const uint32 PageIndex, const int32 MessageIndex );
/** Appends a message */
void AddMessage( const TSharedRef< FTokenizedMessage >& NewMessage, bool bMirrorToOutputLog = true );
/** Appends multiple messages */
void AddMessages( const TArray< TSharedRef< FTokenizedMessage > >& NewMessages, bool bMirrorToOutputLog = true );
/** Clears all messages */
void ClearMessages();
/**
* Add a new page. Old pages are only kept around if they contain messages, so if the current
* page is empty, this call does nothing.
* @param InTitle The title that will be displayed for this page.
* @param InMaxPages The maximum number of pages we keep around. If the count is exceeded,
* we discard the oldest page.
*/
void NewPage( const FText& InTitle, uint32 InMaxPages );
/** Get the number of pages contained in this log */
uint32 NumPages() const;
/** Get the number of messages on the passed-in page */
uint32 NumMessages( uint32 PageIndex ) const;
/**
* Get the title of the page at the specified index
* @param PageIndex The index of the page
*/
const FText& GetPageTitle( const uint32 PageIndex ) const;
/** Helper function for RemoveDuplicates(), exposed so the ViewModel can use it too */
static bool AreMessagesEqual(const TSharedRef< FTokenizedMessage >& Message0, const TSharedRef< FTokenizedMessage >& Message1);
/** Remove any messages that are duplicates of one another - O(n^2) */
void RemoveDuplicates(uint32 PageIndex);
protected:
/** Will broadcast to all registered observers informing them of a change */
virtual void Notify() { ChangedEvent.Broadcast(); }
/** Access the current page (we only add messages to this page */
FPage& CurrentPage() const;
/** Get a page by index - uses cache to speed up linked list access */
FPage* PageAtIndex(const uint32 PageIndex) const;
/** Create a new page if we have one pending */
void CreateNewPageIfRequired();
private:
/**
* FMessageLogListingModel Constructor
*
* @param InLogName The name of the log
*/
FMessageLogListingModel( const FName& InLogName )
: LogName( InLogName )
, bIsPrintingToOutputLog( false )
{
check( LogName != NAME_None );
// create default page
Pages.AddTail(FPage(FText::FromName(LogName)));
CachedPage = &Pages.GetTail()->GetValue();
CachedPageIndex = 0;
}
/** Helper function for AddMessage and AddMessages */
void AddMessageInternal( const TSharedRef<FTokenizedMessage>& NewMessage, bool bMirrorToOutputLog );
private:
/** The name of a pending page */
FText PendingPageName;
/** The cap on the number of pages we have */
uint32 MaxPages;
/** The list of pages in this log listing */
TDoubleLinkedList<FPage> Pages;
/** Name of the listing, for identification */
FName LogName;
/** Delegate to call when data is changed */
FChangedEvent ChangedEvent;
// Are we currently processing the output log mirror? If so, we drop any additional messages we receive, as they are duplicates
bool bIsPrintingToOutputLog;
/** Cached page index */
mutable uint32 CachedPageIndex;
/** Cached page */
mutable FPage* CachedPage;
};