View Issue Details

IDProjectCategoryView StatusLast Update
0003807JEDI VCL04 Feature Requestpublic2006-08-14 16:37
ReporterNanotonneAssigned Tojfudickar 
PrioritynormalSeverityfeatureReproducibilityalways
Status resolvedResolutionfixed 
Product VersionDaily / GIT 
Target VersionFixed in Version 
Summary0003807: JvAppStorage: FileName replacements
Descriptioni need to have no fixed filename but command special to formating text in filename property via "<" and ">" (LESS THAN (UP) and MORE THAN(DOWN) character delimiter).

---> For example for this case :
Property FileName = dir1\hel<exename>lo.native.ini
(my full executable named execu1.exe)

result real FileName will be dir1\helexecu1lo.native.ini :-) ;-)
- if i RENAME after my executable program execu1.exe to myexecu2user.exe and after re-run it (this new executable), real FileName change consequencly too dynamically to dir1\helmyexecut2userlo.native.ini

Add property (published and read only?) ResultFileName (or FileNameInterpreted ?) to know resulting FileName property interpeted (see my example to know result string) after interpreting.

with this feature, we can :
- Improve changing filename dynamically
- get exename to change "exe" extention to "ini" extention
- add special text in ini filename as : date actual, time actual, randomize, string number, etc...

see example to format/replacing FileName property:
<exename> is replaced by executable filename runned but WITHOUT ".exe" extention and WHITHOUT path directory. for example c:\dir1\myeXe1.exe give myeXe1
<filename> is replaced by full file name without ".exe" extention (give for example c:\dir1\myeXe1)
<exedir> give the actual directory where is the executable WITHOUT trailing backslash, for example, for c:\dir1\dir2\app1.exe , give dir2
<fullexedir> give full actual directory of exe : c:\dir1\dir2\app1.exe , give dir1\dir2
<date> give 21-05-2006
<time> give 21h53.97 (or 21h53 ?, or 21h53m58)
<random(52)> give integer(or float?) number between 0..52
<random> give float number between 0 and 1
<randomstr(5)> give string randomly with maximum 5 characters
<...>
....
....
etc ... ( we can add new "command" substitute)

possibility to mixed rules, for example :
user<exename>-curr-<date><random(5)>.ini

thank to accept this feature!!
<exename> is the MOST important!. after, we can extend this feature later...
Additional Informationit's easy to test replacement of text :

function translatefilename(filename:string):string;
var i,j:integer;
s:string;
begin
  result:='';
  while filename<>'' do
  begin
    i:=pos('<',filename);
    if i=0 then
    begin
      result:=result+filename;
      filename:='';
          // here, we can test if '>' is present, because it's arror! because
          // '<' should be placed BEFORE '>' : maybe we can ignore, delete this char,
          // or raise exception? me i think delete this char is best solution
      // result:=StringReplace(result,'>','',[rfReplaceAll]); // delete '>' ?
    end
     else
    begin
      result:=result+copy(filename,1,pred(i));
      delete(filename,1,i);
      j:=pos('>',filename);
      s:=copy(filename,1,pred(j));
     // s:=StringReplace(s,'>','',[rfReplaceAll]); // delete '<' ?
      delete(filename,1,j);
      result:=result+'+'+uppercase(s)+'-'; // uppercase or special function to replace command!
// result:=result+'+'+processcommand(s)+'-'; // uppercase or special function to replace command!
      s:='';
    end;
  end;
end;

{
function processcommand(s:string):string;
begin
  if upcase(s)='exename' then result:=....... else
  if s='random' then .... else
  if s='date' then..... else
  if pos('addition('=1 then ..... else // then addition (a,b) = a+b variable!
  ..................... else // for example 'multiplie(4,5),-> result=20 ! :)
  result:='';
end;
}

see fileadded for example !
TagsNo tags attached.

Activities

2006-07-12 08:33

 

UnitTranslatefilename1.pas (4,065 bytes)

obones

2006-07-12 11:49

administrator   ~0009790

Which component is this about?

Nanotonne

2006-07-12 12:29

reporter   ~0009791

ouuups! sorry!!
for TJvAppIniFileStorage, TJvAppXMLFileStorage !!! :)

