View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0003807 | JEDI VCL | 04 Feature Request | public | 2006-07-12 08:33 | 2006-08-14 16:37 |
Reporter | Nanotonne | Assigned To | jfudickar | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | Daily / GIT | ||||
Target Version | Fixed in Version | ||||
Summary | 0003807: JvAppStorage: FileName replacements | ||||
Description | i 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 Information | it'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 ! | ||||
Tags | No tags attached. | ||||
2006-07-12 08:33
|
UnitTranslatefilename1.pas (4,065 bytes) |
|
Which component is this about? |
|
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... |
|
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. |
|
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! |
|
Hi Olivier, we have made something similar for the TJvAppRegistryStorage. Why not also for the file storages? Greetings Jens |
|
Well then, it should be in all of them then, yes. |
|
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) |
|
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? |
|
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 |
|
Should we use < and > or % to be compatible between registry and file pathnames? |
|
I'd rather use %, people are much more used to it as a replacement marker. |
|
Hi Olivier, i think adding the function to jcl would be the best. But which Unit? JclStrings / JclFileUtils / ... ? Any Comments Greetings Jens |
|
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) |
|
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=""/> |
|
Reminder sent to: obones Hi Olivier, please have a look for my changes. Greetings and thanks Jens |
|
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. |
|
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 |
|
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. |
|
Commited to svn. Please have a look for it. Have a look at the default example alao. |
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 |