⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbview.cpp

📁 手机文件浏览器 Here are the sources to SMan v1.2c 1.2 is a major jump from v1.1. You will see this from the
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{
	// No point showing InfoMsgs here because the call to ShowRecordList() will take care of that

	// Note: the call to RDbStoreDatabase::OpenL and CreateL destroys "decryptor" / "encryptor"

	// Security is handled slightly different here. The encryption / decryption key is set by
	// the security data of the security classes i.e. CSecurityBase::SecurityData() - NOT THE PASSWORD
	// Since we do not know the password beforehand, the routines here set the security data to be
	// the password itself. The APIs for CreateL and OpenL will fail accordingly if your encryption / decryption
	// key is wrong. Everything works nicely except for the standard password dialogs. We cannot use that
	// because these dialogs assume you know the password beforehand. It's a simple matter of creating
	// our own dialog.
	
	if (securityBase)
		delete securityBase;
	securityBase = Security::NewL();
	securityBase->SetL(TPtrC(), dbPassword);

	if (dbIsOpened)
		DeInitDB();
	
	if (!dbIsOpened)
	{
		TBuf8<KMaxPassword> tempPassword;

		if (fileStore)
		{
			delete fileStore;
			fileStore = NULL;
		}
		if (!ConeUtils::FileExists(dbFileName))
		{
			TRAPD(err, fileStore = CPermanentFileStore::CreateL(CEikonEnv::Static()->FsSession(), dbFileName, EFileRead | EFileWrite));
			if (!err)
			{
				TStreamId streamId;

				tempPassword.Copy(DEFAULT_PASSWORD);
				fileStore->SetTypeL(fileStore->Layout());
				encryptor = securityBase->NewEncryptL(tempPassword);
				streamId = dbStore.CreateL(fileStore, encryptor);
				fileStore->SetRootL(streamId);
				fileStore->CommitL();
				doCreateTable();
				// The choice of index is, unfortunately, a little arbitrary at this point.
				doCreateIndex();
				dbIsOpened = ETrue;
			}
			else
				iEikonEnv->InfoMsg(R_TBUF_DB_ERR_CREATE);
		}
		else
		{
			TRAPD(err, fileStore = CFileStore::OpenL(CEikonEnv::Static()->FsSession(), dbFileName, EFileRead | EFileWrite));
			if (!err)
			{
				TBool retVal = EFalse;
		
				tempPassword.Copy(dbPassword);
				decryptor = securityBase->NewDecryptL(tempPassword);
				TRAPD(err2, dbStore.OpenL(fileStore, fileStore->Root(), decryptor));
				if (err2)
				{
					if (err2 == KErrGeneral)
					{
						TPassword thePassword;
						CGetPasswordDialog *passwordDialog;
						
						passwordDialog = new (ELeave) CGetPasswordDialog(&thePassword);
						if (passwordDialog->ExecuteLD(R_DIALOG_DB_GETPASSWORD) != EEikBidOk)
							thePassword.Copy(dbPassword);
							
						securityBase->SetL(dbPassword, thePassword);
						tempPassword.Copy(thePassword);
						decryptor = securityBase->NewDecryptL(tempPassword);
						TRAP(err2, dbStore.OpenL(fileStore, fileStore->Root(), decryptor));
						if (!err2)
						{
							dbPassword.Copy(thePassword);
							dbIsOpened = ETrue;
							retVal = ETrue;
						}
					}
					if (!retVal)
						iEikonEnv->InfoMsg(R_TBUF_DB_ERR_READ);
				}
				else
					dbIsOpened = ETrue;
			}
			else
				iEikonEnv->InfoMsg(R_TBUF_DB_ERR_READ);
		}
	}
	
	if (!dbIsOpened)
	{
		if (fileStore)
		{
			delete fileStore;
			fileStore = NULL;
		}
		doCloseDB(ETrue);
	}	
	delete securityBase;
	securityBase = NULL;
}

void CSMan2DBView::doReadDB()
{
	if (dbIsOpened)
		DeInitDB();
	ShowRecordsList(ETrue, ETrue);
}

void CSMan2DBView::doCloseDB(TBool aDrawToolbar)
{
	if (dbIsOpened)
		DeInitDB();
	HideAllControls();
	currentDBView = DBView_List;
	currentRecordIndexIsValid = EFalse;
	if (aDrawToolbar)
		static_cast<CSMan2AppUi*>(CEikonEnv::Static()->EikAppUi())->SetToolbarL(R_TOOLBAR_DB_LIST);
	((CDesCArray*)cIndexListBox->Model()->ItemTextArray())->Reset();
	cIndexListBox->HandleItemRemovalL();
}