add published (or public) FileNameInterpreted property in TJvAppIniFileStorage, TJvAppXMLFileStorage
and too RealFileName (or ThrueFileName, or RealFileName, or ResultFileName, or IniFileName) property

(FileNameInterpreted := translatefilename(FileName);{to "translate" via "<"cmd">"}
RealFileName:=JvAppIniFileStorage1.IniFile.FileName; //can be interesting too...

obones

2006-07-13 01:37

administrator   ~0009793

You can already do that by setting Location to flCustom and having an handler for OnGetFileName. There you can do whatever you please with the name.
I don't see the point in having "replacements" as we would end up with lots of requests to add new markers over and over.
To me, the current situation is fine and should not be changed.

Nanotonne

2006-07-13 02:12

reporter   ~0009797

Yes but with it's more easy and more customizable with this method we can just change filename without creating event!
and it's more easy to set exename as inifile extention! (and too more extensible!)
the primary target is to a inifile with same name as full exefilename but ".exe" replaced by ".ini" WITHOUT EVENT to customize name!
if my app is c:\app\app1.exe , then ini name will be c:\app\app1.ini, if i rename exe by app2.exe and execute it, new ini will be c:\app\app2.ini.
Actually we can't do that without add codeline in app, we need to add code line! (then it's not 100% more simple!)

this method requiert NO event!! (then no additionnal code in app!) and too it's easy to extend possibility and customize the filename!!!!! (add just a string in filename property, etc, etc!)
this feature is easy to set in place: i have already create function to string in string! this method requier NO ADDITIONNAL CODE ! (and easy to do).
This (my) function can be too used for texte replacement scripting for the filename or other for other/special situation!
try to test! this function is interesting!

(we too can add flAdvanced to permit too this feature .... but for me this fuction/feature ("<command>") is a best choice and is compatible with all application already created if we recompile it.)

