- Timestamp:
- Dec 21, 2021, 5:16:41 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Forms/UFormContacts.lfm
r76 r82 16 16 object ListView1: TListView 17 17 Left = 0 18 Height = 8 0118 Height = 810 19 19 Top = 0 20 20 Width = 1210 … … 68 68 Left = 0 69 69 Height = 39 70 Top = 8 3370 Top = 842 71 71 Width = 1210 72 72 Align = alBottom … … 116 116 Left = 0 117 117 Height = 32 118 Top = 8 01118 Top = 810 119 119 Width = 1210 120 120 OnChange = ListViewFilter1Change … … 123 123 object StatusBar1: TStatusBar 124 124 Left = 0 125 Height = 36126 Top = 8 72125 Height = 27 126 Top = 881 127 127 Width = 1210 128 128 Panels = < -
trunk/Forms/UFormContacts.pas
r77 r82 203 203 for J := 0 to FilterItems.Count - 1 do begin 204 204 if FilterItems[J].FieldIndex = cfNone then begin 205 for K := 0 to TContact(List.Items[I]). Parent.Fields.Count - 1 do begin205 for K := 0 to TContact(List.Items[I]).GetFields.Count - 1 do begin 206 206 if Pos(UTF8LowerCase(FilterItems[J].Value), 207 UTF8LowerCase(TContact(List.Items[I]).Fields[TContact(List.Items[I]). Parent.Fields[K].Index])) > 0 then begin207 UTF8LowerCase(TContact(List.Items[I]).Fields[TContact(List.Items[I]).GetFields[K].Index])) > 0 then begin 208 208 Inc(FoundCount); 209 209 Break; … … 286 286 for I := 0 to ListView1.Columns.Count - 1 do begin 287 287 if Assigned(Contacts) and Assigned(Contacts.ContactsFile) then begin 288 Field := Contacts.ContactsFile.Fields.GetByIndex(ListViewColumns[I]);288 Field := TContact.GetFields.GetByIndex(ListViewColumns[I]); 289 289 if Assigned(Field) then 290 290 ListView1.Columns[I].Caption := Field.Title; … … 312 312 Contact := TContact.Create; 313 313 try 314 Contact. Parent:= Contacts.ContactsFile;314 Contact.ContactsFile := Contacts.ContactsFile; 315 315 FormContact.Contact := Contact; 316 316 FormContact.OnGetPrevious := GetPreviousContact; 317 317 FormContact.OnGetNext := GetNextContact; 318 Contact.Properties.AddNew('VERSION', Core.DefaultVcardVersion); 318 319 if FormContact.ShowModal = mrOK then begin 319 320 Contacts.Add(Contact); … … 341 342 Contact := TContact.Create; 342 343 try 343 Contact. Parent:= Contacts.ContactsFile;344 Contact.ContactsFile := Contacts.ContactsFile; 344 345 Contact.Assign(TContact(ListView1.Selected.Data)); 345 346 FormContact.Contact := Contact; … … 442 443 Contact := TContact.Create; 443 444 try 444 Contact. Parent:= Contacts.ContactsFile;445 Contact.ContactsFile := Contacts.ContactsFile; 445 446 Contact.Assign(TContact(ListView1.Selected.Data)); 446 447 FormContact.Contact := Contact; -
trunk/Forms/UFormFind.lfm
r76 r82 27 27 object ComboBoxField: TComboBox 28 28 Left = 184 29 Height = 3329 Height = 41 30 30 Top = 16 31 31 Width = 240 32 ItemHeight = 2532 ItemHeight = 0 33 33 OnChange = ComboBoxFieldChange 34 34 ParentFont = False … … 38 38 object Label1: TLabel 39 39 Left = 13 40 Height = 2 540 Height = 24 41 41 Top = 19 42 Width = 1 2542 Width = 135 43 43 Caption = 'By contact field:' 44 44 ParentColor = False … … 47 47 object EditValue: TEdit 48 48 Left = 440 49 Height = 3349 Height = 42 50 50 Top = 16 51 51 Width = 208 -
trunk/Forms/UFormFind.pas
r76 r82 63 63 Items := TStringList.Create; 64 64 try 65 Contacts.ContactsFile.Fields.LoadToStrings(Items);65 TContact.GetFields.LoadToStrings(Items); 66 66 67 67 // Remove fields which are not used in contacts … … 75 75 Items.Free; 76 76 end; 77 ContactField := Contacts.ContactsFile.Fields.GetByIndex(ContactFieldIndex);77 ContactField := TContact.GetFields.GetByIndex(ContactFieldIndex); 78 78 ComboBoxField.ItemIndex := ComboBoxField.Items.IndexOfObject(ContactField); 79 79 if (ComboBoxField.Items.Count > 0) and (ComboBoxField.ItemIndex = -1) then -
trunk/Forms/UFormFindDuplicity.lfm
r73 r82 31 31 item 32 32 Caption = 'Count' 33 Width = 13633 Width = 242 34 34 end> 35 35 OwnerData = True … … 56 56 object ComboBoxField: TComboBox 57 57 Left = 160 58 Height = 3358 Height = 41 59 59 Top = 16 60 60 Width = 326 61 ItemHeight = 2561 ItemHeight = 0 62 62 OnChange = ComboBoxFieldChange 63 63 ParentFont = False … … 67 67 object Label1: TLabel 68 68 Left = 13 69 Height = 2 569 Height = 24 70 70 Top = 19 71 Width = 1 2571 Width = 135 72 72 Caption = 'By contact field:' 73 73 ParentColor = False -
trunk/Forms/UFormFindDuplicity.pas
r73 r82 119 119 Items := TStringList.Create; 120 120 try 121 Contacts.ContactsFile.Fields.LoadToStrings(Items);121 TContact.GetFields.LoadToStrings(Items); 122 122 123 123 // Remove fields which are not used in contacts … … 130 130 Items.Free; 131 131 end; 132 ContactField := Contacts.ContactsFile.Fields.GetByIndex(ContactFieldIndex);132 ContactField := TContact.GetFields.GetByIndex(ContactFieldIndex); 133 133 ComboBoxField.ItemIndex := ComboBoxField.Items.IndexOfObject(ContactField); 134 134 if (ComboBoxField.Items.Count > 0) and (ComboBoxField.ItemIndex = -1) then -
trunk/Forms/UFormProperty.pas
r68 r82 102 102 Core.ThemeManager1.UseTheme(Self); 103 103 FContactProperty := nil; 104 TContact sFile(Core.DataFile).Fields.LoadToStrings(ComboBoxField.Items);104 TContact.GetFields.LoadToStrings(ComboBoxField.Items); 105 105 end; 106 106 … … 129 129 Groups.Free; 130 130 end; 131 Field := TContact sFile(Core.DataFile).Fields.GetBySysNameGroups(EditName.Text,131 Field := TContact.GetFields.GetBySysNameGroups(EditName.Text, 132 132 GroupsArray); 133 133 if Assigned(Field) then -
trunk/Forms/UFormSettings.lfm
r23 r82 3 3 Height = 360 4 4 Top = 367 5 Width = 5 775 Width = 564 6 6 Caption = 'Settings' 7 7 ClientHeight = 360 8 ClientWidth = 5 778 ClientWidth = 564 9 9 Constraints.MinHeight = 360 10 10 Constraints.MinWidth = 480 … … 16 16 LCLVersion = '2.0.12.0' 17 17 object ComboBoxLanguage: TComboBox 18 Left = 19218 Left = 240 19 19 Height = 41 20 Top = 3621 Width = 31220 Top = 16 21 Width = 264 22 22 ItemHeight = 0 23 23 ParentFont = False … … 28 28 Left = 24 29 29 Height = 24 30 Top = 3630 Top = 24 31 31 Width = 88 32 32 Caption = 'Language:' … … 35 35 end 36 36 object ButtonOk: TButton 37 Left = 4 5137 Left = 438 38 38 Height = 37 39 39 Top = 307 … … 47 47 end 48 48 object ButtonCancel: TButton 49 Left = 30749 Left = 294 50 50 Height = 37 51 51 Top = 307 … … 58 58 end 59 59 object CheckBoxAutomaticDPI: TCheckBox 60 Left = 1960 Left = 24 61 61 Height = 30 62 Top = 12562 Top = 200 63 63 Width = 148 64 64 Caption = 'Automatic DPI' … … 69 69 end 70 70 object SpinEditDPI: TSpinEdit 71 Left = 19271 Left = 240 72 72 Height = 42 73 Top = 17373 Top = 232 74 74 Width = 145 75 75 MaxValue = 300 … … 81 81 end 82 82 object LabelDPI: TLabel 83 Left = 9683 Left = 56 84 84 Height = 24 85 Top = 18285 Top = 240 86 86 Width = 35 87 87 Caption = 'DPI:' … … 91 91 end 92 92 object CheckBoxReopenLastFileOnStart: TCheckBox 93 Left = 1993 Left = 24 94 94 Height = 30 95 Top = 8695 Top = 160 96 96 Width = 226 97 97 Caption = 'Reopen last file on start' … … 103 103 Height = 2 104 104 Top = 288 105 Width = 5 47105 Width = 534 106 106 Anchors = [akLeft, akRight, akBottom] 107 107 end … … 109 109 Left = 24 110 110 Height = 24 111 Top = 221111 Top = 72 112 112 Width = 63 113 113 Caption = 'Theme:' … … 116 116 end 117 117 object ComboBoxTheme: TComboBox 118 Left = 192118 Left = 240 119 119 Height = 41 120 Top = 221121 Width = 312120 Top = 64 121 Width = 264 122 122 ItemHeight = 0 123 123 ParentFont = False … … 125 125 TabOrder = 6 126 126 end 127 object Label3: TLabel 128 Left = 24 129 Height = 24 130 Top = 120 131 Width = 186 132 Caption = 'Default vCard version:' 133 ParentColor = False 134 end 135 object EditDefaultVcardVersion: TEdit 136 Left = 240 137 Height = 42 138 Top = 112 139 Width = 144 140 TabOrder = 7 141 end 127 142 end -
trunk/Forms/UFormSettings.lrj
r21 r82 7 7 {"hash":300234,"name":"tformsettings.labeldpi.caption","sourcebytes":[68,80,73,58],"value":"DPI:"}, 8 8 {"hash":55973348,"name":"tformsettings.checkboxreopenlastfileonstart.caption","sourcebytes":[82,101,111,112,101,110,32,108,97,115,116,32,102,105,108,101,32,111,110,32,115,116,97,114,116],"value":"Reopen last file on start"}, 9 {"hash":95339402,"name":"tformsettings.label2.caption","sourcebytes":[84,104,101,109,101,58],"value":"Theme:"} 9 {"hash":95339402,"name":"tformsettings.label2.caption","sourcebytes":[84,104,101,109,101,58],"value":"Theme:"}, 10 {"hash":232157114,"name":"tformsettings.label3.caption","sourcebytes":[68,101,102,97,117,108,116,32,118,67,97,114,100,32,118,101,114,115,105,111,110,58],"value":"Default vCard version:"} 10 11 ]} -
trunk/Forms/UFormSettings.pas
r23 r82 21 21 ComboBoxLanguage: TComboBox; 22 22 ComboBoxTheme: TComboBox; 23 EditDefaultVcardVersion: TEdit; 23 24 Label1: TLabel; 24 25 Label2: TLabel; 26 Label3: TLabel; 25 27 LabelDPI: TLabel; 26 28 SpinEditDPI: TSpinEdit; … … 100 102 SpinEditDPI.Value := Core.ScaleDPI1.DPI.X; 101 103 CheckBoxReopenLastFileOnStart.Checked := Core.ReopenLastFileOnStart; 104 EditDefaultVcardVersion.Text := Core.DefaultVcardVersion; 102 105 UpdateInterface; 103 106 end; … … 108 111 Core.ScaleDPI1.DPI := Point(SpinEditDPI.Value, SpinEditDPI.Value); 109 112 Core.ReopenLastFileOnStart := CheckBoxReopenLastFileOnStart.Checked; 113 Core.DefaultVcardVersion := EditDefaultVcardVersion.Text; 110 114 end; 111 115 -
trunk/Install/snap/snapcraft.yaml
r79 r82 42 42 install -d -m 755 $SNAPCRAFT_PART_INSTALL/usr/share/pixmaps 43 43 install -m 755 Images/vCard\ Studio.png $SNAPCRAFT_PART_INSTALL/usr/share/pixmaps 44 after: 45 - desktop-gtk2 44 46 stage: 45 47 - etc … … 82 84 - libxrender1 83 85 86 desktop-gtk2: 87 source: https://github.com/ubuntu/snapcraft-desktop-helpers.git 88 source-subdir: gtk 89 plugin: make 90 make-parameters: ["FLAVOR=gtk2"] 91 build-packages: 92 - build-essential 93 - libgtk2.0-dev 94 stage-packages: 95 - libxkbcommon0 # XKB_CONFIG_ROOT 96 - ttf-ubuntu-font-family 97 - dmz-cursor-theme 98 - light-themes 99 - adwaita-icon-theme 100 - gnome-themes-standard 101 - shared-mime-info 102 - libgtk2.0-0 103 - libgdk-pixbuf2.0-0 104 - libglib2.0-bin 105 - libgtk2.0-bin 106 - unity-gtk2-module 107 - locales-all 108 - libappindicator1 109 - xdg-user-dirs 110 - ibus-gtk 111 - libibus-1.0-5 112 113 # additional plugs to pick up the GTK theme and icons from the system 114 plugs: 115 icon-themes: 116 interface: content 117 target: $SNAP/data-dir/icons 118 default-provider: gtk-common-themes 119 sound-themes: 120 interface: content 121 target: $SNAP/data-dir/sounds 122 default-provider: gtk-common-themes 123 gtk-2-engines: 124 interface: content 125 target: $SNAP/lib/gtk-2.0 126 default-provider: gtk2-common-themes:gtk-2-engines 127 gtk-2-themes: 128 interface: content 129 target: $SNAP/usr/share/themes 130 default-provider: gtk2-common-themes:gtk-2-themes 131 132 environment: 133 XDG_DATA_DIRS: $SNAP/usr/share:$XDG_DATA_DIRS 134 GTK_PATH: $SNAP/lib/gtk-2.0 135 84 136 apps: 85 137 vcard-studio: 86 138 command: usr/bin/vCardStudio 139 command-chain: 140 - bin/desktop-launch 87 141 desktop: usr/share/applications/vCardStudio.desktop 88 142 plugs: -
trunk/Languages/vCardStudio.cs.po
r77 r82 779 779 msgstr "Téma:" 780 780 781 #: tformsettings.label3.caption 782 msgid "Default vCard version:" 783 msgstr "Výchozí verze vCard:" 784 781 785 #: tformsettings.labeldpi.caption 782 786 msgid "DPI:" … … 1249 1253 msgid "Invalid line length for encoded text" 1250 1254 msgstr "Neplatná délka řádky kódovaného textu" 1251 -
trunk/Languages/vCardStudio.po
r76 r82 767 767 msgstr "" 768 768 769 #: tformsettings.label3.caption 770 msgid "Default vCard version:" 771 msgstr "" 772 769 773 #: tformsettings.labeldpi.caption 770 774 msgid "DPI:" -
trunk/UContact.pas
r77 r82 106 106 107 107 TContactProperties = class(TFPGObjectList<TContactProperty>) 108 function AddNew(Name, Value: string): TContactProperty; 108 109 procedure Assign(Source: TContactProperties); 109 110 procedure AssignToList(List: TFPGObjectList<TObject>); … … 121 122 FModified: Boolean; 122 123 FOnModify: TNotifyEvent; 124 class var FFields: TContactFields; 123 125 function GetField(Index: TContactFieldIndex): string; 124 126 procedure SetField(Index: TContactFieldIndex; AValue: string); … … 127 129 public 128 130 Properties: TContactProperties; 129 Parent: TContactsFile; 131 ContactsFile: TContactsFile; 132 class function GetFields: TContactFields; 130 133 function HasField(FieldIndex: TContactFieldIndex): Boolean; 131 134 function FullNameToFileName: string; … … 136 139 constructor Create; 137 140 destructor Destroy; override; 141 class destructor Destroy; 138 142 procedure SaveToStrings(Output: TStrings); 139 143 function LoadFromStrings(Lines: TStrings; StartLine: Integer = 0): Integer; … … 167 171 private 168 172 FOnError: TErrorEvent; 169 procedure InitFields;170 173 procedure Error(Text: string; Line: Integer); 171 174 function NewItem(Key, Value: string): string; 172 175 public 173 Fields: TContactFields;174 176 Contacts: TContacts; 175 177 function GetFileName: string; override; … … 430 432 { TContactProperties } 431 433 434 function TContactProperties.AddNew(Name, Value: string): TContactProperty; 435 begin 436 Result := TContactProperty.Create; 437 Result.Name := Name; 438 Result.Value := Value; 439 Add(Result); 440 end; 441 432 442 procedure TContactProperties.Assign(Source: TContactProperties); 433 443 var … … 643 653 for I := 0 to Count - 1 do begin 644 654 Items[I].Assign(Source.Items[I]); 645 Items[I]. Parent:= ContactsFile;655 Items[I].ContactsFile := ContactsFile; 646 656 end; 647 657 end; … … 655 665 NewContact := TContact.Create; 656 666 NewContact.Assign(Contacts[I]); 657 NewContact. Parent:= ContactsFile;667 NewContact.ContactsFile := ContactsFile; 658 668 Add(NewContact); 659 669 end; … … 668 678 NewContact := TContact.Create; 669 679 NewContact.Assign(Contacts[I]); 670 NewContact. Parent:= ContactsFile;680 NewContact.ContactsFile := ContactsFile; 671 681 Insert(Index, NewContact); 672 682 Inc(Index); … … 687 697 begin 688 698 Result := TContact.Create; 689 Result. Parent:= ContactsFile;699 Result.ContactsFile := ContactsFile; 690 700 Add(Result); 691 701 end; … … 723 733 NewContact := TContact.Create; 724 734 NewContact.Assign(Contact); 725 NewContact. Parent:= ContactsFile;735 NewContact.ContactsFile := ContactsFile; 726 736 Add(NewContact); 727 737 end; … … 813 823 { TContact } 814 824 815 function TContact.GetField(Index: TContactFieldIndex): string; 816 var 817 Prop: TContactProperty; 818 Field: TContactField; 819 begin 820 if not Assigned(Parent) then raise Exception.Create(SContactHasNoParent); 821 Field := Parent.Fields.GetByIndex(Index); 822 if Assigned(Field) then begin 823 Prop := GetProperty(Field); 824 if Assigned(Prop) then begin 825 Field := Parent.Fields.GetByIndex(Index); 826 if Field.ValueIndex <> -1 then begin 827 Result := DecodeEscaped(Prop.ValueItem[Field.ValueIndex]) 828 end else Result := Prop.Value; 829 end else Result := ''; 830 end else raise Exception.Create(SFieldIndexNotDefined); 831 end; 832 833 procedure TContact.SetField(Index: TContactFieldIndex; AValue: string); 834 var 835 Prop: TContactProperty; 836 Field: TContactField; 837 I: Integer; 838 begin 839 if not Assigned(Parent) then raise Exception.Create(SContactHasNoParent); 840 Field := Parent.Fields.GetByIndex(Index); 841 if Assigned(Field) then begin 842 Prop := GetProperty(Field); 843 if (not Assigned(Prop)) and (AValue <> '') then begin 844 Prop := TContactProperty.Create; 845 Prop.Name := Field.SysName; 846 for I := 0 to Length(Field.Groups) - 1 do 847 Prop.Attributes.Add(Field.Groups[I]); 848 Properties.Add(Prop); 849 end; 850 if Assigned(Prop) then begin 851 if Field.ValueIndex <> -1 then begin 852 Prop.ValueItem[Field.ValueIndex] := EncodeEscaped(AValue); 853 end else Prop.Value := AValue; 854 855 // Remove if empty 856 if Prop.Value = '' then begin 857 Properties.Remove(Prop); 858 end; 859 end; 860 Modified := True; 861 end else raise Exception.Create(SFieldIndexNotDefined); 862 end; 863 864 procedure TContact.SetModified(AValue: Boolean); 865 begin 866 if FModified = AValue then Exit; 867 FModified := AValue; 868 DoOnModify; 869 end; 870 871 procedure TContact.DoOnModify; 872 begin 873 if Assigned(FOnModify) then FOnModify(Self); 874 end; 875 876 function TContact.HasField(FieldIndex: TContactFieldIndex): Boolean; 877 var 878 Field: TContactField; 879 begin 880 if not Assigned(Parent) then raise Exception.Create(SContactHasNoParent); 881 Field := Parent.Fields.GetByIndex(FieldIndex); 882 if Assigned(Field) then begin 883 Result := Assigned(GetProperty(Field)); 884 end else raise Exception.Create(SFieldIndexNotDefined); 885 end; 886 887 function TContact.FullNameToFileName: string; 888 var 889 I: Integer; 890 begin 891 Result := Fields[cfFullName]; 892 for I := 1 to Length(Result) do begin 893 if Result[I] in [':', '/', '\', '.', '"', '*', '|', '?', '<', '>'] then 894 Result[I] := '_'; 895 end; 896 end; 897 898 function TContact.GetProperty(Field: TContactField): TContactProperty; 899 var 900 I: Integer; 901 begin 902 Result := Properties.GetByNameGroups(Field.SysName, Field.Groups, Field.NoGroups); 903 I := 0; 904 while (not Assigned(Result)) and (I < Field.Alternatives.Count) do begin 905 Result := Properties.GetByNameGroups(Field.Alternatives[I].SysName, 906 Field.Alternatives[I].Groups, Field.Alternatives[I].NoGroups); 907 if Assigned(Result) then Break; 908 Inc(I); 909 end; 910 end; 911 912 function TContact.GetProperty(FieldIndex: TContactFieldIndex): TContactProperty; 913 var 914 Field: TContactField; 915 begin 916 if not Assigned(Parent) then raise Exception.Create(SContactHasNoParent); 917 Field := Parent.Fields.GetByIndex(FieldIndex); 918 if Assigned(Field) then begin 919 Result := GetProperty(Field); 920 end else Result := nil; 921 end; 922 923 procedure TContact.Assign(Source: TContact); 924 begin 925 Properties.Assign(Source.Properties); 926 FModified := Source.FModified; 927 end; 928 929 function TContact.UpdateFrom(Source: TContact): Boolean; 930 var 931 I: Integer; 932 begin 933 if not Assigned(Parent) then raise Exception.Create(SContactHasNoParent); 934 Result := False; 935 for I := 0 to Parent.Fields.Count - 1 do begin 936 if (Source.Fields[Parent.Fields[I].Index] <> '') and 937 (Source.Fields[Parent.Fields[I].Index] <> 938 Fields[Parent.Fields[I].Index]) then begin 939 Result := True; 940 Fields[Parent.Fields[I].Index] := Source.Fields[Parent.Fields[I].Index]; 941 end; 942 end; 943 end; 944 945 constructor TContact.Create; 946 begin 947 Properties := TContactProperties.Create; 948 end; 949 950 destructor TContact.Destroy; 951 begin 952 FreeAndNil(Properties); 953 inherited; 954 end; 955 956 procedure TContact.SaveToStrings(Output: TStrings); 957 var 958 I: Integer; 959 NameText: string; 960 Value2: string; 961 LineIndex: Integer; 962 OutText: string; 963 LinePrefix: string; 964 CutLength: Integer; 965 const 966 MaxLineLength = 73; 967 begin 968 with Output do begin 969 Add(VCardBegin); 970 for I := 0 to Properties.Count - 1 do 971 with Properties[I] do begin 972 NameText := Name; 973 if Attributes.Count > 0 then 974 NameText := NameText + ';' + Attributes.DelimitedText; 975 if Encoding <> '' then begin 976 Value2 := GetEncodedValue; 977 NameText := NameText + ';ENCODING=' + Encoding; 978 end else Value2 := Value; 979 if Pos(LineEnding, Value2) > 0 then begin 980 Add(NameText + ':' + GetNext(Value2, LineEnding)); 981 while Pos(LineEnding, Value2) > 0 do begin 982 Add(' ' + GetNext(Value2, LineEnding)); 983 end; 984 Add(' ' + GetNext(Value2, LineEnding)); 985 Add(''); 986 end else begin 987 OutText := NameText + ':' + Value2; 988 LineIndex := 0; 989 LinePrefix := ''; 990 while True do begin 991 if Length(OutText) > MaxLineLength then begin 992 CutLength := MaxLineLength; 993 if Encoding = 'QUOTED-PRINTABLE' then begin 994 // Do not cut encoded items 995 if ((CutLength - 2) >= 1) and (OutText[CutLength - 2] = '=') then 996 Dec(CutLength, 2) 997 else if ((CutLength - 1) >= 1) and (OutText[CutLength - 1] = '=') then 998 Dec(CutLength, 1); 999 end; 1000 Add(LinePrefix + Copy(OutText, 1, CutLength)); 1001 LinePrefix := ' '; 1002 System.Delete(OutText, 1, CutLength); 1003 Inc(LineIndex); 1004 Continue; 1005 end else begin 1006 Add(LinePrefix + OutText); 1007 Break; 1008 end; 1009 end; 1010 if LinePrefix <> '' then Add(''); 1011 end; 1012 end; 1013 Add(VCardEnd); 1014 end; 1015 end; 1016 1017 function TContact.LoadFromStrings(Lines: TStrings; StartLine: Integer = 0): Integer; 1018 type 1019 TParseState = (psNone, psInside, psFinished); 1020 var 1021 ParseState: TParseState; 1022 Line: string; 1023 Value: string; 1024 I: Integer; 1025 NewProperty: TContactProperty; 1026 CommandPart: string; 1027 Names: string; 1028 begin 1029 ParseState := psNone; 1030 I := StartLine; 1031 while I < Lines.Count do begin 1032 Line := Trim(Lines[I]); 1033 if Line = '' then begin 1034 // Skip empty lines 1035 end else 1036 if ParseState = psNone then begin 1037 if Line = VCardBegin then begin 1038 ParseState := psInside; 1039 end else begin 1040 Parent.Error(SExpectedVCardBegin, I + 1); 1041 I := -1; 1042 Break; 1043 end; 1044 end else 1045 if ParseState = psInside then begin 1046 if Line = VCardEnd then begin 1047 ParseState := psFinished; 1048 Inc(I); 1049 Break; 1050 end else 1051 if Pos(':', Line) > 0 then begin 1052 CommandPart := GetNext(Line, ':'); 1053 Names := CommandPart; 1054 Value := Line; 1055 while True do begin 1056 Inc(I); 1057 if (Length(Lines[I]) > 0) and (Lines[I][1] = ' ') then begin 1058 Value := Value + Trim(Lines[I]); 1059 end else 1060 if (Length(Lines[I]) > 0) and (Length(Value) > 0) and (Value[Length(Value)] = '=') and 1061 (Lines[I][1] = '=') then begin 1062 Value := Value + Copy(Trim(Lines[I]), 2, MaxInt); 1063 end else begin 1064 Dec(I); 1065 Break; 1066 end; 1067 end; 1068 NewProperty := Properties.GetByName(Names); 1069 if not Assigned(NewProperty) then begin 1070 NewProperty := TContactProperty.Create; 1071 Properties.Add(NewProperty); 1072 end; 1073 NewProperty.Attributes.DelimitedText := Names; 1074 if NewProperty.Attributes.Count > 0 then begin 1075 NewProperty.Name := NewProperty.Attributes[0]; 1076 NewProperty.Attributes.Delete(0); 1077 end; 1078 NewProperty.Value := Value; 1079 NewProperty.EvaluateAttributes; 1080 end else begin 1081 Parent.Error(SExpectedProperty, I + 1); 1082 I := -1; 1083 Break; 1084 end; 1085 end; 1086 Inc(I); 1087 end; 1088 Result := I; 1089 end; 1090 1091 procedure TContact.SaveToFile(FileName: string); 1092 var 1093 Lines: TStringList; 1094 begin 1095 Lines := TStringList.Create; 1096 try 1097 SaveToStrings(Lines); 1098 Lines.SaveToFile(FileName); 1099 finally 1100 Lines.Free; 1101 end; 1102 end; 1103 1104 procedure TContact.LoadFromFile(FileName: string); 1105 var 1106 Lines: TStringList; 1107 begin 1108 Lines := TStringList.Create; 1109 try 1110 Lines.LoadFromFile(FileName); 1111 {$IF FPC_FULLVERSION>=30200} 1112 if (Length(Lines.Text) > 0) and (Pos(VCardBegin, Lines.Text) = 0) then begin 1113 Lines.LoadFromFile(FileName, TEncoding.Unicode); 1114 if (Length(Lines.Text) > 0) and (Pos(VCardBegin, Lines.Text) = 0) then begin 1115 Lines.LoadFromFile(FileName, TEncoding.BigEndianUnicode); 1116 end; 1117 end; 1118 {$ENDIF} 1119 LoadFromStrings(Lines); 1120 finally 1121 Lines.Free; 1122 end; 1123 end; 1124 1125 { TContactsFile } 1126 1127 procedure TContactsFile.InitFields; 1128 begin 1129 with Fields do begin 825 class function TContact.GetFields: TContactFields; 826 begin 827 if not Assigned(FFields) then begin 828 FFields := TContactFields.Create; 829 with FFields do begin 1130 830 AddNew('VERSION', [], [], SVersion, cfVersion, dtString); 1131 831 AddNew('N', [], [], SLastName, cfLastName, dtString, 0); … … 1230 930 with AddNew('X-MYSPACE', [], [], SMySpace, cfMySpace, dtString) do 1231 931 AddAlternative('X-SOCIALPROFILE', ['MYSPACE'], []); 1232 end; 1233 end; 932 end; 933 end; 934 Result := FFields; 935 end; 936 937 function TContact.GetField(Index: TContactFieldIndex): string; 938 var 939 Prop: TContactProperty; 940 Field: TContactField; 941 begin 942 if not Assigned(ContactsFile) then raise Exception.Create(SContactHasNoParent); 943 Field := GetFields.GetByIndex(Index); 944 if Assigned(Field) then begin 945 Prop := GetProperty(Field); 946 if Assigned(Prop) then begin 947 Field := GetFields.GetByIndex(Index); 948 if Field.ValueIndex <> -1 then begin 949 Result := DecodeEscaped(Prop.ValueItem[Field.ValueIndex]) 950 end else Result := Prop.Value; 951 end else Result := ''; 952 end else raise Exception.Create(SFieldIndexNotDefined); 953 end; 954 955 procedure TContact.SetField(Index: TContactFieldIndex; AValue: string); 956 var 957 Prop: TContactProperty; 958 Field: TContactField; 959 I: Integer; 960 begin 961 if not Assigned(ContactsFile) then raise Exception.Create(SContactHasNoParent); 962 Field := GetFields.GetByIndex(Index); 963 if Assigned(Field) then begin 964 Prop := GetProperty(Field); 965 if (not Assigned(Prop)) and (AValue <> '') then begin 966 Prop := TContactProperty.Create; 967 Prop.Name := Field.SysName; 968 for I := 0 to Length(Field.Groups) - 1 do 969 Prop.Attributes.Add(Field.Groups[I]); 970 Properties.Add(Prop); 971 end; 972 if Assigned(Prop) then begin 973 if Field.ValueIndex <> -1 then begin 974 Prop.ValueItem[Field.ValueIndex] := EncodeEscaped(AValue); 975 end else Prop.Value := AValue; 976 977 // Remove if empty 978 if Prop.Value = '' then begin 979 Properties.Remove(Prop); 980 end; 981 end; 982 Modified := True; 983 end else raise Exception.Create(SFieldIndexNotDefined); 984 end; 985 986 procedure TContact.SetModified(AValue: Boolean); 987 begin 988 if FModified = AValue then Exit; 989 FModified := AValue; 990 DoOnModify; 991 end; 992 993 procedure TContact.DoOnModify; 994 begin 995 if Assigned(FOnModify) then FOnModify(Self); 996 end; 997 998 function TContact.HasField(FieldIndex: TContactFieldIndex): Boolean; 999 var 1000 Field: TContactField; 1001 begin 1002 if not Assigned(ContactsFile) then raise Exception.Create(SContactHasNoParent); 1003 Field := GetFields.GetByIndex(FieldIndex); 1004 if Assigned(Field) then begin 1005 Result := Assigned(GetProperty(Field)); 1006 end else raise Exception.Create(SFieldIndexNotDefined); 1007 end; 1008 1009 function TContact.FullNameToFileName: string; 1010 var 1011 I: Integer; 1012 begin 1013 Result := Fields[cfFullName]; 1014 for I := 1 to Length(Result) do begin 1015 if Result[I] in [':', '/', '\', '.', '"', '*', '|', '?', '<', '>'] then 1016 Result[I] := '_'; 1017 end; 1018 end; 1019 1020 function TContact.GetProperty(Field: TContactField): TContactProperty; 1021 var 1022 I: Integer; 1023 begin 1024 Result := Properties.GetByNameGroups(Field.SysName, Field.Groups, Field.NoGroups); 1025 I := 0; 1026 while (not Assigned(Result)) and (I < Field.Alternatives.Count) do begin 1027 Result := Properties.GetByNameGroups(Field.Alternatives[I].SysName, 1028 Field.Alternatives[I].Groups, Field.Alternatives[I].NoGroups); 1029 if Assigned(Result) then Break; 1030 Inc(I); 1031 end; 1032 end; 1033 1034 function TContact.GetProperty(FieldIndex: TContactFieldIndex): TContactProperty; 1035 var 1036 Field: TContactField; 1037 begin 1038 if not Assigned(ContactsFile) then raise Exception.Create(SContactHasNoParent); 1039 Field := GetFields.GetByIndex(FieldIndex); 1040 if Assigned(Field) then begin 1041 Result := GetProperty(Field); 1042 end else Result := nil; 1043 end; 1044 1045 procedure TContact.Assign(Source: TContact); 1046 begin 1047 Properties.Assign(Source.Properties); 1048 FModified := Source.FModified; 1049 end; 1050 1051 function TContact.UpdateFrom(Source: TContact): Boolean; 1052 var 1053 I: Integer; 1054 begin 1055 if not Assigned(ContactsFile) then raise Exception.Create(SContactHasNoParent); 1056 Result := False; 1057 for I := 0 to GetFields.Count - 1 do begin 1058 if (Source.Fields[GetFields[I].Index] <> '') and 1059 (Source.Fields[GetFields[I].Index] <> 1060 Fields[GetFields[I].Index]) then begin 1061 Result := True; 1062 Fields[GetFields[I].Index] := Source.Fields[GetFields[I].Index]; 1063 end; 1064 end; 1065 end; 1066 1067 constructor TContact.Create; 1068 begin 1069 Properties := TContactProperties.Create; 1070 end; 1071 1072 destructor TContact.Destroy; 1073 begin 1074 FreeAndNil(Properties); 1075 inherited; 1076 end; 1077 1078 class destructor TContact.Destroy; 1079 begin 1080 FreeAndNil(FFields); 1081 end; 1082 1083 procedure TContact.SaveToStrings(Output: TStrings); 1084 var 1085 I: Integer; 1086 NameText: string; 1087 Value2: string; 1088 LineIndex: Integer; 1089 OutText: string; 1090 LinePrefix: string; 1091 CutLength: Integer; 1092 const 1093 MaxLineLength = 73; 1094 begin 1095 with Output do begin 1096 Add(VCardBegin); 1097 for I := 0 to Properties.Count - 1 do 1098 with Properties[I] do begin 1099 NameText := Name; 1100 if Attributes.Count > 0 then 1101 NameText := NameText + ';' + Attributes.DelimitedText; 1102 if Encoding <> '' then begin 1103 Value2 := GetEncodedValue; 1104 NameText := NameText + ';ENCODING=' + Encoding; 1105 end else Value2 := Value; 1106 if Pos(LineEnding, Value2) > 0 then begin 1107 Add(NameText + ':' + GetNext(Value2, LineEnding)); 1108 while Pos(LineEnding, Value2) > 0 do begin 1109 Add(' ' + GetNext(Value2, LineEnding)); 1110 end; 1111 Add(' ' + GetNext(Value2, LineEnding)); 1112 Add(''); 1113 end else begin 1114 OutText := NameText + ':' + Value2; 1115 LineIndex := 0; 1116 LinePrefix := ''; 1117 while True do begin 1118 if Length(OutText) > MaxLineLength then begin 1119 CutLength := MaxLineLength; 1120 if Encoding = 'QUOTED-PRINTABLE' then begin 1121 // Do not cut encoded items 1122 if ((CutLength - 2) >= 1) and (OutText[CutLength - 2] = '=') then 1123 Dec(CutLength, 2) 1124 else if ((CutLength - 1) >= 1) and (OutText[CutLength - 1] = '=') then 1125 Dec(CutLength, 1); 1126 end; 1127 Add(LinePrefix + Copy(OutText, 1, CutLength)); 1128 LinePrefix := ' '; 1129 System.Delete(OutText, 1, CutLength); 1130 Inc(LineIndex); 1131 Continue; 1132 end else begin 1133 Add(LinePrefix + OutText); 1134 Break; 1135 end; 1136 end; 1137 if LinePrefix <> '' then Add(''); 1138 end; 1139 end; 1140 Add(VCardEnd); 1141 end; 1142 end; 1143 1144 function TContact.LoadFromStrings(Lines: TStrings; StartLine: Integer = 0): Integer; 1145 type 1146 TParseState = (psNone, psInside, psFinished); 1147 var 1148 ParseState: TParseState; 1149 Line: string; 1150 Value: string; 1151 I: Integer; 1152 NewProperty: TContactProperty; 1153 CommandPart: string; 1154 Names: string; 1155 begin 1156 ParseState := psNone; 1157 I := StartLine; 1158 while I < Lines.Count do begin 1159 Line := Trim(Lines[I]); 1160 if Line = '' then begin 1161 // Skip empty lines 1162 end else 1163 if ParseState = psNone then begin 1164 if Line = VCardBegin then begin 1165 ParseState := psInside; 1166 end else begin 1167 ContactsFile.Error(SExpectedVCardBegin, I + 1); 1168 I := -1; 1169 Break; 1170 end; 1171 end else 1172 if ParseState = psInside then begin 1173 if Line = VCardEnd then begin 1174 ParseState := psFinished; 1175 Inc(I); 1176 Break; 1177 end else 1178 if Pos(':', Line) > 0 then begin 1179 CommandPart := GetNext(Line, ':'); 1180 Names := CommandPart; 1181 Value := Line; 1182 while True do begin 1183 Inc(I); 1184 if (Length(Lines[I]) > 0) and (Lines[I][1] = ' ') then begin 1185 Value := Value + Trim(Lines[I]); 1186 end else 1187 if (Length(Lines[I]) > 0) and (Length(Value) > 0) and (Value[Length(Value)] = '=') and 1188 (Lines[I][1] = '=') then begin 1189 Value := Value + Copy(Trim(Lines[I]), 2, MaxInt); 1190 end else begin 1191 Dec(I); 1192 Break; 1193 end; 1194 end; 1195 NewProperty := Properties.GetByName(Names); 1196 if not Assigned(NewProperty) then begin 1197 NewProperty := TContactProperty.Create; 1198 Properties.Add(NewProperty); 1199 end; 1200 NewProperty.Attributes.DelimitedText := Names; 1201 if NewProperty.Attributes.Count > 0 then begin 1202 NewProperty.Name := NewProperty.Attributes[0]; 1203 NewProperty.Attributes.Delete(0); 1204 end; 1205 NewProperty.Value := Value; 1206 NewProperty.EvaluateAttributes; 1207 end else begin 1208 ContactsFile.Error(SExpectedProperty, I + 1); 1209 I := -1; 1210 Break; 1211 end; 1212 end; 1213 Inc(I); 1214 end; 1215 Result := I; 1216 end; 1217 1218 procedure TContact.SaveToFile(FileName: string); 1219 var 1220 Lines: TStringList; 1221 begin 1222 Lines := TStringList.Create; 1223 try 1224 SaveToStrings(Lines); 1225 Lines.SaveToFile(FileName); 1226 finally 1227 Lines.Free; 1228 end; 1229 end; 1230 1231 procedure TContact.LoadFromFile(FileName: string); 1232 var 1233 Lines: TStringList; 1234 begin 1235 Lines := TStringList.Create; 1236 try 1237 Lines.LoadFromFile(FileName); 1238 {$IF FPC_FULLVERSION>=30200} 1239 if (Length(Lines.Text) > 0) and (Pos(VCardBegin, Lines.Text) = 0) then begin 1240 Lines.LoadFromFile(FileName, TEncoding.Unicode); 1241 if (Length(Lines.Text) > 0) and (Pos(VCardBegin, Lines.Text) = 0) then begin 1242 Lines.LoadFromFile(FileName, TEncoding.BigEndianUnicode); 1243 end; 1244 end; 1245 {$ENDIF} 1246 LoadFromStrings(Lines); 1247 finally 1248 Lines.Free; 1249 end; 1250 end; 1251 1252 { TContactsFile } 1234 1253 1235 1254 procedure TContactsFile.Error(Text: string; Line: Integer); … … 1272 1291 while I < Lines.Count do begin 1273 1292 Contact := TContact.Create; 1274 Contact. Parent:= Self;1293 Contact.ContactsFile := Self; 1275 1294 NewI := Contact.LoadFromStrings(Lines, I); 1276 1295 if NewI <= Lines.Count then begin … … 1339 1358 Contacts := TContacts.Create; 1340 1359 Contacts.ContactsFile := Self; 1341 Fields := TContactFields.Create;1342 InitFields;1343 1360 end; 1344 1361 1345 1362 destructor TContactsFile.Destroy; 1346 1363 begin 1347 FreeAndNil(Fields);1348 1364 FreeAndNil(Contacts); 1349 1365 inherited; -
trunk/UCore.lfm
r79 r82 498 498 Images = ImageList1 499 499 Left = 384 500 Top = 20 2500 Top = 200 501 501 object AExit: TAction 502 502 Caption = 'Exit' -
trunk/UCore.pas
r76 r82 83 83 GenerateCount: Integer; 84 84 ToolbarVisible: Boolean; 85 DefaultVcardVersion: string; 85 86 function GetProfileImage: TImage; 86 87 procedure FileNew; … … 453 454 LastPropertyValueFileName := ReadStringWithDefault('LastPropertyValueFileName', ''); 454 455 GenerateCount := ReadIntegerWithDefault('GenerateCount', 1); 456 DefaultVcardVersion := ReadStringWithDefault('DefaultVcardVersion', '2.1'); 455 457 finally 456 458 Free; … … 479 481 WriteString('LastPropertyValueFileName', LastPropertyValueFileName); 480 482 WriteInteger('GenerateCount', GenerateCount); 483 WriteString('DefaultVcardVersion', DefaultVcardVersion); 481 484 finally 482 485 Free; … … 506 509 AFileSplit.Enabled := Assigned(DataFile); 507 510 AFileCombine.Enabled := Assigned(DataFile); 511 AFind.Enabled := Assigned(DataFile); 508 512 AFindDuplicate.Enabled := Assigned(DataFile); 509 513 AGenerate.Enabled := Assigned(DataFile); … … 525 529 LastOpenedList1.AddItem(FileNameOption); 526 530 end else 527 if (LastOpenedList1.Items.Count > 0) and FileExists(LastOpenedList1.Items[0]) then begin531 if ReopenLastFileOnStart and (LastOpenedList1.Items.Count > 0) and FileExists(LastOpenedList1.Items[0]) then begin 528 532 // Open last opened file 529 533 AFileNew.Execute;
Note:
See TracChangeset
for help on using the changeset viewer.