void CSMan2DBView::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
	if (currentDBView == DBView_List)
	{
		TBool consumed = EFalse;
		TInt theItem;
		TBool pointValid = cIndexListBox->View()->XYPosToItemIndex(aPointerEvent.iPosition, theItem);
		
		if (aPointerEvent.iType == TPointerEvent::EDrag)
		{
			if (aPointerEvent.iPosition.iX < (cIndexListBox->View()->ItemDrawer()->MarkColumn()))
			{
				if ((pointValid) && (oldItem != theItem))
				{
					consumed = ETrue;
					cIndexListBox->View()->VerticalMoveToItemL(theItem, CListBoxView::EDisjointSelection);
					cIndexListBox->UpdateScrollBarsL();
					oldItem = theItem;
				}
			}
		}
		else if (aPointerEvent.iType == TPointerEvent::EButton1Down)
		{
			if (pointValid)
			{
				oldItem = theItem;
				consumed = ETrue;
				if (aPointerEvent.iPosition.iX > cIndexListBox->View()->ItemDrawer()->MarkColumn())
				{
					cIndexListBox->View()->VerticalMoveToItemL(theItem, CListBoxView::ENoSelection);
					doDisplayOneRecord(ETrue);
				}
				else
					cIndexListBox->View()->VerticalMoveToItemL(theItem, CListBoxView::EDisjointSelection);
				cIndexListBox->UpdateScrollBarsL();
			}
		}
		if (!consumed)
			CCoeControl::HandlePointerEventL(aPointerEvent);
	}
	else
		CViewBase::HandlePointerEventL(aPointerEvent);
}

TBool CSMan2DBView::ReadDB(TPtrC sqlStatement)
{
	TInt retVal = EFalse;
	
	if (!dbIsOpened)
		InitDB();
	
	if (dbIsOpened)
	{
		// Symbian has a very VERY useful feature in its DBMS engine called pre-evaluation. :) :) :) :) 
		// Solves the classical problem of memory vs performance issue when navigating a db
		// This technology is similar to cursors in other databases. In our case, we don't need to use it
		// but i've included this functionality for future versions of SMan. I have a strong feeling, v1.3++ will
		// be using this.
		dbView.Close();
		if (dbWindow)
		{
			delete dbWindow;
			dbWindow = NULL;
		}
		dbWindow = new (ELeave) TDbWindow(WINDOW_FORE_ROWSETS, WINDOW_REAR_ROWSETS);

		// By default, this constructor gives EUpdatable access.
		if (dbView.Prepare(dbStore, TDbQuery(sqlStatement.Left(sqlStatement.Length()), EDbCompareNormal), *dbWindow) == KErrNone)
		{
			if (dbView.EvaluateAll() == KErrNone)
				retVal = ETrue;
		}
		else
			iEikonEnv->InfoMsg(R_TBUF_DB_ERR_READ);
	}
	else
		iEikonEnv->InfoMsg(R_TBUF_DB_ERR_READ);	
	return retVal;
}

void CSMan2DBView::HideRecordsList()
{
	cIndexListBox->MakeVisible(EFalse);
	cIndexListBox->SetFocus(EFalse);
}

void CSMan2DBView::HideRecordsSingleReadOnly()
{
	readOnlyDisplay->MakeVisible(EFalse);
	// If i don't set size to shrink it, making the control invisible still exhibits the following problems:
	// 1) The scrollbar is still visible!!! Very persistent bugger
	// 2) When setting zoom (applying paragraph and character format), the control momentarily does a
	//     redraw and is visible
	// So i cheat by making the control really really small.
	readOnlyDisplay->SetSize(TSize(1, 1));
	readOnlyDisplay->SetFocus(EFalse);
}

void CSMan2DBView::HideRecordsSingle()
{
	for (int i = 0; i < NUM_DATA_FIELDS; i++)
	{
		fieldLabels[i]->SetFocus(EFalse);
		fieldValues[i]->SetFocus(EFalse);
	}
	
	// Note: I found that if i don't do the following block of code, the FEP will go crazy when I switch
	// the view back to single records i.e. make the scrollable container visible. When it switches back,
	// you won't see any flashing cursor ANYWHERE but the FEP's black triangle is visible indicating some
	// control is awaiting FEP input. The moment you scribble anywhere, an ETEXT 12 panic occurs. Weird.
	TBuf<1> empty;
	empty.Copy(_L(""));
	fieldDisplayName->SetTextL(&empty);
	
	fieldDisplayName->SetFocus(EFalse);
	scrollableContainer->MakeVisible(EFalse);
	scrollableContainer->SetFocus(EFalse);
}