for info : OnGetFileName with flCustom (new setting Location type) is not called just one only but more count (>4x!!)!! :(, normally should be called just one cycle!

jfudickar

2006-07-18 00:14

developer   ~0009810

Hi Olivier,

we have made something similar for the TJvAppRegistryStorage.

Why not also for the file storages?

Greetings
Jens

obones

2006-07-18 02:58

administrator   ~0009811

Well then, it should be in all of them then, yes.

Nanotonne

2006-07-18 03:42

reporter   ~0009813

cool!! :=
i have modified my function to best impovement/feature later and best usability for other thing :

unction TranslateFilename{TranslateString?}(filename:string; const BeginDelim:string='<'; const EndDelim:string='>'):string;
var i,j:integer;
s:string;
begin
  result:='';
  while filename<>'' do
  begin
    i:=pos(begindelim,filename);
    if i=0 then
    begin
      result:=result+filename;
      filename:='';
          // here, we can test if begindelim is present, because it's arror! because
          // begindelim should be placed BEFORE enddelim : maybe we can ignore, delete this char,
          // or raise exception? me i think delete this char is best solution
      // result:=StringReplace(result,EndDelim,'',[rfReplaceAll]); // delete EndDelim ?
    end
     else
    begin
      result:=result+copy(filename,1,pred(i));
      delete(filename,1,i);
      j:=pos(EndDelim,filename);
      s:=copy(filename,1,pred(j));
     // s:=StringReplace(s,EndDelim,'',[rfReplaceAll]); // delete BeginDelim ?
      delete(filename,1,j);
// result:=result+'+'+uppercase(s)+'-'; // uppercase or special function to replace command!
 result:=result+processfunctioncommand(s); // uppercase or special function to replace command!
      s:='';
    end;
  end;
end;

after we can do TranslateFilename(FileName,'<','>') if we have 'hel<appname>lo' or TranslateFilename(FileName,'%','%) if we have 'hel%APPNAME%lo
I have see in tJvFormStorage, property AppStoragePath is defalut with value '%FORM_NAME%' to past/get the form name value, then we can use/replace too easy with my function for this too : TranslateFilename(AppStoragePath) (or TranslateString? best logic name of function? maybe, because it's not limited for "filename only"....).
with AppStoragePath='%FORM_NAME%' by default the result will be then equivalent to TranslateFilename('%FORM_NAME%'{,'%','%'}).
hmm.. i prefer TranslateString or ConvertString, or ProcessString in replacement to TranslateName, it's best choice and easy usable for application if we want get/"include in" a exename, formname, etc.... with possibility to change(customize) delimiters (starting and ending) for extensible future feature (for app or for jvcl component)

obones

2006-07-18 05:05

administrator   ~0009814

But i'd rather have all of them use the same functions. Jens, can you look at how it was done in the Registry one and adpat it to the others?

Nanotonne

2006-07-18 06:00

reporter   ~0009815

same function, yes, it's good idea, but based on
function ProcessString(filename:string; const BeginDelim:string='<'; const EndDelim:string='>'):string;

the call for common jvcl components (using this function) should be : ProcessString(nameofproperty, '%', '%') and this function should be too accessible by application to use it for other thing (should be in jcl i thing).

it's need to separate this feature in two base functions :
- ProcessString : to process the string with both delimiters include
- ProcessStringDelimited : to process the strings BETWEEN the delimiters founds in ProcessString.

with this, ProcessStringDelimited can be improved separatly easier and easier maintained for add or modified the command to replace ('appname', 'formname', 'dirname', 'datetimenow', 'randomvalue(valueinteger)', etc ... or customized command by application eventually, if possible, in future (i don't know how actually) but i thing it's possible))

the return value for jvcl component using ProcessString function should be accessible (readonly) and published to check if it's good, or public only property, for example named ProcessedFileName, for jvinifilestorage and other components (common), for app already existing, no change code, but we can improve easy app already existing to check this property or add delimitered string to improve it! :)

use sames commons functions for jvcl components and eventually adapt other comonent for to be same is good idea, as suggered obones.
it's need to analyze to find best choice solution for common components, what we use common solution (uniform) for components using this functions

jfudickar

2006-07-19 02:31

developer   ~0009817

Should we use < and > or % to be compatible between registry and file pathnames?

obones

2006-07-19 02:34

administrator   ~0009818

I'd rather use %, people are much more used to it as a replacement marker.

jfudickar

2006-07-23 04:16

developer   ~0009840

Hi Olivier,

i think adding the function to jcl would be the best. But which Unit?

JclStrings / JclFileUtils / ... ?


Any Comments

Greetings
Jens

obones

2006-07-24 00:53

administrator   ~0009843

I'm not sure it should go into the JCL, but it is a simple string replacement method. I mean, you could make it so generic that it does not care it receives filenames. Ask the JCL guys, or simply put it in JvJCLUtils.pas for now.

2006-07-31 15:41

 

JvTranslateString.zip (29,506 bytes)

jfudickar

2006-07-31 15:45

developer   ~0009927

Hey Guys,

please had a look on my changes.

It seems to be a little bit complicated to create a separate component but it has advantages like internal variables and also the current form name.

Please give me your comments.

And what do you think about adding a translatestring in each read/write method to translate the path.

This could be interesting if you want to store control positions depending on the screensize.

Greetings
Jens

P.S. If you want to rebuild using the installer you must path the JvCore-R.xml with the following line:
<File Name="..\..\run\JvTranslateString.pas" Targets="all" Formname="" Condition=""/>

jfudickar

2006-08-09 00:08

developer   ~0009968

Reminder sent to: obones

Hi Olivier,

please have a look for my changes.

Greetings and thanks
Jens

obones

2006-08-10 06:30

administrator   ~0009970

Ah yes. First and foremost, sorry for the delay.
I would have much prefered patch files so that I can read the differences easier. But all in all, it looks good except for this:

Well no, the property should use its own field as it is now, but there should be a second one, internal that is used if the property is not filled.
This way, users do not have to create a component if they don't want to, and if they do, it is used instead. With the current setup, we get a memory leak.

jfudickar

2006-08-12 06:48

developer   ~0009971

Sorry OLivier,

maybe i'm sitting on the line, but i didn't understand your comments :-)

Could you try it again, please.

Should i hide the property TranslateStringEngine as protected?
And where did you see a memory leak?

Greetings
Jens

obones

2006-08-14 01:41

administrator   ~0009972

TranslateStringEngine reads and writes the FTranslateStringEngine field, as expected with a property.
In TJvCustomAppStorage.Create, you create an instance of TJvTranslateString and assign it to FTranslateStringEngine. And in the destructor, you free it.
Now, imagine that someone makes the property public, or derives a component.
He will be able to write this:

Storage.TranslateStringEngine := MyTranslateStringEngine;

This replaces the value set by the constructor by a value from the user, thus creating a leak on the instance created internally. On top of that, as a user, I do not expect the component to free my own instance. I mean, when you set the Menu property of a TToolBar, you do not expect nor do you want it to free the menu. That's the same here.

First solution is to write a setter for the TranslateStringEngine property, setter that does this:

FTranslateStringEngine.Assign(Value);

and then write the appropriate code for Assign. But that won't work fine for two reasons: First, if the property gets published (which I intend to do) as the IDE will not be able to find the link between the two components. Second, you need to write an OnChange mechanism to track changes in the assigned value.
Hence, what you need to do is something very similar to what is done for the Painter property of TJvMainMenu: have FInternalTranslateStringEngine and FTranslateStringEngine fields and create an instance only for the internal one. Now, keep the TranslateStringEngine property with the current read and write values (direct access to FTranslateStringEngine). This way, it allows the user of the class to pass in his own instance of a TJvTranslateString component (or derived) and this link will stick in the designer.
Of course, you need to modify all code that uses TranslateStringEngine so that it tests if FTranslateStringEngine is assigned and if not, use FInternalTranslateStringEngine. This is usually done via a protected function, called in this case GetActiveTranslateStringEngine (and maybe a property called ActiveTranslateStringEngine with just a getter) which does this:

Result := FInternalTranslateStringEngine;
if Assigned(FTranslateStringEngine) then
  Result := FTranslateStringEngine;

This way, when you write your code you use ActiveTranslateStringEngine and will get a valid instance, regardless of the fact whether or not the user set the TranslateStringEngine property.
I hope I'm clear here.

jfudickar

2006-08-14 16:37

developer   ~0009975

Commited to svn. Please have a look for it.

Have a look at the default example alao.

Issue History

Date Modified Username Field Change
2006-07-12 08:33 Nanotonne New Issue
2006-07-12 08:33 Nanotonne File Added: UnitTranslatefilename1.pas
2006-07-12 11:49 obones Note Added: 0009790
2006-07-12 11:49 obones Status new => feedback
2006-07-12 12:29 Nanotonne Note Added: 0009791
2006-07-13 01:35 obones Summary add replacement text (dyn)in filename property via special rule formating text interpretation in filename, for example <exename> => JvAppStorage: FileName replacements
2006-07-13 01:37 obones Note Added: 0009793
2006-07-13 02:12 Nanotonne Note Added: 0009797
2006-07-18 00:14 jfudickar Note Added: 0009810
2006-07-18 02:58 obones Note Added: 0009811
2006-07-18 03:42 Nanotonne Note Added: 0009813
2006-07-18 05:05 obones Note Added: 0009814
2006-07-18 06:00 Nanotonne Note Added: 0009815
2006-07-18 13:02 jfudickar Status feedback => assigned
2006-07-18 13:02 jfudickar Assigned To => jfudickar
2006-07-19 02:31 jfudickar Note Added: 0009817
2006-07-19 02:34 obones Note Added: 0009818
2006-07-23 04:16 jfudickar Note Added: 0009840
2006-07-24 00:53 obones Note Added: 0009843
2006-07-31 15:41 jfudickar File Added: JvTranslateString.zip
2006-07-31 15:45 jfudickar Note Added: 0009927
2006-07-31 15:45 jfudickar Status assigned => feedback
2006-08-09 00:08 jfudickar Note Added: 0009968
2006-08-10 06:30 obones Note Added: 0009970
2006-08-12 06:48 jfudickar Note Added: 0009971
2006-08-14 01:41 obones Note Added: 0009972
2006-08-14 16:37 jfudickar Status feedback => resolved
2006-08-14 16:37 jfudickar Resolution open => fixed
2006-08-14 16:37 jfudickar Note Added: 0009975