Componentes.Terceros.jvcl/official/3.36/run/JvPropertyStore.pas
2009-02-27 12:23:32 +00:00

1238 lines
38 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvPropertyStore.pas, released on 2003-11-13.
The Initial Developer of the Original Code is Jens Fudickar
Portions created by Marcel Bestebroer are Copyright (C) 2003 Jens Fudickar
All Rights Reserved.
Contributor(s):
Marcel Bestebroer
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvPropertyStore.pas 12073 2008-12-12 23:46:18Z jfudickar $
unit JvPropertyStore;
{$I jvcl.inc}
interface
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
Classes,
JvAppStorage, JvComponentBase, JvPropertyStoreEditorIntf;
type
TJvIgnorePropertiesStringList = class(TStringList)
public
constructor Create;
procedure AddDelete(AItem: string; ADelete: Boolean);
end;
TJvCustomPropertyStoreClass = class of TJvCustomPropertyStore;
TJvCustomPropertyStore = class(TJvComponent, IJvPropertyEditorHandler)
private
FAppStoragePath: string;
FAppStorage: TJvCustomAppStorage;
FEnabled: Boolean;
FReadOnly: Boolean;
FDeleteBeforeStore: Boolean;
FClearBeforeLoad: Boolean;
FIntIgnoreProperties: TStringList;
FIgnoreProperties: TJvIgnorePropertiesStringList;
FAutoLoad: Boolean;
FLastLoadTime: TDateTime;
FIgnoreLastLoadTime: Boolean;
FCombinedIgnoreProperties: TStringList;
FOnBeforeLoadProperties: TNotifyEvent;
FOnAfterLoadProperties: TNotifyEvent;
FOnBeforeStoreProperties: TNotifyEvent;
FOnAfterStoreProperties: TNotifyEvent;
FSynchronizeStoreProperties: Boolean;
FSynchronizeLoadProperties: Boolean;
procedure SetAutoLoad(Value: Boolean);
function GetIgnoreProperties: TJvIgnorePropertiesStringList;
procedure SetIgnoreProperties(Value: TJvIgnorePropertiesStringList);
function GetLastSaveTime: TDateTime;
function GetPropCount(Instance: TPersistent): Integer;
function GetPropertyCount: Integer;
function GetPropertyName(Index: Integer): string;
function GetPropName(Instance: TPersistent; Index: Integer): string;
protected
procedure CloneClassProperties(Src, Dest: TPersistent); virtual;
procedure UpdateChildPaths(OldPath: string = ''); virtual;
procedure SetAppstoragePath(Value: string); virtual;
procedure SetAppStorage(Value: TJvCustomAppStorage); virtual;
procedure Loaded; override;
procedure DisableAutoLoadDown;
procedure LoadData; virtual;
procedure StoreData; virtual;
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
function GetCombinedIgnoreProperties: TStringList;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure StoreProperties; virtual;
procedure LoadProperties; virtual;
procedure Assign(Source: TPersistent); override;
procedure Clear; virtual;
function IgnoreProperty(const PropertyName: string): Boolean;
//1 // This function defines, if the properties should be stored in this moment
function StorePropertiesNow: Boolean; virtual;
function TranslatePropertyName(AName: string): string; virtual;
property AppStorage: TJvCustomAppStorage read FAppStorage write
SetAppStorage;
property CombinedIgnoreProperties: TStringList read
GetCombinedIgnoreProperties;
property IgnoreProperties: TJvIgnorePropertiesStringList read
GetIgnoreProperties write SetIgnoreProperties;
property AutoLoad: Boolean read FAutoLoad write SetAutoLoad;
property AppStoragePath: string read FAppStoragePath write
SetAppstoragePath;
property Enabled: Boolean read FEnabled write FEnabled default True;
property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
property DeleteBeforeStore: Boolean read FDeleteBeforeStore write
FDeleteBeforeStore default False;
property ClearBeforeLoad: Boolean read FClearBeforeLoad write
FClearBeforeLoad default False;
property IgnoreLastLoadTime: Boolean read FIgnoreLastLoadTime write
FIgnoreLastLoadTime default False;
property OnBeforeLoadProperties: TNotifyEvent read FOnBeforeLoadProperties
write FOnBeforeLoadProperties;
property OnAfterLoadProperties: TNotifyEvent read FOnAfterLoadProperties
write FOnAfterLoadProperties;
property OnBeforeStoreProperties: TNotifyEvent read FOnBeforeStoreProperties
write FOnBeforeStoreProperties;
property OnAfterStoreProperties: TNotifyEvent read FOnAfterStoreProperties
write FOnAfterStoreProperties;
property PropertyCount: Integer read GetPropertyCount;
property PropertyName[Index: Integer]: string read GetPropertyName;
//1 Synchronize the StoreProperties procedure
/// Defines if the execution of the StoreProperties procedure for the current
/// AppStoragePath should be synchronized via a global mutex
/// When the SynchronizeLoadProperties is also definde the load and store
/// procedures will be synched with the same mutex.
property SynchronizeStoreProperties: Boolean read FSynchronizeStoreProperties
write FSynchronizeStoreProperties default False;
//1 Synchronize the LoadProperties procedure
/// Defines if the execution of the LoadProperties procedure for the current
/// AppStoragePath should be synchronized via a global mutex.
/// When the SynchronizeStoreProperties is also definde the load and store
/// procedures will be synched with the same mutex.
property SynchronizeLoadProperties: Boolean read FSynchronizeLoadProperties
write FSynchronizeLoadProperties default False;
property Tag;
//1 Creates a new instance of the same objecttype and assigns the property contents to the new instance
function Clone(AOwner: TComponent): TJvCustomPropertyStore;
//IJvPropertyEditorHandler = interface
function EditIntf_GetVisibleObjectName: string; virtual;
function EditIntf_TranslatePropertyName(const PropertyName: string): string;
virtual;
function EditIntf_DisplayProperty(const PropertyName: string): Boolean; virtual;
function EditIntf_GetObjectHint: string; virtual;
function EditIntf_GetPropertyHint(const PropertyName: string): string;
virtual;
function EditIntf_IsPropertySimple(const PropertyName: string): Boolean;
virtual;
end;
TJvCustomPropertyListStore = class(TJvCustomPropertyStore,
IJvPropertyListEditorHandler)
private
FItems: TStringList;
FFreeObjects: Boolean;
FCreateListEntries: Boolean;
FItemName: string;
FItemsObjectName: string;
function GetItems: TStringList;
protected
function GetString(Index: Integer): string;
function GetObject(Index: Integer): TObject;
procedure SetString(Index: Integer; Value: string);
procedure SetObject(Index: Integer; Value: TObject);
function GetCount: Integer;
procedure ReadSLOItem(Sender: TJvCustomAppStorage; const Path: string;
const List: TObject; const Index: Integer; const ItemName: string);
procedure WriteSLOItem(Sender: TJvCustomAppStorage; const Path: string;
const List: TObject; const Index: Integer; const ItemName: string);
procedure DeleteSLOItems(Sender: TJvCustomAppStorage; const Path: string;
const List: TObject; const First, Last: Integer; const ItemName: string);
function CreateItemList: TStringList; virtual;
function CreateObject: TPersistent; virtual; abstract;
function GetSorted: Boolean;
procedure SetSorted(Value: Boolean);
function GetDuplicates: TDuplicates;
procedure SetDuplicates(Value: TDuplicates);
procedure StoreData; override;
procedure LoadData; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear; override;
function IndexOf(const s: string): Integer;
function IndexOfObject(AObject: TObject): Integer;
property Strings[Index: Integer]: string read GetString write SetString;
property Objects[Index: Integer]: TObject read GetObject write SetObject;
property Items: TStringList read GetItems;
property Count: Integer read GetCount;
{ Defines if the Items.Objects- Objects will be freed inside the clear procedure }
property FreeObjects: Boolean read FFreeObjects write FFreeObjects default
True;
{ Defines if new List entries will be created if there are stored entries, which
are not in the current object }
property CreateListEntries: Boolean read FCreateListEntries write
FCreateListEntries default True;
property ItemName: string read FItemName write FItemName;
//1 Name to read the value of the object from the appstorage path
/// Using this path addition the internal name of the object is read from
/// the appstorage.
/// This property is necessary only for the xml appstorage.
/// When in this case the property is not defined the internal items string
/// value couldn't be recovered from the appstorage (out of xml
/// restrictions with array elements)
property ItemsObjectName: string read FItemsObjectName write FItemsObjectName;
property Sorted: Boolean read GetSorted write SetSorted;
function CreateAddObject(const aObjectName: String): TPersistent;
//IJvPropertyListEditorHandler = interface
function ListEditIntf_ObjectCount: integer;
function ListEditIntf_GetObject(Index: integer): TPersistent;
procedure ListEditIntf_MoveObjectPosition(CurIndex, NewIndex: Integer);
function ListEditIntf_CreateNewObject: TPersistent;
function ListEditIntf_CloneNewObject(Index: integer): TPersistent;
procedure ListEditIntf_DeleteObject(Index: integer);
end;
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile:
'$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/branches/JVCL3_36_PREPARATION/run/JvPropertyStore.pas $';
Revision: '$Revision: 12073 $';
Date: '$Date: 2008-12-13 00:46:18 +0100 (sam., 13 déc. 2008) $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
implementation
uses
{$IFDEF HAS_UNIT_RTLCONSTS}
RTLConsts,
{$ENDIF HAS_UNIT_RTLCONSTS}
Consts, SysUtils, TypInfo,
JclSynch,
JvStrings, JvResources;
const
cLastSaveTime = 'Last Save Time';
cObject = 'Object';
cItem = 'Item';
//=== { TCombinedStrings } ===================================================
type
// Read-only TStrings combining multiple TStrings instances in a single list
TCombinedStrings = class(TStringList)
private
FList: TList;
protected
function Get(Index: Integer): string; override;
function GetObject(Index: Integer): TObject; override;
function GetCount: Integer; override;
public
constructor Create;
destructor Destroy; override;
procedure AddStrings(Strings: TStrings); override;
// procedure DeleteStrings(Strings: TStrings);
procedure Clear; override;
procedure Delete(Index: Integer); override;
procedure Insert(Index: Integer; const S: string); override;
end;
constructor TCombinedStrings.Create;
begin
inherited Create;
Sorted := True;
FList := TList.Create;
end;
destructor TCombinedStrings.Destroy;
begin
FreeAndNil(FList);
inherited Destroy;
end;
function TCombinedStrings.Get(Index: Integer): string;
var
OrgIndex: Integer;
I: Integer;
begin
OrgIndex := Index;
I := 0;
if Index < 0 then
Error(SListIndexError, Index);
while (I < FList.Count) and (Index >= TStrings(FList[I]).Count) do
begin
Dec(Index, TStrings(FList[I]).Count);
Inc(I);
end;
if I >= FList.Count then
Error(SListIndexError, OrgIndex);
Result := TStrings(FList[I])[Index];
end;
function TCombinedStrings.GetObject(Index: Integer): TObject;
var
OrgIndex: Integer;
I: Integer;
begin
OrgIndex := Index;
I := 0;
if Index < 0 then
Error(SListIndexError, Index);
while (Index < TStrings(FList[I]).Count) and (I < FList.Count) do
begin
Dec(Index, TStrings(FList[I]).Count);
Inc(I);
end;
if I >= FList.Count then
Error(SListIndexError, OrgIndex);
Result := TStrings(FList[I]).Objects[Index];
end;
function TCombinedStrings.GetCount: Integer;
var
I: Integer;
begin
Result := 0;
for I := 0 to FList.Count - 1 do
Inc(Result, TStrings(FList[I]).Count);
end;
procedure TCombinedStrings.AddStrings(Strings: TStrings);
begin
if FList.IndexOf(Strings) = -1 then
FList.Add(Strings);
end;
(*
procedure TCombinedStrings.DeleteStrings(Strings: TStrings);
begin
FList.Remove(Strings);
end;
*)
procedure TCombinedStrings.Clear;
begin
FList.Clear;
end;
procedure TCombinedStrings.Delete(Index: Integer);
begin
end;
procedure TCombinedStrings.Insert(Index: Integer; const S: string);
begin
end;
constructor TJvIgnorePropertiesStringList.Create;
begin
inherited Create;
Sorted := True;
end;
//=== { TJvIgnorePropertiesStringList } ======================================
procedure TJvIgnorePropertiesStringList.AddDelete(AItem: string; ADelete:
Boolean);
begin
if ADelete then
begin
if IndexOf(AItem) >= 0 then
Delete(IndexOf(AItem));
end
else
begin
if IndexOf(AItem) < 0 then
Add(AItem);
end;
end;
//=== { TJvCustomPropertyStore } =============================================
constructor TJvCustomPropertyStore.Create(AOwner: TComponent);
const
IgnorePropertyList: array[1..18] of string =
(
'AboutJVCL',
'AppStorage',
'AppStoragePath',
'AutoLoad',
'ClearBeforeLoad',
'Name',
'Tag',
'Enabled',
'ReadOnly',
'DeleteBeforeStore',
'IgnoreLastLoadTime',
'IgnoreProperties',
'OnBeforeLoadProperties',
'OnAfterLoadProperties',
'OnBeforeStoreProperties',
'OnAfterStoreProperties',
'SynchronizeLoadProperties',
'SynchronizeStoreProperties'
);
var
I: Integer;
begin
inherited Create(AOwner);
FLastLoadTime := Now;
FAppStorage := nil;
FEnabled := True;
FReadOnly := False;
FDeleteBeforeStore := False;
FAutoLoad := False;
FIntIgnoreProperties := TStringList.Create;
FIgnoreProperties := TJvIgnorePropertiesStringList.Create;
FIgnoreLastLoadTime := False;
FCombinedIgnoreProperties := TCombinedStrings.Create;
for I := Low(IgnorePropertyList) to High(IgnorePropertyList) do
FIntIgnoreProperties.Add(IgnorePropertyList[I]);
FSynchronizeStoreProperties := False;
FSynchronizeLoadProperties := False;
end;
destructor TJvCustomPropertyStore.Destroy;
begin
if not (csDesigning in ComponentState) then
if AutoLoad then
StoreProperties;
FreeAndNil(FCombinedIgnoreProperties);
FreeAndNil(FIntIgnoreProperties);
FreeAndNil(FIgnoreProperties);
Clear;
inherited Destroy;
end;
procedure TJvCustomPropertyStore.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = FAppStorage) then
FAppStorage := nil;
end;
function TJvCustomPropertyStore.GetCombinedIgnoreProperties: TStringList;
var
I: Integer;
begin
FCombinedIgnoreProperties.clear;
for I := 0 to FIntIgnoreProperties.Count - 1 do
FCombinedIgnoreProperties.Add(FIntIgnoreProperties[i]);
for I := 0 to FIgnoreProperties.Count - 1 do
FCombinedIgnoreProperties.Add(FIgnoreProperties[i]);
Result := FCombinedIgnoreProperties;
end;
function TJvCustomPropertyStore.GetPropCount(Instance: TPersistent): Integer;
var
Data: PTypeData;
begin
Data := GetTypeData(Instance.ClassInfo);
Result := Data.PropCount;
end;
function TJvCustomPropertyStore.GetPropName(Instance: TPersistent; Index:
Integer): string;
var
PropList: PPropList;
PropInfo: PPropInfo;
Data: PTypeData;
begin
Result := '';
Data := GetTypeData(Instance.ClassInfo);
{$IFDEF CLR}
PropList := GetPropInfos(Instance.ClassInfo);
PropInfo := PropList[Index];
Result := PropInfo.Name;
{$ELSE}
GetMem(PropList, Data^.PropCount * SizeOf(PPropInfo));
try
GetPropInfos(Instance.ClassInfo, PropList);
PropInfo := PropList^[Index];
Result := {$IFDEF SUPPORTS_UNICODE}UTF8ToString{$ENDIF SUPPORTS_UNICODE}(PropInfo^.Name);
finally
FreeMem(PropList, Data^.PropCount * SizeOf(PPropInfo));
end;
{$ENDIF CLR}
end;
procedure TJvCustomPropertyStore.CloneClassProperties(Src, Dest: TPersistent);
var
Index: Integer;
SrcPropInfo: PPropInfo;
DestPropInfo: PPropInfo;
function GetPropKind(PropInfo: PPropInfo): TTypeKind;
begin
{$IFDEF CLR}
Result := PropInfo.TypeKind;
{$ELSE}
Result := PropInfo.PropType^.Kind;
{$ENDIF CLR}
end;
begin
for Index := 0 to GetPropCount(Src) - 1 do
if CompareText(GetPropName(Src, Index), 'Name') <> 0 then
begin
SrcPropInfo := GetPropInfo(Src.ClassInfo, GetPropName(Src, Index));
DestPropInfo := GetPropInfo(Dest.ClassInfo, GetPropName(Src, Index));
if (DestPropInfo <> nil) and (GetPropKind(DestPropInfo) =
GetPropKind(SrcPropInfo)) then
case GetPropKind(DestPropInfo) of
{$IFDEF UNICODE} tkUString, {$ENDIF}
tkLString, tkString:
SetStrProp(Dest, DestPropInfo, GetStrProp(Src, SrcPropInfo));
tkInteger, tkChar, tkEnumeration, tkSet:
SetOrdProp(Dest, DestPropInfo, GetOrdProp(Src, SrcPropInfo));
tkFloat:
SetFloatProp(Dest, DestPropInfo, GetFloatProp(Src, SrcPropInfo));
tkVariant:
SetVariantProp(Dest, DestPropInfo, GetVariantProp(Src,
SrcPropInfo));
tkClass:
if GetObjectProp(Src, SrcPropInfo) is TPersistent then
TPersistent(GetObjectProp(Dest,
DestPropInfo)).Assign(TPersistent(GetObjectProp(Src,
SrcPropInfo)));
tkMethod:
SetMethodProp(Dest, DestPropInfo, GetMethodProp(Src, SrcPropInfo));
end;
end;
end;
procedure TJvCustomPropertyStore.Loaded;
begin
inherited Loaded;
if not (csDesigning in ComponentState) then
if AutoLoad then
LoadProperties;
end;
procedure TJvCustomPropertyStore.Assign(Source: TPersistent);
begin
if Source is Self.ClassType then
CloneClassProperties(Source, Self)
else
inherited Assign(Source);
end;
procedure TJvCustomPropertyStore.Clear;
begin
end;
function TJvCustomPropertyStore.Clone(AOwner: TComponent):
TJvCustomPropertyStore;
begin
Result := TJvCustomPropertyStoreClass(ClassType).Create(AOwner);
Result.Assign(Self);
end;
function TJvCustomPropertyStore.TranslatePropertyName(AName: string): string;
begin
Result := AName;
end;
procedure TJvCustomPropertyStore.SetAutoLoad(Value: Boolean);
begin
if not Assigned(Owner) then
Exit;
if Owner is TJvCustomPropertyStore then
FAutoLoad := False
else if Value <> AutoLoad then
FAutoLoad := Value;
end;
procedure TJvCustomPropertyStore.DisableAutoLoadDown;
var
Index: Integer;
PropName: string;
begin
for Index := 0 to GetPropCount(Self) - 1 do
begin
PropName := GetPropName(Self, Index);
if not IgnoreProperty(PropName) then
if PropType(Self, GetPropName(Self, Index)) = tkClass then
if (TPersistent(GetObjectProp(Self, PropName)) is TJvCustomPropertyStore)
then
TJvCustomPropertyStore(TPersistent(GetObjectProp(Self,
PropName))).AutoLoad := False;
end;
end;
function TJvCustomPropertyStore.EditIntf_DisplayProperty(const PropertyName:
string): Boolean;
begin
Result := not (IgnoreProperty(PropertyName));
end;
function TJvCustomPropertyStore.EditIntf_GetObjectHint: string;
begin
Result := '';
end;
function TJvCustomPropertyStore.EditIntf_GetPropertyHint(const PropertyName:
string): string;
begin
Result := '';
end;
function TJvCustomPropertyStore.EditIntf_GetVisibleObjectName: string;
begin
Result := '';
end;
function TJvCustomPropertyStore.EditIntf_IsPropertySimple(const PropertyName:
string): Boolean;
var
I: Integer;
begin
if PropertyName = '' then
begin
Result := true;
for I := 0 to GetPropCount(Self) - 1 do
if EditIntf_DisplayProperty(GetPropName(Self, I)) then
begin
Result := EditIntf_IsPropertySimple(GetPropName(Self, I));
if not Result then
Exit;
end;
end
else if IsPublishedProp(Self, PropertyName) and (PropType(Self, PropertyName) = tkClass) then
if (TPersistent(GetObjectProp(Self, PropertyName)) is
TJvCustomPropertyListStore) then
Result := False
else if (TPersistent(GetObjectProp(Self, PropertyName)) is
TJvCustomPropertyStore) then
Result := TJvCustomPropertyStore(GetObjectProp(Self,
PropertyName)).EditIntf_IsPropertySimple('')
else
Result := True
else
Result := True;
end;
function TJvCustomPropertyStore.EditIntf_TranslatePropertyName(const
PropertyName: string): string;
var
s: string;
I: Integer;
c: string;
lastLower: Boolean;
begin
s := '';
LastLower := False;
for I := 1 to Length(PropertyName) do
begin
c := Copy(PropertyName, i, 1);
if (c = Uppercase(c)) then
begin
if LastLower then
s := s + ' ' + c
else
s := s + c;
LastLower := False;
end
else if (c = '_') or (c = '.') then
begin
s := s + ' ';
LastLower := False;
end
else
begin
s := s + c;
LastLower := true;
end
end;
Result := s;
end;
procedure TJvCustomPropertyStore.UpdateChildPaths(OldPath: string);
var
Index: Integer;
VisPropName: string;
PropName: string;
PropertyStore: TJvCustomPropertyStore;
begin
if Assigned(AppStorage) then
begin
if OldPath = '' then
OldPath := AppStoragePath;
for Index := 0 to GetPropCount(Self) - 1 do
begin
PropName := GetPropName(Self, Index);
if PropType(Self, PropName) = tkClass then
if (TPersistent(GetObjectProp(Self, PropName)) is
TJvCustomPropertyStore) then
if not IgnoreProperty(PropName) then
begin
VisPropName := AppStorage.TranslatePropertyName(Self, PropName, False);
PropertyStore :=
TJvCustomPropertyStore(TPersistent(GetObjectProp(Self, PropName)));
if (PropertyStore.AppStoragePath = AppStorage.ConcatPaths([OldPath,
VisPropName])) or
(PropertyStore.AppStoragePath = '') then
PropertyStore.AppStoragePath :=
AppStorage.ConcatPaths([AppStoragePath, VisPropName]);
end;
end;
end;
end;
procedure TJvCustomPropertyStore.SetAppstoragePath(Value: string);
var
OldPath: string;
begin
OldPath := FAppStoragePath;
if Value <> AppStoragePath then
FAppStoragePath := Value;
UpdateChildPaths(OldPath);
end;
procedure TJvCustomPropertyStore.SetAppStorage(Value: TJvCustomAppStorage);
var
Index: Integer;
PropName: string;
begin
if Value <> FAppStorage then
begin
for Index := 0 to GetPropCount(Self) - 1 do
begin
PropName := GetPropName(Self, Index);
if not IgnoreProperty(PropName) then
if PropType(Self, PropName) = tkClass then
if (TPersistent(GetObjectProp(Self, PropName)) is
TJvCustomPropertyStore) then
TJvCustomPropertyStore(TPersistent(GetObjectProp(Self,
PropName))).AppStorage := Value;
end;
FAppStorage := Value;
UpdateChildPaths;
end;
end;
function TJvCustomPropertyStore.GetIgnoreProperties:
TJvIgnorePropertiesStringList;
begin
Result := FIgnoreProperties;
end;
procedure TJvCustomPropertyStore.SetIgnoreProperties(Value:
TJvIgnorePropertiesStringList);
begin
FIgnoreProperties.Assign(Value);
end;
function TJvCustomPropertyStore.GetLastSaveTime: TDateTime;
begin
Result := 0;
if not Enabled then
Exit;
if AppStoragePath = '' then
Exit;
try
if AppStorage.ValueStored(AppStorage.ConcatPaths([AppStoragePath,
cLastSaveTime])) then
Result := AppStorage.ReadDateTime(AppStorage.ConcatPaths([AppStoragePath,
cLastSaveTime]));
except
Result := 0;
end;
end;
function TJvCustomPropertyStore.GetPropertyCount: Integer;
begin
Result := GetPropCount(self);
end;
function TJvCustomPropertyStore.GetPropertyName(Index: Integer): string;
begin
Result := GetPropName(Self, Index);
end;
function TJvCustomPropertyStore.IgnoreProperty(const PropertyName: string):
Boolean;
begin
Result := (IgnoreProperties.IndexOf(PropertyName) >= 0) or
(FIntIgnoreProperties.IndexOf(PropertyName) >= 0);
end;
procedure TJvCustomPropertyStore.LoadProperties;
var
Mutex: TJclMutex;
procedure ExecuteLoadProperties;
begin
AppStorage.BeginUpdate;
try
UpdateChildPaths;
FLastLoadTime := Now;
if ClearBeforeLoad then
Clear;
if Assigned(FOnBeforeLoadProperties) then
FOnBeforeLoadProperties(Self);
LoadData;
AppStorage.ReadPersistent(AppStoragePath, Self, True, True,
CombinedIgnoreProperties);
if Assigned(FOnAfterLoadProperties) then
FOnAfterLoadProperties(Self);
finally
AppStorage.EndUpdate;
end;
end;
begin
if not Enabled then
Exit;
if not Assigned(AppStorage) then
Exit;
if SynchronizeLoadProperties then
begin
if SynchronizeStoreProperties then
Mutex := TJclMutex.Create(nil, False,
string(B64Encode(AnsiString(RsJvPropertyStoreMutexLoadStorePropertiesProcedureName +
AppStoragePath))))
else
Mutex := TJclMutex.Create(nil, False,
string(B64Encode(AnsiString(RsJvPropertyStoreMutexLoadPropertiesProcedureName +
AppStoragePath))));
try
if Mutex.WaitForever = wrSignaled then
try
ExecuteLoadProperties;
finally
Mutex.Release;
end
else
raise
Exception.CreateResFmt({$IFNDEF CLR}@{$ENDIF}RsJvPropertyStoreEnterMutexTimeout, [RsJvPropertyStoreMutexStorePropertiesProcedureName]);
finally
FreeAndNil(Mutex);
end;
end
else
ExecuteLoadProperties;
end;
procedure TJvCustomPropertyStore.StoreProperties;
var
SaveProperties: Boolean;
Mutex: TJclMutex;
procedure ExecuteStoreProperties;
begin
AppStorage.BeginUpdate;
try
UpdateChildPaths;
DisableAutoLoadDown;
SaveProperties := IgnoreLastLoadTime or (GetLastSaveTime < FLastLoadTime);
if SaveProperties then
begin
if DeleteBeforeStore then
AppStorage.DeleteSubTree(AppStoragePath);
if StorePropertiesNow then
begin
if not IgnoreLastLoadTime then
AppStorage.WriteString(AppStorage.ConcatPaths([AppStoragePath,
cLastSaveTime]), DateTimeToStr(Now));
if Assigned(FOnBeforeStoreProperties) then
FOnBeforeStoreProperties(Self);
if SaveProperties then
StoreData;
AppStorage.WritePersistent(AppStoragePath, Self, True,
CombinedIgnoreProperties);
if Assigned(FOnAfterStoreProperties) then
FOnAfterStoreProperties(Self);
end;
end;
finally
AppStorage.EndUpdate;
end;
end;
begin
if not Enabled then
Exit;
if ReadOnly then
Exit;
if not Assigned(AppStorage) then
Exit;
if SynchronizeStoreProperties then
begin
if SynchronizeLoadProperties then
Mutex := TJclMutex.Create(nil, False,
string(B64Encode(AnsiString(RsJvPropertyStoreMutexLoadStorePropertiesProcedureName +
AppStoragePath))))
else
Mutex := TJclMutex.Create(nil, False,
string(B64Encode(AnsiString(RsJvPropertyStoreMutexStorePropertiesProcedureName +
AppStoragePath))));
try
if Mutex.WaitForever = wrSignaled then
try
ExecuteStoreProperties;
finally
Mutex.Release;
end
else
raise
Exception.CreateResFmt({$IFNDEF CLR}@{$ENDIF}RsJvPropertyStoreEnterMutexTimeout, [RsJvPropertyStoreMutexStorePropertiesProcedureName]);
finally
FreeAndNil(Mutex);
end;
end
else
ExecuteStoreProperties;
end;
procedure TJvCustomPropertyStore.LoadData;
begin
end;
procedure TJvCustomPropertyStore.StoreData;
begin
end;
function TJvCustomPropertyStore.StorePropertiesNow: Boolean;
begin
Result := True;
end;
//=== { TJvCustomPropertyListStore } =========================================
constructor TJvCustomPropertyListStore.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItems := CreateItemList;
CreateListEntries := True;
FreeObjects := True;
FItemName := cItem;
FIntIgnoreProperties.Add('ItemName');
FIntIgnoreProperties.Add('FreeObjects');
FIntIgnoreProperties.Add('CreateListEntries')
end;
destructor TJvCustomPropertyListStore.Destroy;
begin
Clear;
FreeAndNil(FItems);
inherited Destroy;
end;
function TJvCustomPropertyListStore.CreateAddObject(const aObjectName: String):
TPersistent;
begin
Result := CreateObject;
Items.AddObject(aObjectName, Result);
end;
function TJvCustomPropertyListStore.GetItems: TStringList;
begin
Result := FItems;
end;
procedure TJvCustomPropertyListStore.StoreData;
begin
inherited StoreData;
AppStorage.WriteList(AppStoragePath, nil, Count, WriteSLOItem, DeleteSLOItems,
ItemName);
end;
procedure TJvCustomPropertyListStore.LoadData;
begin
inherited LoadData;
AppStorage.ReadList(AppStoragePath, nil, ReadSLOItem, ItemName);
end;
procedure TJvCustomPropertyListStore.Clear;
var
I: Integer;
obj : TObject;
begin
if Assigned(Items) then
begin
if FreeObjects then
for I := Count - 1 downto 0 do
if Assigned(Objects[I]) then
begin
obj := Objects[I];
Objects[I] := nil;
obj.Free;
end;
Items.Clear;
end;
inherited Clear;
end;
function TJvCustomPropertyListStore.CreateItemList: TStringList;
begin
Result := TStringList.Create;
end;
function TJvCustomPropertyListStore.GetString(Index: Integer): string;
begin
if Assigned(Items) then
Result := Items.Strings[Index]
else
Result := '';
end;
function TJvCustomPropertyListStore.GetObject(Index: Integer): TObject;
begin
if Assigned(Items) then
Result := Items.Objects[Index]
else
Result := nil;
end;
procedure TJvCustomPropertyListStore.SetString(Index: Integer; Value: string);
begin
Items.Strings[Index] := Value;
end;
procedure TJvCustomPropertyListStore.SetObject(Index: Integer; Value: TObject);
begin
Items.Objects[Index] := Value;
end;
function TJvCustomPropertyListStore.GetCount: Integer;
begin
if Assigned(Items) then
Result := Items.Count
else
Result := -1;
end;
function TJvCustomPropertyListStore.GetSorted: Boolean;
begin
Result := FItems.Sorted;
end;
procedure TJvCustomPropertyListStore.SetSorted(Value: Boolean);
begin
FItems.Sorted := Value;
end;
function TJvCustomPropertyListStore.GetDuplicates: TDuplicates;
begin
Result := FItems.Duplicates;
end;
procedure TJvCustomPropertyListStore.SetDuplicates(Value: TDuplicates);
begin
FItems.Duplicates := Value;
end;
procedure TJvCustomPropertyListStore.ReadSLOItem(Sender: TJvCustomAppStorage;
const Path: string; const List: TObject; const Index: Integer; const ItemName:
string);
var
NewObject: TObject;
NewObjectName: string;
begin
if Index >= Count then
begin
if not CreateListEntries then
Exit;
NewObject := CreateObject;
if Assigned(NewObject) then
begin
if NewObject is TJvCustomPropertyStore then
begin
TJvCustomPropertyStore(NewObject).AppStoragePath :=
Sender.ConcatPaths([Path, Sender.ItemNameIndexPath(ItemName, Index)]);
TJvCustomPropertyStore(NewObject).AppStorage := Sender;
TJvCustomPropertyStore(NewObject).LoadProperties;
end
else if NewObject is TPersistent then
Sender.ReadPersistent(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index)]),
TPersistent(NewObject), True, True, CombinedIgnoreProperties);
if Sender.ValueStored(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index), ItemsObjectName])) then
NewObjectName := Sender.ReadString(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index), ItemsObjectName]))
else
NewObjectName := '';
Items.AddObject(NewObjectName, NewObject);
end
else
Items.Add(Sender.ReadString(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index)])))
end
else if Assigned(Objects[Index]) then
begin
if Objects[Index] is TJvCustomPropertyStore then
begin
TJvCustomPropertyStore(Objects[Index]).AppStoragePath :=
Sender.ConcatPaths([Path, Sender.ItemNameIndexPath(ItemName, Index)]);
TJvCustomPropertyStore(Objects[Index]).AppStorage := Sender;
TJvCustomPropertyStore(Objects[Index]).LoadProperties;
end
else if Objects[Index] is TPersistent then
Sender.ReadPersistent(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index)]),
TPersistent(Objects[Index]), True, True, CombinedIgnoreProperties);
if Sender.ValueStored(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index), ItemsObjectName])) then
Strings[Index] := Sender.ReadString(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index), ItemsObjectName]))
else
Strings[Index] := '';
end
else
Strings[Index] := Sender.ReadString(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index)]));
end;
procedure TJvCustomPropertyListStore.WriteSLOItem(Sender: TJvCustomAppStorage;
const Path: string; const List: TObject; const Index: Integer; const ItemName:
string);
begin
if Assigned(Objects[Index]) then
begin
if Objects[Index] is TJvCustomPropertyStore then
begin
TJvCustomPropertyStore(Objects[Index]).AppStoragePath :=
Sender.ConcatPaths([Path, Sender.ItemNameIndexPath(ItemName, Index)]);
TJvCustomPropertyStore(Objects[Index]).AppStorage := Sender;
TJvCustomPropertyStore(Objects[Index]).StoreProperties;
end
else if Objects[Index] is TPersistent then
Sender.WritePersistent(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index)]),
TPersistent(Objects[Index]), True, CombinedIgnoreProperties);
if Strings[Index] <> '' then
Sender.WriteString(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index), ItemsObjectName]), Strings[Index]);
end
else
Sender.WriteString(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, Index)]), Strings[Index]);
end;
procedure TJvCustomPropertyListStore.DeleteSLOItems(Sender: TJvCustomAppStorage;
const Path: string; const List: TObject; const First, Last: Integer; const
ItemName: string);
var
I: Integer;
begin
for I := Last downto first do
Sender.DeleteValue(Sender.ConcatPaths([Path,
Sender.ItemNameIndexPath(ItemName, i)]));
end;
function TJvCustomPropertyListStore.IndexOf(const s: string): Integer;
begin
Result := FItems.IndexOf(s);
end;
function TJvCustomPropertyListStore.IndexOfObject(AObject: TObject): Integer;
begin
Result := FItems.IndexOfObject(AObject);
end;
procedure TJvCustomPropertyListStore.ListEditIntf_MoveObjectPosition(CurIndex,
NewIndex: Integer);
begin
if (CurIndex >= 0) and (CurIndex < Count) and
(NewIndex >= 0) and (NewIndex < Count) then
Items.Move(CurIndex, NewIndex);
end;
function TJvCustomPropertyListStore.ListEditIntf_CloneNewObject(Index:
integer): TPersistent;
begin
if (Index >= 0) and (Index < Count) and
Assigned(Objects[Index]) then
if (Objects[Index] is TJvCustomPropertyStore) then
begin
Result := TPersistent(TJvCustomPropertyStore(Objects[Index]).Clone(self));
Items.AddObject ('New '+ItemName, Result);
end
else
begin
Result := ListEditIntf_CreateNewObject;
if (Objects[Index] is TPersistent)then
TPersistent(Result).Assign(TPersistent(Objects[Index]));
end
else
Result := nil;
end;
function TJvCustomPropertyListStore.ListEditIntf_CreateNewObject: TPersistent;
begin
Result := CreateObject;
Items.AddObject ('New '+ItemName, Result);
end;
procedure TJvCustomPropertyListStore.ListEditIntf_DeleteObject(Index: integer);
begin
if (Index >= 0) and (Index < Count) then
begin
if Assigned(Objects[Index]) then
Objects[Index].Free // The item will be deleted automaticly
else
Items.Delete(Index);
end;
end;
function TJvCustomPropertyListStore.ListEditIntf_GetObject(Index: integer):
TPersistent;
begin
if (Index >= 0) and (Index < Count) and (Objects[Index] is TPersistent) then
Result := TPersistent(Objects[Index])
else
Result := nil;
;
end;
function TJvCustomPropertyListStore.ListEditIntf_ObjectCount: integer;
begin
Result := Count;
end;
{$IFDEF UNITVERSIONING}
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.