browserutilities/recenturlstore/RecentUrlSrc/RecentUrlStore.cpp
changeset 0 dd21522fd290
child 16 a359256acfc6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/recenturlstore/RecentUrlSrc/RecentUrlStore.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,358 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* 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:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*      Implementation of RecentUrlStore
+*
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "RecentUrlStore.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+_LIT(KRecentUrlDBFile, "c:\\private\\%08x\\RecentUrlStore.db");
+
+_LIT(KSQLInsertVersion, "INSERT INTO dbversion (dbver) VALUES ('1.0')");
+
+/*
+*    Database columns:
+*       History - counter used to order the urls latest first
+*       Url - url of visited page
+*/
+_LIT(KVersionTableSQL, "CREATE TABLE dbversion(dbver CHAR(10))");
+_LIT(KRecentUrlTableSQL, "CREATE TABLE recenturl(history COUNTER, domain VARCHAR(50), url VARCHAR(250), title VARCHAR(250))");
+const TUint KDomainSize = 50;
+const TUint KUrlSize = 250;
+const TUint KTitleSize = 250;
+
+_LIT(KIndex1SQL, "CREATE INDEX updateidx ON recenturl (history)");
+
+_LIT(KSQLInsert, "INSERT INTO recenturl (domain,url,title) VALUES ('%S','%S', '%S')");
+_LIT(KSQLDelete, "DELETE FROM recenturl WHERE url = '%S'");
+_LIT(KSQLSelect, "SELECT url,title FROM recenturl WHERE domain LIKE '%S*' OR url LIKE '*://%S*' ORDER BY history desc");
+_LIT(KSQLSelectAll, "SELECT url,title FROM recenturl ORDER BY history desc");
+const TUint KUrlCol = 1;
+const TUint KTitleCol = 2;
+
+const TUint KMaxRows = 100;
+
+_LIT(KDomainDelim, "."); // domain starts after first '.' and ends after second '.'
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================= FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRecentUrlStore::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+EXPORT_C CRecentUrlStore * CRecentUrlStore::NewL ()
+    {
+    CRecentUrlStore* self = new (ELeave) CRecentUrlStore();
+    self->ConstructL();
+    return self;
+
+    }
+
+// -----------------------------------------------------------------------------
+// CRecentUrlStore::CRecentUrlStore
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+CRecentUrlStore::CRecentUrlStore():
+	iFirstTimeOpened(ETrue)
+	{
+
+	}
+
+// -----------------------------------------------------------------------------
+// CRecentUrlStore::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+void CRecentUrlStore::ConstructL()
+    {
+    
+    // Create the file name from UID
+	RProcess myProcess;	
+	TBuf <256>buf;    
+    buf.Format(KRecentUrlDBFile, myProcess.Identity());
+	iRecentUrlDBFile = buf.AllocL();
+
+	User::LeaveIfError(iDbSession.Connect());
+	
+    }
+    
+//-----------------------------------------------------------------------------
+// CRecentUrlStore Destructor
+//-----------------------------------------------------------------------------
+CRecentUrlStore::~CRecentUrlStore()
+    {
+	iDbSession.Close();
+	delete iRecentUrlDBFile;
+    }
+
+    
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::GetData
+// params aUrl - Url filter
+// Returns matching urls.
+//-----------------------------------------------------------------------------
+EXPORT_C TInt CRecentUrlStore::GetData (CDesCArray& aUrls, CDesCArray& aTitles, const TDesC& aUrl)
+    {
+    RDbNamedDatabase dataBase;
+    TInt err = OpenDatabase(dataBase);
+    if (err == KErrNone)
+    	{
+    	TRAP(err, GetDataL(dataBase, aUrls, aTitles, aUrl));
+    	dataBase.Close();
+    	}
+    return err;
+    }
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::GetData
+// params aUrl - Url filter
+// Returns matching urls.
+//-----------------------------------------------------------------------------
+void CRecentUrlStore::GetDataL (RDbNamedDatabase& aDataBase, 
+			CDesCArray& aUrls, CDesCArray& aTitles, const TDesC& aUrl)
+    {
+	
+    TInt rowCount(0);
+
+	// select values from the database filtered by url
+	if (aUrl.Length())
+		{
+		HBufC* domain = aUrl.AllocLC();
+		domain->Des().LowerCase();
+		iSQLStatement.Format(KSQLSelect, domain, domain);
+		CleanupStack::PopAndDestroy();
+		}
+	else
+		{
+		iSQLStatement.Format(KSQLSelectAll);
+		}
+	
+
+    RDbView view;
+    
+    TInt err = view.Prepare(aDataBase, TDbQuery(iSQLStatement));
+    if (err == KErrNone)
+    	{
+    	err = view.EvaluateAll();
+    	if (err == KErrNone)
+    		{
+    		view.FirstL();
+    		// loop through rows and build the list
+    		while (view.AtRow() && rowCount++ < KMaxRows)
+    			{
+    			view.GetL();
+				aUrls.AppendL(view.ColDes(KUrlCol));
+				aTitles.AppendL(view.ColDes(KTitleCol));
+    			view.NextL();
+    			}
+    		/*
+    		* This loop will keep the number of rows in the database at a reasonable size by
+    		* deleting old rows (deletes rows beyond KMaxRows).  Should be at most 1 row deleted.
+    		* Its more efficiant to delete it here than in the SaveData because in this function
+    		* we already have the list and know its size
+    		*/
+    		while (view.AtRow())
+    			{
+    			view.GetL();
+    			iSQLStatement.Format(KSQLDelete, &aUrl);
+				aDataBase.Execute(iSQLStatement);
+    			view.NextL();
+    			}
+       		}
+    	}
+    view.Close();
+    }
+
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::DeleteData
+// Deletes a single row from the database.
+//-----------------------------------------------------------------------------
+EXPORT_C void CRecentUrlStore::DeleteData (const TDesC& aUrl)
+    {
+    RDbNamedDatabase dataBase;
+    if (OpenDatabase(dataBase) == KErrNone)
+    	{
+		iSQLStatement.Format(KSQLDelete, &aUrl);
+		dataBase.Execute(iSQLStatement);
+    	dataBase.Close();
+    	}
+    }
+
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::SaveDataL
+// Save the url in store.
+//-----------------------------------------------------------------------------
+EXPORT_C void CRecentUrlStore::SaveData (const TDesC& aUrl, const TDesC& aTitle)
+	{
+	RDbNamedDatabase dataBase;
+	TInt urlLength (aUrl.Length());
+	
+	// shouldn't happen but if it's too long for the data store just skip it!
+	if (urlLength > KUrlSize)
+		{
+		return;
+		}
+	
+	if (OpenDatabase(dataBase) == KErrNone)
+		{
+		// find the point where the domain starts and ends
+		TInt domainLength(urlLength);
+		TInt domainStart(0);
+		
+		TInt startPos = aUrl.Find(KDomainDelim);
+		if (startPos != KErrNotFound)
+			{
+			domainStart = startPos + (KDomainDelim().Length()); // first char after delim
+			TInt len = aUrl.Right(urlLength - domainStart).Find(KDomainDelim);
+			if (len > 0) // ignore delim following delim.  we don't want an empty string
+				{
+				domainLength = len;
+				}
+			else
+				{
+				domainLength -= domainStart;
+				}
+			}
+			
+		// make sure it's not too big for the data store
+		domainLength = (domainLength > KDomainSize) ? KDomainSize : domainLength;
+		TInt titleLength = (aTitle.Length() > KTitleSize) ? KTitleSize : aTitle.Length();
+			
+		HBufC* domain = aUrl.Mid(domainStart,domainLength).AllocLC();
+		domain->Des().LowerCase();
+		HBufC* title = aTitle.Left(titleLength).AllocLC();
+
+		// delete and re-insert
+		iSQLStatement.Format(KSQLDelete, &aUrl);
+		dataBase.Execute(iSQLStatement);
+		iSQLStatement.Format(KSQLInsert, domain, &aUrl, title);
+		CleanupStack::PopAndDestroy(2); // domain, title
+		
+		dataBase.Execute(iSQLStatement);
+		dataBase.Close();
+		}
+	}
+	
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::ClearData
+// Clear the store.
+//-----------------------------------------------------------------------------
+EXPORT_C void CRecentUrlStore::ClearData ()
+	{
+	// the quickest way to clear the data is to re-create it
+	TRAP_IGNORE(CreateDatabaseL());
+	}
+
+
+// private
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::DeleteOldRowsL
+//-----------------------------------------------------------------------------
+void CRecentUrlStore::DeleteOldRowsL (RDbNamedDatabase& aDataBase)
+    {
+	
+    TInt rowCount(0);
+
+	iSQLStatement.Format(KSQLSelectAll);
+	
+    RDbView view;
+    
+    TInt err = view.Prepare(aDataBase, TDbQuery(iSQLStatement));
+    if (err == KErrNone)
+    	{
+    	err = view.EvaluateAll();
+    	if (err == KErrNone)
+    		{
+    		view.FirstL();
+    		// loop through rows we want to keep
+    		while (view.AtRow() && rowCount++ < KMaxRows)
+    			{
+    			view.NextL();
+    			}
+    		// delete the rows that are old
+    		while (view.AtRow())
+    			{
+    			view.DeleteL();
+    			view.NextL();
+    			}
+       		}
+    	}
+    view.Close();
+    }
+
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::OpenDatabase
+// Open the data store.
+//-----------------------------------------------------------------------------
+TInt CRecentUrlStore::OpenDatabase(RDbNamedDatabase& aDataBase)
+	{
+	TInt error = KErrNone;
+	// open the database - create if it doesn't exist
+	error = aDataBase.Open(iDbSession, *iRecentUrlDBFile);
+	// compact it once during our session
+	if (error == KErrNone && iFirstTimeOpened)
+		{
+		TRAP_IGNORE(DeleteOldRowsL(aDataBase));
+		aDataBase.Compact();
+		iFirstTimeOpened = EFalse;
+		}
+		
+	if (error != KErrNone)
+		{
+		TRAP(error,CreateDatabaseL());
+		if (error == KErrNone)
+			{
+			error = aDataBase.Open(iDbSession, *iRecentUrlDBFile);
+			}
+		}
+	return error;
+	}
+
+//-----------------------------------------------------------------------------
+// CRecentUrlStore::CreateDatabaseL
+// Create the data store.
+//-----------------------------------------------------------------------------
+void CRecentUrlStore::CreateDatabaseL()
+	{
+	RDbNamedDatabase dataBase;
+	User::LeaveIfError(dataBase.Replace(iDbSession, *iRecentUrlDBFile));
+	    	
+	CleanupClosePushL(dataBase);
+	User::LeaveIfError(dataBase.Execute(KVersionTableSQL));
+	User::LeaveIfError(dataBase.Execute(KRecentUrlTableSQL));
+	User::LeaveIfError(dataBase.Execute(KIndex1SQL));
+	User::LeaveIfError(dataBase.Execute(KSQLInsertVersion));
+	CleanupStack::PopAndDestroy();//dataBase	    
+    
+	}
+	
+//  End of File