TBool CSMan2DBView::ReadRecordsList()
{
	TBool retVal = EFalse;
	
	CDesCArray *iArray = ((CDesCArray *) cIndexListBox->Model()->ItemTextArray());
	iArray->Reset();
	cIndexListBox->HandleItemRemovalL();
	
	if (!dbIsOpened)
		InitDB();
	
	if (dbIsOpened)
	{
		TBuf<70> sqlString;
		sqlString.Copy(_L("SELECT Index, DisplayName FROM Databank ORDER BY DisplayName"));
		if (!configData->dbSortAscending)
			sqlString.Append(_L(" DESC"));
			
		if (ReadDB(sqlString))
		{
			TBuf<100> rowBuffer;
			TBuf<50> displayNameBuffer;
			TInt indexBuffer;
			
			for (dbView.FirstL(); dbView.AtRow(); dbView.NextL())
			{
				dbView.GetL();
				displayNameBuffer.Copy(dbView.ColDes(2));
				indexBuffer = dbView.ColUint32(1);
				rowBuffer.Copy(displayNameBuffer);
				rowBuffer.Append(KColumnListSeparator);
				displayNameBuffer.Format(_L("%u"), indexBuffer);
				rowBuffer.Append(displayNameBuffer);
				iArray->AppendL(rowBuffer);
			}
			retVal = ETrue;
			cIndexListBox->HandleItemAdditionL();
		}
		// Free up resources as the listbox now owns the data
		dbView.Close();
	}
	else
		iEikonEnv->InfoMsg(R_TBUF_DB_ERR_READ);
	return retVal;
}

void CSMan2DBView::ShowRecordsList(TBool aRefresh, TBool showToolbar)
{
	TBool readOk = EFalse;
	
	currentRecordIndex = 0;
	currentRecordIndexIsValid = EFalse;
	HideRecordsSingle();
	HideRecordsSingleReadOnly();
	if (aRefresh)
		readOk = ReadRecordsList();
	else
		readOk = ETrue;
		
	if (showToolbar)
		static_cast<CSMan2AppUi*>(CEikonEnv::Static()->EikAppUi())->SetToolbarL(R_TOOLBAR_DB_LIST);
		
	if (readOk)
	{
		cIndexListBox->MakeVisible(ETrue);
		cIndexListBox->SetFocus(ETrue, ENoDrawNow);
		cIndexListBox->DrawDeferred();
	}
	currentRecordIndexIsValid = EFalse;
	currentDBOp = DBOp_Browsing;
	currentDBView = DBView_List;
}

void CSMan2DBView::ShowRecordsSingleReadOnly(TUint32 aIndex)
{
	HideRecordsSingle();
	HideRecordsList();
		
	if (!dbIsOpened)
		InitDB();

	if (dbIsOpened)
	{
		TBuf<255> sqlString;
		TBool readOK = EFalse;
		
		sqlString.Format(_L("SELECT DisplayName, NameField1, ContentField1, NameField2, ContentField2, NameField3, ContentField3, NameField4, ContentField4, NameField5, ContentField5 FROM Databank WHERE Index = %u"), aIndex);
		if (ReadDB(sqlString))
		{
			if (dbView.CountL() == 1)
			{
				dbView.FirstL();
				if (dbView.AtRow())
				{
					TBuf<1> lineBreak;
					lineBreak.Copy(_L(""));
					readOnlyDisplay->SetTextL(&lineBreak);
					lineBreak.Append(CEditableText::ELineBreak);

					dbView.GetL();
					readOnlyDisplay->InsertDeleteCharsL(0, dbView.ColDes(1), TCursorSelection(0, 0));
					readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), lineBreak, TCursorSelection(0, 0));
					readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), lineBreak, TCursorSelection(0, 0));
					for (int i = 0; i < NUM_DATA_FIELDS; i++)
					{
						// Because doWriteDB removes all the empty fields and shift the data upwards, 
						// we will never end up with a gap in the middle. Therefore, the moment
						// we see a gap we can assume we have reached the end of the record
						if (dbView.ColDes(2 + i * 2).Length() == 0)
							break;

						readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), dbView.ColDes(2 + i * 2), TCursorSelection(0, 0));
						sqlString.Copy(_L(":"));
						readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), sqlString, TCursorSelection(0, 0));						
						readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), lineBreak, TCursorSelection(0, 0));
						readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), dbView.ColDes(3 + i * 2), TCursorSelection(0, 0));
						readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), lineBreak, TCursorSelection(0, 0));
						readOnlyDisplay->InsertDeleteCharsL(readOnlyDisplay->TextLength(), lineBreak, TCursorSelection(0, 0));
					}
					readOnlyDisplay->SetSize(TSize(Size().iWidth, Size().iHeight - 10));
					readOnlyDisplay->MakeVisible(ETrue);
					readOnlyDisplay->SetFocus(ETrue);
					readOnlyDisplay->SetCursorPosL(0, EFalse);
					readOnlyDisplay->UpdateScrollBarsL();
					readOnlyDisplay->DrawNow();
					currentRecordIndex = aIndex;
					currentRecordIndexIsValid = ETrue;
					currentDBOp = DBOp_Viewing;
					readOK = ETrue;

					static_cast<CSMan2AppUi*>(CEikonEnv::Static()->EikAppUi())->SetToolbarL(R_TOOLBAR_DB_SINGLE);
					currentDBView = DBView_Single_ReadOnly;
				}
			}
		}
		if (!readOK)
		{
			iEikonEnv->InfoMsg(R_TBUF_DB_RECORDMISSING);
			ShowRecordsList(ETrue, ETrue);
			return;
		}
	}
}

