DirectPrint/DirectPrintApp/engine/src/directprintengine.cpp
changeset 19 2275db202402
parent 11 613a5ff70823
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DirectPrint/DirectPrintApp/engine/src/directprintengine.cpp	Tue May 11 14:10:02 2010 +0800
@@ -0,0 +1,649 @@
+/*
+* Copyright (c) 2010 Kanrikogaku Kenkyusho, Ltd.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Kanrikogaku Kenkyusho, Ltd. - Initial contribution
+*
+* Contributors:
+*
+* Description:
+* {Description of the file}
+*
+*/
+
+#include <pdrport.h>				// CFilePrinterPort
+#include <TXTETEXT.H>				// CEditableText
+#include <TXTRICH.H>				// CRichText
+#include <FLDBLTIN.H>				// CPageNumField
+#include <flddef.h>					// KPageNumberFieldUid, KNumPagesFieldUid
+#include <stringloader.h>			// StringLoader
+#include <xmlengdocument.h>			// RXmlEngDocument
+#include <xmlengelement.h>			// TXmlEngElement
+#include <xmlengattr.h>				// TXmlEngAttr
+#include <xmlengnodelist.h>			// RXmlEngNodeList
+#include <bautils.h>				// BaflUtils
+#include <eikenv.h>					// CEikonEnv
+
+#include "clog.h"
+#include <directprintapp.rsg>
+#include "directprintengine.h"
+#include "directprintband.h"
+#include "directprintengineobserver.h"
+#include "directprintmodel.h"
+#include "directprintbanduid.h"
+
+//! Default Page spec in Twips
+#define KDefaultPageSpecInTwips TPageSpec(TPageSpec::EPortrait,TSize(11906,16838))
+
+CDirectPrintEngine::CDirectPrintEngine(CDirectPrintModel& aModel)
+	: iModel(aModel)
+	{
+	}
+
+CDirectPrintEngine::~CDirectPrintEngine()
+	{
+	if (iProgressDialog)
+		{
+		TRAP_IGNORE(iProgressDialog->ProcessFinishedL());
+		delete iProgressDialog;
+		iProgressDialog = NULL;
+		}
+
+	if (iPrintBand)
+		{
+		delete iPrintBand;
+		iPrintBand = NULL;
+		}
+
+	iPrintSetup->FreeModelList();
+	delete iPrintSetup;
+	delete iProgressMessage;
+	iFs.Close();
+	}
+
+CDirectPrintEngine* CDirectPrintEngine::NewL(CDirectPrintModel& aModel)
+	{
+	CDirectPrintEngine* self = CDirectPrintEngine::NewLC(aModel);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CDirectPrintEngine* CDirectPrintEngine::NewLC(CDirectPrintModel& aModel)
+	{
+	CDirectPrintEngine* self = new(ELeave) CDirectPrintEngine(aModel);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+void CDirectPrintEngine::ConstructL()
+	{
+	LOG("CDirectPrintEngine::ConstructL BEGIN");
+	iFs.Connect();
+
+	iPrintSetup = CPrintSetup::NewL();
+	iPrintSetup->AddPrinterDriverDirL(KDefaultPrinterDriverPath);
+	iModelList = iPrintSetup->ModelNameListL(iFs);
+
+#ifdef _DEBUG
+	LOG1("ModelCount=[%d]", ModelCount());
+	for (TInt i=0; i < ModelCount(); i++)
+		{
+		TPrinterModelEntry entry = (*iModelList)[i];
+		RDebug::Print(_L("[%d][%S][%d] "), i, &(entry.iModelName), entry.iRequiresPrinterPort);
+		LOG1("ModelName=[%S]", &(entry.iModelName));
+		}
+#endif
+	// read progress message
+	iProgressMessage = StringLoader::LoadL( R_DIRECTPRINT_MSG_PRINTING_PROGRESS );
+
+	LOG("CDirectPrintEngine::ConstructL END");
+	}
+
+void CDirectPrintEngine::SetObserver(MDirectPrintEngineObserver* aObserver)
+	{
+	iObserver = aObserver;
+	}
+
+/**
+  Override of base class virtual.
+  Notifies that a print or print preview operation is about to begin.
+ */
+void CDirectPrintEngine::NotifyPrintStarted(TPrintParameters /*aPrintParams*/)
+	{
+	iPageCounter = 0;
+	TRAPD(err, StartPrintProgressNoteL());
+	iLastError = err;
+	}
+
+/**
+  Override of base class virtual.\n
+  Notifies that a band is about to be printed used to display print progress information,
+  including the current page number.\n
+  It is called immediately before each band is printed.\n
+ */
+void CDirectPrintEngine::NotifyBandPrinted(TInt /*aPercent*/, TInt aCurrentPageNum, TInt /*aCurrentCopyNum*/)
+	{
+	if (iPageCounter==0)
+		{
+		// start print
+		}
+	if (iPageCounter<aCurrentPageNum)
+		{
+		// next page
+		iPageCounter = aCurrentPageNum;
+		TRAPD(err, UpdatePrintProgressNoteL(iPageCounter));
+		iLastError = err;
+		}
+	}
+
+/**
+  Override of base class virtual.\n
+  Notifies that the print or print preview operation has completed.\n
+  used to display information about how the operation completed,
+  for example any errors that occurred.\n
+ */
+void CDirectPrintEngine::NotifyPrintEnded(TInt aErr)
+	{
+	CActiveScheduler::Stop();
+	TInt err = KErrNone;
+
+	if (aErr == KErrNone)
+		{
+		if (iObserver)
+			{
+			TRAP(err, iObserver->HandlePrintEventL(MDirectPrintEngineObserver::EDirectPrintEngineEventFinishCreatePrintData, 0, KNullDesC));
+			}
+		}
+	else
+		{
+		switch (aErr)
+			{
+		case KErrCancel:
+			if (iObserver)
+				{
+				TRAP(err, iObserver->HandlePrintEventL(MDirectPrintEngineObserver::EDirectPrintEngineEventCancelCreatePrintData, aErr, KNullDesC));
+				}
+			break;
+		default:
+			if (iObserver)
+				{
+				TRAP(err, iObserver->HandlePrintEventL(MDirectPrintEngineObserver::EDirectPrintEngineEventErrorCreatePrintData, aErr, KNullDesC));
+				}
+			break;
+			}
+		}
+
+	TRAP(err, EndPrintProgressNoteL());
+	}
+
+/**
+  Override of base class virtual.\n
+  Returns the number of pages in the current document.\n
+  @return - TInt (Number of pages).\n
+ */
+TInt CDirectPrintEngine::UpdateFieldNumPages()const
+	{
+	return iMaxPageNum;
+	}
+
+
+void CDirectPrintEngine::PrintL()
+	{
+	
+	// set the total page
+	iMaxPageNum = 1;
+	iPrintSetup->Header()->SetNumPagesInfo(*this);
+
+	TInt modelNum = iModelList->UidToNum(ModelUid(iModelIndex));
+	iPrintSetup->CreatePrinterDeviceL(modelNum);
+
+	// create a port if necessary
+	CPrinterPort* port=NULL;
+	if ((*iModelList)[modelNum].iRequiresPrinterPort)
+		{
+#ifdef __WINSCW__
+		port = CFilePrinterPort::NewL(_L("c:\\fpr.pcl"));
+#else
+//		port = CFilePrinterPort::NewL(_L("e:\\fpr.pcl"));
+		port = CFilePrinterPort::NewL(_L("c:\\fpr.pcl"));
+#endif
+		}
+
+	iPrintSetup->PrinterDevice()->SelectPageSpecInTwips(KDefaultPageSpecInTwips);
+	iPrintSetup->iPageMarginsInTwips.iHeaderOffset = 720;
+	iPrintSetup->iPageMarginsInTwips.iFooterOffset = 0;
+	iPrintSetup->iPageMarginsInTwips.iMargins.iLeft = 1440; // 1 inch
+	iPrintSetup->iPageMarginsInTwips.iMargins.iRight = 1440;
+	iPrintSetup->iPageMarginsInTwips.iMargins.iTop = 1440;
+	iPrintSetup->iPageMarginsInTwips.iMargins.iBottom = 1440;
+
+	if (iObserver)
+		{
+		iObserver->HandlePrintEventL(MDirectPrintEngineObserver::EDirectPrintEngineEventStartCreatePrintData, 0, KNullDesC);
+		}
+	
+
+	TRAPD(err, DoPrintL(port));
+	if (err == KErrNone)
+		{
+		CActiveScheduler::Start(); // stopped by killing it - subtle...
+		}
+	else
+		{
+		if (iObserver)
+			{
+			iObserver->HandlePrintEventL(MDirectPrintEngineObserver::EDirectPrintEngineEventErrorCreatePrintData, err, KNullDesC);
+			}
+		}
+
+//	if (iPrintBand)
+//		{
+//		delete iPrintBand;
+//		iPrintBand = NULL;
+//		}
+	}
+
+void CDirectPrintEngine::DoPrintL(CPrinterPort* aPort)
+	{
+	// create a header
+	iPrintSetup->Header()->CreateTextL();
+	TBuf<40> buf(_L("This is the header on page  out of "));
+	buf.Append(CEditableText::EParagraphDelimiter);
+	iPrintSetup->Header()->Text()->InsertL(0,buf);
+	CTextField* pNumberfield=iPrintSetup->Header()->Text()->NewTextFieldL(KPageNumberFieldUid);
+	iPrintSetup->Header()->Text()->InsertFieldL(27,pNumberfield,KPageNumberFieldUid);  
+	CNumPagesField* numPagesField=(CNumPagesField*)iPrintSetup->Header()->Text()->NewTextFieldL(KNumPagesFieldUid);
+	iPrintSetup->Header()->Text()->InsertFieldL(35,numPagesField,KNumPagesFieldUid);  
+	iPrintSetup->Header()->Text()->UpdateFieldL(27);
+	iPrintSetup->Header()->Text()->UpdateFieldL(35);
+	iPrintSetup->Header()->SetFirstPageToPrintTo(1); // no header on first 3 pages
+
+	iPrintSetup->Footer()->CreateTextL();
+	TBuf<40> buf2(_L("This is the footer on page "));
+	buf2.Append(CEditableText::EParagraphDelimiter);
+	iPrintSetup->Footer()->Text()->InsertL(0,buf2);
+	CTextField* pNumberfield2=iPrintSetup->Footer()->Text()->NewTextFieldL(KPageNumberFieldUid);
+	iPrintSetup->Footer()->Text()->InsertFieldL(27,pNumberfield2,KPageNumberFieldUid);	
+	iPrintSetup->Footer()->Text()->UpdateFieldL(27);
+
+	// start print to file
+	iPrintSetup->iNumOfFirstPage = 1;
+	TPrintParameters params;
+	params.iFirstPage = 1; // don't print the first page at all, ie print page no's 3-6
+	params.iLastPage = 1;
+	params.iNumCopies = 1;
+	TPageSpec spec;
+	spec.iPortraitPageSize = KA4PaperSizeInTwips;
+	spec.iOrientation = TPageSpec::EPortrait;
+	iPrintSetup->PrinterDevice()->SelectPageSpecInTwips(spec);
+
+	//===========================
+	// start printing
+	//===========================
+	iPrintSetup->StartPrintL(params, *(PageRegionPrinter()), aPort, this);
+
+	}
+
+
+TInt CDirectPrintEngine::ModelCount()
+	{
+	return iModelList->ModelCount();
+	}
+
+void CDirectPrintEngine::ModelName(TInt aIndex, TDes& aDes)
+	{
+	TPtrC name((*iModelList)[aIndex].iModelName);
+	if (name.Length() <= aDes.MaxLength())
+		{
+		aDes.Copy(name);
+		}
+	}
+
+TUid CDirectPrintEngine::ModelUid(TInt aIndex)
+	{
+	return (*iModelList)[aIndex].iUid;
+	}
+
+void CDirectPrintEngine::SetUseModel(TInt aIndex)
+	{
+	iModelIndex = aIndex;
+	}
+
+void CDirectPrintEngine::StartPrintProgressNoteL()
+	{
+	// Delete possible previous CAknProgressDialog.
+	delete iProgressDialog;
+	iProgressDialog = NULL;
+
+	// Create new CAknProgressDialog.
+	iProgressDialog = new ( ELeave ) CAknProgressDialog( reinterpret_cast
+														 <CEikDialog**> 
+														 ( &iProgressDialog ) );
+	
+	iProgressDialog->SetCallback( this );
+	iProgressDialog->PrepareLC( R_DIRECTPRINT_PRINT_PROGRESS_NOTE );
+	iProgressInfo = iProgressDialog->GetProgressInfoL();
+	iProgressInfo->SetFinalValue( iMaxPageNum );
+
+	TBuf<32> msg;
+	msg.AppendFormat(*iProgressMessage, iPageCounter, iMaxPageNum);
+	iProgressDialog->SetTextL(msg);
+	iProgressDialog->RunLD();
+	}
+
+void CDirectPrintEngine::EndPrintProgressNoteL()
+	{
+	if (iProgressDialog)
+		{
+		iProgressDialog->ProcessFinishedL();
+		delete iProgressDialog;
+		iProgressDialog = NULL;
+		}
+	}
+
+void CDirectPrintEngine::UpdatePrintProgressNoteL(TInt aPage)
+	{
+	if (iProgressInfo)
+		{
+		TBuf<32> msg;
+		msg.AppendFormat(*iProgressMessage, aPage, iMaxPageNum);
+		iProgressDialog->SetTextL(msg);
+		iProgressInfo->SetAndDraw(aPage);
+		}
+	}
+
+void CDirectPrintEngine::DialogDismissedL( TInt /*aButtonId*/ )
+	{
+	if (iPrintSetup)
+		{
+		iPrintSetup->EndPrint();
+		}
+	}
+
+void CDirectPrintEngine::StartPrintPreviewL()
+	{
+	// Clear previous object
+	EndPrintPreview();
+
+	// set the total page
+	iMaxPageNum = 1;
+	iPrintSetup->Header()->SetNumPagesInfo(*this);
+
+	TInt modelNum = iModelList->UidToNum(ModelUid(iModelIndex));
+	iPrintSetup->CreatePrinterDeviceL(modelNum);
+
+	// create a port if necessary
+	//CPrinterPort* port=NULL;
+	//if ((*iModelList)[modelNum].iRequiresPrinterPort)
+	//	{
+	//	port = CFilePrinterPort::NewL(_L("e:\\fpr.pcl"));
+	//	}
+
+	iPrintSetup->PrinterDevice()->SelectPageSpecInTwips(KDefaultPageSpecInTwips);
+	iPrintSetup->iPageMarginsInTwips.iHeaderOffset = 720;
+	iPrintSetup->iPageMarginsInTwips.iFooterOffset = 0;
+	iPrintSetup->iPageMarginsInTwips.iMargins.iLeft = 1440; // 1 inch
+	iPrintSetup->iPageMarginsInTwips.iMargins.iRight = 1440;
+	iPrintSetup->iPageMarginsInTwips.iMargins.iTop = 1440;
+	iPrintSetup->iPageMarginsInTwips.iMargins.iBottom = 1440;
+	}
+
+void CDirectPrintEngine::EndPrintPreview()
+	{
+	}
+
+void CDirectPrintEngine::SetParamL(RXmlEngDocument* aParam)
+	{
+	LOG("CDirectPrintEngine::SetParamL BEGIN");
+
+	iParam = aParam;
+	if ( iPrintBand )
+		{
+		delete iPrintBand;
+		iPrintBand = NULL;
+		}
+
+	_LIT8(KElementRecogMode, "RecognizeMode");
+	_LIT8(KElementRecogModeAttr, "mode");
+	_LIT8(KElementRecogModeValueFile, "PrintRecognizeModeFile");
+	_LIT8(KElementRecogModeValuePlugin, "PrintRecognizeModePlugin");
+	_LIT8(KElementFile, "PrintFile");
+	_LIT8(KElementFileAttr, "file");
+	_LIT8(KElementPluginUid, "PluginUid");
+	_LIT8(KElementPluginUidAttr, "uid");
+
+	TXmlEngElement element = iParam->DocumentElement().FirstChild().AsElement();
+	HBufC* filename = NULL;
+	TUint uidValue = 0;
+
+	enum {
+		EParamModeFile	 = 0x0001,
+		EParamModePlugin = 0x0002,
+		EParamFileExist   = 0x0008,
+		EParamPluginExist = 0x0010
+	};
+	TUint paramFlag = 0;
+
+	while (element.NotNull())
+		{
+		if (element.Name().CompareF(KElementRecogMode()) == 0)
+			{
+			TXmlEngAttr attr = element.AttributeNodeL(KElementRecogModeAttr,KNullDesC8);
+			if(attr.Value().CompareF(KElementRecogModeValueFile) == 0)
+				{
+				paramFlag |= EParamModeFile;
+				LOG("Param:Mode=File");
+				}
+			else if(attr.Value().CompareF(KElementRecogModeValuePlugin) == 0)
+				{
+				paramFlag |= EParamModePlugin;
+				LOG("Param:Mode=Plugin");
+				}
+			else
+				{
+				LOG("[Error] Param:Mode=Not set");
+				break;
+				}
+			}
+		else if (element.Name().CompareF(KElementFile()) == 0)
+			{
+			TXmlEngAttr attr = element.AttributeNodeL(KElementFileAttr,KNullDesC8);
+			filename = HBufC::NewLC(attr.Value().Length());
+			TPtr ptr(filename->Des());
+			ptr.Copy(attr.Value());
+			if (ptr.Length() > 0)
+				{
+				LOG1("Param:FileName UID=[%S]", &ptr);
+				if (BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), ptr))
+					{
+					paramFlag |= EParamFileExist;
+					}
+				}
+			if (!(paramFlag & EParamFileExist))
+				{
+				LOG("[Error] File not exist");
+				}
+			}
+		else if (element.Name().CompareF(KElementPluginUid()) == 0)
+			{
+			TXmlEngAttr attr = element.AttributeNodeL(KElementPluginUidAttr,KNullDesC8);
+			//HBufC8* bufUid = HBufC8::NewLC(attr.Value().Length());
+			//TPtr8 ptr(bufUid->Des());
+			HBufC* bufUid = HBufC::NewLC(attr.Value().Length());
+			TPtr ptr(bufUid->Des());
+			ptr.Copy(attr.Value());
+			//_LIT8(KHeadOfHexString, "0x");
+			_LIT(KHeadOfHexString, "0x");
+			const TInt KUidStingLength = 8;
+			if (ptr.Left(KHeadOfHexString().Length()).CompareF(KHeadOfHexString()) == 0)
+				{
+				ptr.Delete(0, KHeadOfHexString().Length());
+				}
+			if (ptr.Length() == KUidStingLength)
+				{
+				//TBuf<8> bufUid;
+				//bufUid.Copy(ptr);
+				//TLex lex(bufUid);
+				TLex lex(ptr);
+				if (lex.Val(uidValue,EHex) == KErrNone)
+					{
+					LOG1("Param:Plugin UID=[0x%X]", uidValue);
+					paramFlag |= EParamPluginExist;
+					}
+				else
+					{
+					LOG("[Error] Convert from HEX string to int");
+					}
+				}
+			if (!(paramFlag & EParamPluginExist))
+				{
+				LOG("[Error] File not exist");
+		  		}
+			CleanupStack::PopAndDestroy(bufUid); //bufUid
+			}
+
+		if (paramFlag == (EParamFileExist|EParamModeFile)
+		 || paramFlag == (EParamPluginExist|EParamModePlugin))
+			{
+			break;
+			}
+		element = element.NextSibling().AsElement();
+		}
+
+	if (paramFlag == (EParamFileExist|EParamModeFile)
+	 && filename)
+		{
+		TPtrC ptr(filename->Des());
+		SearchPluginFromFilenameL(ptr);
+		}
+	if (paramFlag == (EParamPluginExist|EParamModePlugin)
+	 && uidValue)
+		{
+		TUid uid = TUid::Uid(uidValue);
+		LoadPluginFromUidL(uid);
+		}
+
+	if (filename)
+		{
+		CleanupStack::PopAndDestroy(filename); //filename
+		}
+
+	if ( !iPrintBand )
+		{
+		// error xml parameter
+		User::Leave(KErrArgument);
+		}
+
+	LOG("CDirectPrintEngine::SetParamL END");
+	}
+
+void CDirectPrintEngine::SearchPluginFromFilenameL(const TDesC& aFileName)
+	{
+	LOG("CDirectPrintEngine::SearchPluginFromFilenameL START");
+	RImplInfoPtrArray infoArray;
+	TUid interface = TUid::Uid(KDirectPrintBandInterfaceUid);
+	REComSession::ListImplementationsL( interface, infoArray );
+	CleanupClosePushL( infoArray );
+	LOG1("CDirectPrintEngine::SearchPluginFromFilenameL infoArray.Count(): %d", infoArray.Count());
+
+	TParsePtrC parse(aFileName);
+
+	TPtrC8 dataType;
+	TPtrC16 dispName;
+	TPtrC8 opaqueData;
+	HBufC* dataTypeBuf = NULL;
+	TBool bFound = EFalse;
+	TInt findLen;
+	const TChar KDataTypeSeparator = '|';
+
+	for( TInt i = 0; i < infoArray.Count(); i++ )
+		{
+		LOG1("[InfoArray] i=%d", i);
+		CImplementationInformation* info = infoArray[i];
+		dataType.Set( info->DataType() );
+		dispName.Set( info->DisplayName() );
+		opaqueData.Set( info->OpaqueData() );
+
+		dataTypeBuf = HBufC::NewLC( dataType.Length() );
+		TPtr dataTypePtr(dataTypeBuf->Des());
+		dataTypePtr.Copy( dataType );
+
+		LOG1("[DataType]=[%S]", &dataTypePtr);
+		FOREVER
+			{
+			findLen = dataTypePtr.Locate( KDataTypeSeparator );
+			if (findLen < 0)
+				{
+				// the separator is not found
+				if (dataTypePtr.Length() > 0)
+					{
+					findLen = dataTypePtr.Length();
+					}
+				else
+					{
+					break;
+					}
+				}
+//			LOG1("[Compare]=[%S]", &(dataTypePtr.Left( findLen )));
+//			LOG1("[Ext]=[%S]", &(parse.Ext()));
+//			LOG1("[Comp]=[%S]", &(dataTypePtr.Left( findLen )));
+			if ( parse.Ext().CompareF( dataTypePtr.Left( findLen ) ) == 0 )
+				{
+				bFound = ETrue;
+				break;
+				}
+			dataTypePtr.Delete( 0, findLen+1 );
+			}
+
+		CleanupStack::PopAndDestroy(dataTypeBuf); // dataTypeBuf
+		
+		if ( bFound )
+			{
+			LOG("Match!!!");
+			LoadPluginFromUidL(info->ImplementationUid());
+			break;
+			}
+		}
+
+	infoArray.ResetAndDestroy();
+	CleanupStack::PopAndDestroy(&infoArray); // infoArray
+
+	LOG("CDirectPrintEngine::SearchPluginFromFilenameL End");
+	}
+
+void CDirectPrintEngine::LoadPluginFromUidL(const TUid aUid)
+	{
+	LOG1("CDirectPrintEngine::LoadPluginFromUidL(0x%X) Start", aUid.iUid);
+
+	CDirectPrintBand* band = NULL;
+	band = CDirectPrintBand::NewL(aUid);
+	TCleanupItem clItem( CleanupBand, band );
+	CleanupStack::PushL( clItem );
+	band->InitPrintBandL( iPrintSetup,
+						  iParam,
+						  KNullDesC );
+	CleanupStack::Pop(); // band
+	iPrintBand = band;
+
+	LOG("CDirectPrintEngine::LoadPluginFromUidL End");
+	}
+
+void CDirectPrintEngine::CleanupBand( TAny* aData )
+	{
+	LOG("[CDirectPrintEngine::CleanupBand]\t Begin");
+
+	CDirectPrintBand* band = (CDirectPrintBand*)aData;
+	delete band;
+
+	LOG("[CDirectPrintEngine::CleanupBand]\t End");
+	}
+
+
+
+// End of file