📄 dbview.cpp
字号:
{
// 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 + -