void CSMan2DBView::ShowRecordsSingle(TUint32 aIndex, TBool aIsNewRecord)
{
	TInt i;
	
	HideRecordsList();
	HideRecordsSingleReadOnly();
	currentRecordIndexIsValid = EFalse;
	
	if (!dbIsOpened)
		InitDB();

	TBuf<1> empty;
	empty.Copy(_L(""));
	for (i = 0; i < NUM_DATA_FIELDS; i++)
	{
		fieldLabels[i]->SetTextL(&empty);
		fieldLabels[i]->SetFocus(EFalse);
		fieldValues[i]->SetTextL(&empty);
		fieldValues[i]->SetFocus(EFalse);
	}
	fieldDisplayName->SetTextL(&empty);
		
	if (aIsNewRecord)
	{
		static_cast<CSMan2AppUi*>(CEikonEnv::Static()->EikAppUi())->SetToolbarL(R_TOOLBAR_DB_SINGLE);
		currentDBOp = DBOp_Adding;
		currentDBView = DBView_Single_Editable;
	}
	
	if ((!aIsNewRecord) && (dbIsOpened))
	{
		TBuf<255> sqlString;
		TBool readOK = EFalse;
		
		sqlString.Format(_L("SELECT DisplayName, NameField1, ContentField1, NameField2, ContentField2, NameField3, ContentField3, NameField4, ContentField4, NameField5, ContentField5 FROM Databank WHERE Index = %u"), aIndex);
		if (ReadDB(sqlString))
		{
			if (dbView.CountL() == 1)
			{
				dbView.FirstL();
				if (dbView.AtRow())
				{
					dbView.GetL();
					for (i = 0; i < NUM_DATA_FIELDS; i++)
					{
						sqlString.Copy(dbView.ColDes(2 + i * 2));
						fieldLabels[i]->SetTextL(&sqlString);
						sqlString.Copy(dbView.ColDes(3 + i * 2));
						fieldValues[i]->SetTextL(&sqlString);
					}
					sqlString.Copy(dbView.ColDes(1));
					fieldDisplayName->SetTextL(&sqlString);
					currentDBOp = DBOp_Editing;
					readOK = ETrue;
					currentRecordIndex = aIndex;
					currentRecordIndexIsValid = ETrue;
					
					static_cast<CSMan2AppUi*>(CEikonEnv::Static()->EikAppUi())->SetToolbarL(R_TOOLBAR_DB_SINGLE);
					currentDBView = DBView_Single_Editable;
				}
			}
		}
		
		if (!readOK)
		{
			iEikonEnv->InfoMsg(R_TBUF_DB_RECORDMISSING);
			ShowRecordsList(ETrue, ETrue);
			return;
		}
	}
	dbView.Close();	
	scrollableContainer->MakeVisible(ETrue);
	scrollableContainer->SetFocus(ETrue, EDrawNow);
	// We've turned off the horizontal scrollbar and with the way we've positioned the controls, the 
	// vertical scrollbar will ALWAYS appear. However,  to be on the safe side we still check if the
	// vertical scrollbar is there
	TBool vertScroller, horizScroller;
	scrollableContainer->ScrollBarsNeeded(vertScroller, horizScroller);
	if (vertScroller)
	{
		scrollableContainer->ScrollBarFrame()->GetScrollBarHandle(CEikScrollBar::EVertical)->OverrideColorL(EColorScrollBarShaft, KRgbCyan);
		scrollableContainer->ScrollBarFrame()->GetScrollBarHandle(CEikScrollBar::EVertical)->OverrideColorL(EColorScrollThumbEdge, KRgbCyan);
		scrollableContainer->ScrollBarFrame()->GetScrollBarHandle(CEikScrollBar::EVertical)->OverrideColorL(EColorScrollButtonThumbBackground, KRgbCyan);
		scrollableContainer->ScrollBarFrame()->GetScrollBarHandle(CEikScrollBar::EVertical)->OverrideColorL(EColorScrollButtonThumbBackgroundPressed, KRgbCyan);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -