umeedit.pas
来自「FMA is a free1 powerful phone editing to」· PAS 代码 · 共 1,343 行 · 第 1/3 页
PAS
1,343 行
unit uMEEdit;
{
*******************************************************************************
* Descriptions: Phone Book Edit Implementation
* $Source: /cvsroot/fma/fma/Attic/uMEEdit.pas,v $
* $Locker: $
*
* Todo:
*
* Change Log:
* $Log: uMEEdit.pas,v $
*
*******************************************************************************
}
interface
uses
Windows, TntWindows, Messages, SysUtils, TntSysUtils, Classes, TntClasses, Graphics, TntGraphics, Controls, TntControls, Forms, TntForms,
Dialogs, TntDialogs, Grids, TntComCtrls, TntGrids, ExtCtrls, TntExtCtrls, StdCtrls, TntStdCtrls, Math, Menus, TntMenus, VirtualTrees,
ImgList, uSyncPhonebook, Placemnt, uSIMEdit;
type
TfrmContactsMEEdit = class(TTntFrame)
Panel1: TTntPanel;
btnUpdateME: TTntButton;
cbForce: TTntCheckBox;
btnReset: TTntButton;
PopupMenu1: TTntPopupMenu;
Clear1: TTntMenuItem;
Resetchangeflag1: TTntMenuItem;
ListNumbers: TVirtualStringTree;
NoItemsPanel: TTntPanel;
N1: TTntMenuItem;
N2: TTntMenuItem;
Properties1: TTntMenuItem;
NewPerson1: TTntMenuItem;
UpdateChanged1: TTntMenuItem;
UpdateAllRecords1: TTntMenuItem;
FormStorage1: TFormStorage;
N5: TTntMenuItem;
UpdateContactsPosition1: TTntMenuItem;
N4: TTntMenuItem;
ImportContacts1: TTntMenuItem;
ExportContacts1: TTntMenuItem;
OpenDialog1: TTntOpenDialog;
N3: TTntMenuItem;
MessageContact1: TTntMenuItem;
CallContact1: TTntMenuItem;
ChatContact1: TTntMenuItem;
N7: TTntMenuItem;
DownloadEntirePhonebook1: TTntMenuItem;
SendToPhone1: TTntMenuItem;
ForceAs1: TTntMenuItem;
otalChange1: TTntMenuItem;
CopySelectedToSIMcard1: TTntMenuItem;
Modified1: TTntMenuItem;
procedure Button1Click(Sender: TObject);
procedure StringGridGetEditText(Sender: TObject; ACol, ARow: Integer;
var Value: String);
procedure Resetchangeflag1Click(Sender: TObject);
procedure ListNumbersAfterPaint(Sender: TBaseVirtualTree;
TargetCanvas: TCanvas);
procedure ListNumbersCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
procedure ListNumbersGetImageIndex(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer);
procedure ListNumbersGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
procedure ListNumbersHeaderClick(Sender: TVTHeader;
Column: TColumnIndex; Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
procedure PopupMenu1Popup(Sender: TObject);
procedure NewPerson1Click(Sender: TObject);
procedure UpdateChanged1Click(Sender: TObject);
procedure UpdateAllRecords1Click(Sender: TObject);
procedure UpdateContactsPosition1Click(Sender: TObject);
procedure ListNumbersIncrementalSearch(Sender: TBaseVirtualTree;
Node: PVirtualNode; const SearchText: WideString;
var Result: Integer);
procedure ImportContacts1Click(Sender: TObject);
procedure DownloadEntirePhonebook1Click(Sender: TObject);
procedure ListNumbersKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormStorage1SavePlacement(Sender: TObject);
procedure FormStorage1RestorePlacement(Sender: TObject);
procedure ListNumbersHeaderMouseUp(Sender: TVTHeader;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure btnResetClick(Sender: TObject);
procedure btnUpdateMEClick(Sender: TObject);
procedure btnDELClick(Sender: TObject);
procedure btnEDITClick(Sender: TObject);
procedure CopySelectedToSIMcard1Click(Sender: TObject);
procedure Modified1Click(Sender: TObject);
procedure frmSyncPhonebookNewNoUndo2Click(Sender: TObject);
private
{ Private declarations }
FContact: TContactData; // used for SIM contact editing (uEditContact)
FExplore: PVirtualNode; // remember last rendered data's explorer node
FOldText: String;
function IsUniqueGUID(who: PSIMData): boolean;
procedure FullRefresh;
procedure UpdatePhone(MaxItems: cardinal = 0);
procedure RenderGUIDs;
protected
{ Protected declarations }
FRendered: Boolean;
function FindFreePos: integer;
function GetCapacity(Target, LogName: string): Integer;
procedure DoForceSelectedAs(State: integer);
public
{ Public declarations }
SelContact: PSIMData;
FMaxNumbers: Cardinal;
FMaxNameLen,FMaxTelLen: integer;
constructor Create(AOwner: TComponent); override;
procedure UpdatePhonebook;
procedure OnConnected; virtual;
procedure ExportList(FileType:Integer; Filename: WideString); virtual;
function RenderData(ForceDBNode: PVirtualNode = nil): boolean;
function IsMEMode: boolean; virtual;
function IsRendered: boolean;
function DoEdit(AsNew: boolean = False; NewNumber: string = ''): boolean;
function FindContact(Number: WideString): WideString; overload;
function FindContact(FullName: WideString; var AContact: PSIMData): boolean; overload;
function FindContact(FullName,NumberType: WideString; var AContact: PSIMData): boolean; overload;
function FindContact(FullName: WideString; var ANode: PVirtualNode): boolean; overload;
procedure CheckForChanges;
end;
implementation
uses
gnugettext, gnugettexthelpers, cUnicodeCodecs,
uLogger, uThreadSafe, Unit1, uSMS, uGlobal, uEditContact, uConnProgress, uVcard, uXML, WebUtil, uDialogs;
{$R *.dfm}
{ TfrmContactsSMEdit }
constructor TfrmContactsMEEdit.Create(AOwner: TComponent);
begin
inherited;
{ Set defaults }
FMaxNameLen := 180; FMaxTelLen := 80; FMaxNumbers := 510;
FRendered := False;
end;
function TfrmContactsMEEdit.RenderData(ForceDBNode: PVirtualNode): boolean;
var
sl: TStrings;
s: WideString;
i: Integer;
contact: PSIMData;
Node: PVirtualNode;
EData: PFmaExplorerNode;
Modified,NeedRefresh: Boolean;
begin
{ ForceDBNode is used when loading Profile database etc. }
if Assigned(ForceDBNode) then
FExplore := ForceDBNode
else
if Form1.ExplorerNew.FocusedNode = Form1.FNodeContactsME then
FExplore :=Form1.FNodeContactsME
else
FExplore :=Form1.FNodeContactsSM;
EData := Form1.ExplorerNew.GetNodeData(FExplore);
sl := EData.Data;
{ Load database }
Modified := False;
NeedRefresh := False;
ListNumbers.BeginUpdate;
try
ListNumbers.Clear;
ListNumbers.NodeDataSize := sizeof(TSIMData);
for i := 0 to sl.Count - 1 do begin
s := LongStringToWideString(sl[i]);
if Trim(s) = '' then continue;
{ process DB }
Node := ListNumbers.AddChild(nil);
try
contact := ListNumbers.GetNodeData(Node);
contact.cname := UTF8StringToWideString(HTMLDecode(WideStringToLongString(GetFirstToken(s))));
contact.pnumb := GetFirstToken(s);
contact.position := StrToInt(GetFirstToken(s));
if contact.position = 0 then NeedRefresh := True;
try
contact.imageindex := StrToInt(GetFirstToken(s));
except
contact.imageindex := 3; // 3 = not modified (new) item
Modified := True;
end;
try
contact.CDID := StringToGUID(GetFirstToken(s));
except
contact.CDID := NewGUID;
Modified := True;
end;
contact.LUID := GetFirstToken(s);
Form1.ExtractName(contact.cname,contact.ptype);
except
ListNumbers.DeleteNode(Node);
Log.AddMessageFmt(_('Database: Error loading data (DB Index %d)'), [i], lsError);
if FindCmdLineSwitch('FIXDB') then begin
sl[i] := '';
Log.AddMessageFmt(_('Database: Removed incorrect data (DB Index: %d)'), [i], lsInformation);
end;
end;
end;
RenderGUIDs;
FRendered := True;
finally
ListNumbers.EndUpdate;
ListNumbers.Sort(nil, ListNumbers.Header.SortColumn, ListNumbers.Header.SortDirection);
end;
if NeedRefresh then
if not Form1.IsIrmcSyncEnabled then
Form1.Status(WideFormat(_('Please refresh %s from phone, because some contact positions are missing!'),
[EData.Text]));
Result := Modified;
end;
procedure TfrmContactsMEEdit.Button1Click(Sender: TObject);
begin
if not Form1.FConnected then Form1.ActionConnectionConnectExecute(Self);
Form1.ActionContactsDownloadExecute(Self);
RenderData;
end;
procedure TfrmContactsMEEdit.UpdatePhone(MaxItems: cardinal);
begin
Form1.frmSMEdit.UploadChangesToPhone(IsMEMode,ListNumbers,MaxItems,FMaxNumbers,FMaxNameLen,cbForce.Checked);
end;
procedure TfrmContactsMEEdit.btnUpdateMEClick(Sender: TObject);
var
Item: PSIMData;
Node: PVirtualNode;
mcount,dcount,count: cardinal;
s,d: WideString;
begin
mcount := 0; dcount := 0;
Node := ListNumbers.GetFirst;
while Assigned(Node) do
try
item := ListNumbers.GetNodeData(Node);
if item.imageindex = 2 then
// deleted contact
inc(dcount)
else
// then process modified (or all) entries
if (item.imageindex <> 3) or cbForce.Checked then begin
{ Do sanity check for modified contacts }
if (Trim(item.cname) = '') and (Trim(item.pnumb) <> '') then
raise EConvertError.Create(Format(_('Please enter a contact name at position %s'),[IntToStr(item.position)]));
if (Trim(item.cname) <> '') and (Trim(item.pnumb) = '') then
raise EConvertError.Create(Format(_('Please enter a phone number at position %s'),[IntToStr(item.position)]));
if Length(item.cname) > FMaxNameLen then
raise EConvertError.Create(Format(_('The name at position %s is too long'),[IntToStr(item.position)]));
if Length(item.pnumb) > (FMaxTelLen+byte(Pos('+',item.pnumb) <> 0)) then
raise EConvertError.Create(Format(_('The number at position %s is too long'),[IntToStr(item.position)]));
inc(mcount);
end;
finally
Node := ListNumbers.GetNext(Node);
end;
count := mcount + dcount;
if count <> 0 then begin
if mcount <> 0 then
s := WideFormat(ngettext('%d modified contact', '%d modified contacts', mcount), [mcount])
else
s := '';
if dcount <> 0 then
d := WideFormat(ngettext('%d deleted contact', '%d deleted contacts', dcount), [dcount])
else
d := '';
if s <> '' then begin
if d <> '' then s := WideFormat('%s and %d',[s,d]);
end
else
s := d;
case MessageDlgW(WideFormat(_('Confirm sending %s to Phonebook?'),[s]), mtConfirmation, MB_YESNOCANCEL) of
ID_YES: UpdatePhone(count);
ID_CANCEL: Abort;
end;
end;
end;
procedure TfrmContactsMEEdit.btnResetClick(Sender: TObject);
var
Item: PSIMData;
Node: PVirtualNode;
begin
ListNumbers.BeginUpdate;
Node := ListNumbers.GetFirst;
while Node <> nil do
try
item := ListNumbers.GetNodeData(Node);
item.imageindex := 3; // mark as not modified
finally
Node := ListNumbers.GetNext(Node);
end;
ListNumbers.EndUpdate;
UpdatePhonebook;
end;
procedure TfrmContactsMEEdit.StringGridGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
FOldText := Value;
end;
procedure TfrmContactsMEEdit.btnDELClick(Sender: TObject);
var
Item: PSIMData;
Node,Tmp: PVirtualNode;
s: WideString;
begin
if ListNumbers.SelectedCount = 0 then exit;
s := WideFormat(_('Deleting %d %s.'), [ListNumbers.SelectedCount,ngettext('contact','contacts',ListNumbers.SelectedCount)]);
if MessageDlgW(s+_(' Do you wish to continue?'), mtConfirmation, MB_YESNO or MB_DEFBUTTON2) <> ID_YES then
exit;
Form1.Status(s+'..');
ListNumbers.BeginUpdate;
try
Node := ListNumbers.GetFirst;
while Node <> nil do begin
if ListNumbers.Selected[Node] then begin
item := ListNumbers.GetNodeData(Node);
if item.imageindex <> 0 then begin
item.imageindex := 2;
end
else begin
Tmp := Node;
if Node <> ListNumbers.GetFirst then begin
Node := ListNumbers.GetPrevious(Node);
ListNumbers.DeleteNode(Tmp);
end
else begin
ListNumbers.DeleteNode(Tmp);
Node := ListNumbers.GetFirst;
continue;
end;
end;
end;
Node := ListNumbers.GetNext(Node);
end;
finally
ListNumbers.EndUpdate;
UpdatePhonebook;
end;
Form1.Status('');
end;
procedure TfrmContactsMEEdit.Resetchangeflag1Click(Sender: TObject);
begin
DoForceSelectedAs(3);
end;
function TfrmContactsMEEdit.GetCapacity(Target, LogName: string): Integer;
var
i: Integer;
buffer, stop: String;
slTmp: TStrings;
begin
Form1.TxAndWait('AT+CPBS="'+Target+'"'); // do not localize
Form1.TxAndWait('AT+CPBR=?'); // do not localize
// defaults
buffer := '';
stop := '200'; FMaxNameLen := 14; FMaxTelLen := 80;
// +CPBR: (1-200),80,14
for i := 0 to ThreadSafe.RxBuffer.Count-1 do
if Pos('+CPBR',ThreadSafe.RxBuffer.Strings[i]) = 1 then begin // do not localize
buffer := ThreadSafe.RxBuffer.Strings[i];
break;
end;
for i := 1 to length(buffer) do begin
if IsDelimiter('()-,', buffer, i) then buffer[i] := ' ';
end;
// +CPBR: 1 200 80 14
if buffer <> '' then begin
slTmp := TStringList.Create;
try
slTmp.DelimitedText := buffer;
stop := slTmp.Strings[2];
Log.AddMessage(LogName+': max entries = '+stop, lsDebug); // do not localize debug
FMaxTelLen := StrToInt(slTmp.Strings[3]);
Log.AddMessage(LogName+': max tel length = '+slTmp.Strings[3], lsDebug); // do not localize debug
FMaxNameLen := StrToInt(slTmp.Strings[4]);
Log.AddMessage(LogName+': max name length = '+slTmp.Strings[4], lsDebug); // do not localize debug
finally
slTmp.Free;
end;
end;
Result := StrToInt(stop);
end;
procedure TfrmContactsMEEdit.OnConnected;
begin
FMaxNumbers := GetCapacity('ME','Phone Book');
end;
procedure TfrmContactsMEEdit.ListNumbersAfterPaint(Sender: TBaseVirtualTree;
TargetCanvas: TCanvas);
begin
NoItemsPanel.Visible := ListNumbers.RootNodeCount = 0;
end;
procedure TfrmContactsMEEdit.ListNumbersCompareNodes(Sender: TBaseVirtualTree;
Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
SIM1, SIM2: PSIMData;
begin
SIM1 := Sender.GetNodeData(Node1);
SIM2 := Sender.GetNodeData(Node2);
if Column = 0 then begin
if SIM1.position > SIM2.position then
Result := 1
else
if SIM1.position < SIM2.position then
Result := -1
else
Result := 0;
end
else if Column = 1 then Result := WideCompareStr(SIM1.cname, SIM2.cname)
else if Column = 2 then Result := WideCompareStr(SIM1.pnumb, SIM2.pnumb);
end;
procedure TfrmContactsMEEdit.ListNumbersGetImageIndex(Sender: TBaseVirtualTree;
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
var Ghosted: Boolean; var ImageIndex: Integer);
var
SIM: PSIMData;
begin
if Column = 0 then begin
if (Kind = ikNormal) or (Kind = ikSelected) then begin
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?