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

📄 usimedit.pas

📁 FMA is a free1 powerful phone editing tool allowing users to easily manage all of the personal data
💻 PAS
📖 第 1 页 / 共 4 页
字号:
unit uSIMEdit;

{
*******************************************************************************
* Descriptions: SIM Card Phonebook Edit Implementation
* $Source: /cvsroot/fma/fma/uSIMEdit.pas,v $
* $Locker:  $
*
* Todo:
*
* Change Log:
* $Log: uSIMEdit.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, uPromptConflict, uConflictChanges, Placemnt;

type
  TSIMData = Record
    imageindex: integer; {0=new,1=modified,2=deleted,3=normal}
    position: integer;
    cname,pnumb,ptype: WideString;
    CDID: TGUID;
    LUID : WideString;
  end;
  PSIMData = ^TSIMData;

  TfrmContactsSMEdit = class(TTntFrame)
    Panel1: TTntPanel;
    btnUpdateSIM: 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;
    CopySelectedToPhone1: 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;
    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 CopySelectedToPhone1Click(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 btnUpdateSIMClick(Sender: TObject);
    procedure btnDELClick(Sender: TObject);
    procedure btnEDITClick(Sender: TObject);
    procedure Modified1Click(Sender: TObject);
    procedure frmSyncPhonebookNewNoUndo1Click(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 UpdateSIM(MaxItems: cardinal = 0);
    procedure RenderGUIDs;
  protected
    { Protected declarations }
    FConflictPhone0,FConflictPhone1: string;
    FConflictAnswer: integer;
    FRendered: Boolean;
    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 FindFreePos(NodeData: TStrings = nil): integer;
    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;
    procedure UploadChangesToPhone(IsMEMode: boolean; var ListNumbers: TVirtualStringTree;
      ModifiedCount, MaxNumbers, MaxNameLen: cardinal; UploadAll: boolean);

    procedure CopySelectedToME;
    procedure CopySelectedToIRMC;
    procedure CopyContactsConflict(Sender: TObject; ContactName: WideString; const Description: WideString;
      Phone0,Phone1: string; const Item0Name, Item1Name: WideString; var SelectedItem: Integer);
    procedure OnConflictChanges(Sender: TObject; const TargetName, Option1Name, Option2Name: WideString);
    procedure ResetConflictState;
  end;

implementation

uses
  gnugettext, gnugettexthelpers, cUnicodeCodecs,
  uLogger, uThreadSafe, Unit1, uSMS, uGlobal, uEditContact, uConnProgress, uVcard, uXML, WebUtil, uDialogs;

{$R *.dfm}

{ TfrmContactsSMEdit }

constructor TfrmContactsSMEdit.Create(AOwner: TComponent);
begin
  inherited;
  { Set defaults }
  FMaxNameLen := 14; FMaxTelLen := 80; FMaxNumbers := 200;
  FRendered := False;
end;

function TfrmContactsSMEdit.RenderData(ForceDBNode: PVirtualNode): boolean;
var
  sl: TStrings;
  s: WideString;
  i: Integer;
  contact: PSIMData;
  Node: PVirtualNode;
  EData: PFmaExplorerNode;
  Modified,NeedRefresh: Boolean;
begin
  ResetConflictState;
  { 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
    Form1.Status(WideFormat(_('Please refresh %s from phone, because some contact positions are missing!'),
      [EData.Text]));
  Result := Modified;
end;

procedure TfrmContactsSMEdit.Button1Click(Sender: TObject);
begin
  if not Form1.FConnected then Form1.ActionConnectionConnectExecute(Self);

  Form1.ActionContactsDownloadExecute(Self);
  RenderData;
end;

procedure TfrmContactsSMEdit.UpdateSIM(MaxItems: cardinal);
begin
  UploadChangesToPhone(IsMEMode,ListNumbers,MaxItems,FMaxNumbers,FMaxNameLen,cbForce.Checked);
end;

procedure TfrmContactsSMEdit.btnUpdateSIMClick(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 SIM card?'),[s]), mtConfirmation, MB_YESNOCANCEL) of
      ID_YES: UpdateSIM(count);
      ID_CANCEL: Abort;
    end;
  end;
end;

procedure TfrmContactsSMEdit.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 TfrmContactsSMEdit.StringGridGetEditText(Sender: TObject; ACol,
  ARow: Integer; var Value: String);
begin
  FOldText := Value;
end;

procedure TfrmContactsSMEdit.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 TfrmContactsSMEdit.Resetchangeflag1Click(Sender: TObject);
begin
  DoForceSelectedAs(3);
end;

function TfrmContactsSMEdit.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 TfrmContactsSMEdit.OnConnected;
begin
  FMaxNumbers := GetCapacity('SM','SIM Book');
end;

procedure TfrmContactsSMEdit.ListNumbersAfterPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas);
begin
  NoItemsPanel.Visible := ListNumbers.RootNodeCount = 0;

⌨️ 快捷键说明

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