Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: 1 [2]
  Reply  |  Print  
Author Topic: Subdialogs in general  (Read 46170 times)
Stephen T.
Posts: 114


« Reply #15 on: March 10, 2014, 09:14:58 am »

Quote from: steveT
This second point is/was more of an issue. The function above - ext_open_database - used the global (now public) variable g_DBNAME to open the database. That worked fine. Also, ext_open_database had 'standalone' globals that were converted to PUBLIC defs. g_DBNAME was then defined as a PUBLIC CHAR(40) and was actually set in ext_open_database by FGL_GETENV. Fine. That worked as expected. However, when the issue above was noted, the standalone PUBLIC def of g_DBNAME was replaced with the full IMPORT of base_globals. The database open then started to fail. Looking at the FGLSQLDEBUG output, the problem appears to be that g_DBNAME, if IMPORTed in an FGL, is treated as the name of the database, rather than a variable containing the name. If a local variable was set to the the PUBLIC variable and that used in the DATABASE statement, then it works fine. It just seems to object to using a PUBLIC IMPORTED def (see debug and ext_open_database extracts attached).

Quote from: seb
About the second point (g_DBNAME/FGL_GETENV), sorry but I don't get it. You better provide a little sample to reproduce the problem to let us identify if the behavior described is expected or is a bug...

Seb,
The code snippet attached to the post attempted to show the error (that was also shown in the attached SQLDEBUG output). The code is:
Quote from: snippet
IMPORT FGL base_globals   

 
################################################################################
#  OPEN THE DATABASE........................................
################################################################################
 FUNCTION ext_open_database(p_dbase,p_mode)   
 DEFINE p_dbase,
        p_mode                      CHAR(40)

 DEFINE l_string                    STRING,
        l_dbExists                  INTEGER
 
 define l_dbname                    char(40)

 CONSTANT lc_rcs                    STRING = '$Id: ext_open_database.4gl,v 1.1 2005/06/16 15:24:13 stevet Exp stevet $'

 WHENEVER ERROR CONTINUE

    -- Set the date and time.....
    LET g_today                     = TODAY
    LET g_current                   = CURRENT


    -- Get the user log in code
    SELECT USER
        INTO g_user
        FROM blankTable
        WHERE recNo     = 1

    -- Get the database Type
    LET g_DATABASETYPE  =   FGL_GETENV('DATABASETYPE')
    IF NOT LENGTH(g_DATABASETYPE) THEN
        LET g_DATABASETYPE = 'INFV9.3'
    END IF   

    IF LENGTH(p_dbase) THEN
        LET g_DBNAME    = p_dbase
    ELSE       
        LET g_DBNAME    = FGL_GETENV('DBNAME')
    END IF

    LET g_FGLRUN        = FGL_GETENV('FGLRUN')
    IF NOT LENGTH(g_FGLRUN) THEN
        LET g_FGLRUN    = 'fglrun'
    END IF   

    CLOSE DATABASE

--RE--    LET l_string = 'DATABASE ', g_DBNAME CLIPPED,' ',p_mode CLIPPED
--RE--    IF ext_execute_mysql(l_string,1) THEN
--RE--    END IF
    DATABASE g_DBNAME
    -- NB for some reason under FGL 2.50, g_DBNAME as a public def gets interpreted as the DBNAME
    --    itself rather than a variable containing the DBNAME - if the g_DBNAME is moved to a local
    --    variable, it works fine
    LET l_DBNAME    = g_DBNAME
    DATABASE l_DBNAME

Quote from: SQLDEBUG
SQL: CLOSE DATABASE
 | 4gl source      : ext_open_database.4gl line=101
 | sqlcode         : -1803
 |   sqlstate      : HY000
 |   sqlerrd2      : -1
 |   sql message   : Connection does not exist.
 |   sql msg param :
 | curr driver     : ident='dbmpgs91x'
 | curr connection : ident='none' (dbspec=[none])
 | Execution time  :   0 00:00:00.00004
SQL: DATABASE
 | 4gl source      : ext_open_database.4gl line=106
 | pgs.c:00453(3)  : Connection parameters for '?':
 | pgs.c:00454(3)  :  Database      = 'g_dbname'
 | pgs.c:00455(3)  :  Hostname      = ''
 | pgs.c:00456(3)  :  Port          = ''
 | pgs.c:00457(3)  :  User name     = ''
 | pgs.c:00458(3)  :  Password      = ''
 | pgs.c:00486(2)  : Could not connect to database.
 | pgs.c:00367(1)  : Warning: NULL PGresult handler.
 | sqlcode         : -6372
 |   sqlstate      : XX000
 |   sqlerrd2      : -1
 |  sql message   : FATAL:  database "g_dbname" does not exist
 |   sql msg param :
 | curr driver     : ident='dbmpgs91x'
 | curr connection : ident='none' (dbspec=[none])
 | Execution time  :   0 00:00:00.00248
SQL: DATABASE
 | 4gl source      : ext_open_database.4gl line=111
 | pgs.c:00453(3)  : Connection parameters for '?':
 | pgs.c:00454(3)  :  Database      = 'dev_rand'
 | pgs.c:00455(3)  :  Hostname      = ''
 | pgs.c:00456(3)  :  Port          = ''
 | pgs.c:00457(3)  :  User name     = ''
 | pgs.c:00458(3)  :  Password      = ''
 | pgs.c:00494(3)  :  PGS version   = 901
 | pgs.c:00192(2)  : Execdirect : set intervalstyle='iso_8601'
 | sqlcode         : 0

Sebastien F.
Four Js
Posts: 545


« Reply #16 on: March 10, 2014, 09:27:11 am »

Sorry but I get confused:
The principle of the INITIALIZER combobox attribute is to have the runtime system call the initializer function automatically when a form is loaded/displayed.
Here you write that you call "by hand" your combobox initializers from the MAIN module (through different other functions)...
What are you doing exactly in your code?
Why are you calling the combobox initializers explicitely?
Maybe you have this "ext_reload_combos" function that must be called in some particular case?
It's quite difficult to help without seeing the code.
Anyway, yes, assuming that ext_init_combos() is the initialization function defined in the INITIALIZER attribute, if that function was called once before OPEN FORM/DISPLAY FORM or OPEN WINDOW, the module containing this function is loaded, and then the function is available for the automatic combobox initialization call. But maybe you are doing the job twice.
Seb
Sebastien F.
Four Js
Posts: 545


« Reply #17 on: March 10, 2014, 09:35:31 am »

Quote from: steveT
This second point is/was more of an issue. The function above - ext_open_database - used the global (now public) variable g_DBNAME to open the database. That worked fine. Also, ext_open_database had 'standalone' globals that were converted to PUBLIC defs. g_DBNAME was then defined as a PUBLIC CHAR(40) and was actually set in ext_open_database by FGL_GETENV. Fine. That worked as expected. However, when the issue above was noted, the standalone PUBLIC def of g_DBNAME was replaced with the full IMPORT of base_globals. The database open then started to fail. Looking at the FGLSQLDEBUG output, the problem appears to be that g_DBNAME, if IMPORTed in an FGL, is treated as the name of the database, rather than a variable containing the name. If a local variable was set to the the PUBLIC variable and that used in the DATABASE statement, then it works fine. It just seems to object to using a PUBLIC IMPORTED def (see debug and ext_open_database extracts attached).

Quote from: seb
About the second point (g_DBNAME/FGL_GETENV), sorry but I don't get it. You better provide a little sample to reproduce the problem to let us identify if the behavior described is expected or is a bug...

Seb,
The code snippet attached to the post attempted to show the error (that was also shown in the attached SQLDEBUG output). The code is:
Quote from: snippet
IMPORT FGL base_globals   

 
################################################################################
#  OPEN THE DATABASE........................................
################################################################################
 FUNCTION ext_open_database(p_dbase,p_mode)   
 DEFINE p_dbase,
        p_mode                      CHAR(40)

 DEFINE l_string                    STRING,
        l_dbExists                  INTEGER
 
 define l_dbname                    char(40)

 CONSTANT lc_rcs                    STRING = '$Id: ext_open_database.4gl,v 1.1 2005/06/16 15:24:13 stevet Exp stevet $'

 WHENEVER ERROR CONTINUE

    -- Set the date and time.....
    LET g_today                     = TODAY
    LET g_current                   = CURRENT


    -- Get the user log in code
    SELECT USER
        INTO g_user
        FROM blankTable
        WHERE recNo     = 1

    -- Get the database Type
    LET g_DATABASETYPE  =   FGL_GETENV('DATABASETYPE')
    IF NOT LENGTH(g_DATABASETYPE) THEN
        LET g_DATABASETYPE = 'INFV9.3'
    END IF   

    IF LENGTH(p_dbase) THEN
        LET g_DBNAME    = p_dbase
    ELSE       
        LET g_DBNAME    = FGL_GETENV('DBNAME')
    END IF

    LET g_FGLRUN        = FGL_GETENV('FGLRUN')
    IF NOT LENGTH(g_FGLRUN) THEN
        LET g_FGLRUN    = 'fglrun'
    END IF   

    CLOSE DATABASE

--RE--    LET l_string = 'DATABASE ', g_DBNAME CLIPPED,' ',p_mode CLIPPED
--RE--    IF ext_execute_mysql(l_string,1) THEN
--RE--    END IF
    DATABASE g_DBNAME
    -- NB for some reason under FGL 2.50, g_DBNAME as a public def gets interpreted as the DBNAME
    --    itself rather than a variable containing the DBNAME - if the g_DBNAME is moved to a local
    --    variable, it works fine
    LET l_DBNAME    = g_DBNAME
    DATABASE l_DBNAME

Quote from: SQLDEBUG
SQL: CLOSE DATABASE
 | 4gl source      : ext_open_database.4gl line=101
 | sqlcode         : -1803
 |   sqlstate      : HY000
 |   sqlerrd2      : -1
 |   sql message   : Connection does not exist.
 |   sql msg param :
 | curr driver     : ident='dbmpgs91x'
 | curr connection : ident='none' (dbspec=[none])
 | Execution time  :   0 00:00:00.00004
SQL: DATABASE
 | 4gl source      : ext_open_database.4gl line=106
 | pgs.c:00453(3)  : Connection parameters for '?':
 | pgs.c:00454(3)  :  Database      = 'g_dbname'
 | pgs.c:00455(3)  :  Hostname      = ''
 | pgs.c:00456(3)  :  Port          = ''
 | pgs.c:00457(3)  :  User name     = ''
 | pgs.c:00458(3)  :  Password      = ''
 | pgs.c:00486(2)  : Could not connect to database.
 | pgs.c:00367(1)  : Warning: NULL PGresult handler.
 | sqlcode         : -6372
 |   sqlstate      : XX000
 |   sqlerrd2      : -1
 |  sql message   : FATAL:  database "g_dbname" does not exist
 |   sql msg param :
 | curr driver     : ident='dbmpgs91x'
 | curr connection : ident='none' (dbspec=[none])
 | Execution time  :   0 00:00:00.00248
SQL: DATABASE
 | 4gl source      : ext_open_database.4gl line=111
 | pgs.c:00453(3)  : Connection parameters for '?':
 | pgs.c:00454(3)  :  Database      = 'dev_rand'
 | pgs.c:00455(3)  :  Hostname      = ''
 | pgs.c:00456(3)  :  Port          = ''
 | pgs.c:00457(3)  :  User name     = ''
 | pgs.c:00458(3)  :  Password      = ''
 | pgs.c:00494(3)  :  PGS version   = 901
 | pgs.c:00192(2)  : Execdirect : set intervalstyle='iso_8601'
 | sqlcode         : 0




Yes I understand now, and I confirm that variables imported from other modules cannot be used in Static SQL statements.
We are discussing this internally to decide if it's a bug or an expected behavior:
It's probably not a good practice to use imported module variables in local SQL statements, you may have the same problem as with combobox initializer functions (must discuss this with the team)
The compiler should however print and error or warning, that imported variables are used in SQL statements.

Seb
Stephen T.
Posts: 114


« Reply #18 on: March 10, 2014, 10:29:56 am »

[qoute="Seb]

Regarding the "next field" case:
Here again, a little sample would be appreciated to let us understand, here some remarks...
I think that you should design your dialogs so that you don't have to add particular code to jump to a specific field in a given condition.
The field navigation should be natural and implicit.
If the "always in edit mode" for record lists (INPUT ARRAY semantics) is not mandatory, consider using DISPLAY ARRAY with modification triggers (ON APPEND, ON INSERT, ON DELETE, ON UPDATE) - It's easier to deal with a DISPLAY ARRAY as with all special cases of INPUT ARRAY.
[/quote]

Seb,
Exactly. So in our case, if the user is in an array and leaves a row blank (ie they TAB from the first field of the row, and that row is blank), then the code jumps out of that array and to the next dialog (whatever that is). I have emulated this by creating an array of next/previous fields by dialog name and populating the array before the main DIALOG and then using a wrapper around DIALOG.nextField to pick up the current dialog name and set the field focus based on the array.
The issue being (from my perspective) is that I can never know what the next/previous dialog is and hence what the next/previous field is. The code we repeat all over the place is address input with contact methods. The contact methods are then editable and an array. So in that case, after the user has finished entering contact methods, tabbing from a blank contact method type would typically take the user to the start of the next dialog.

How then is it intended to move between the dialogs as (ie as shown), without knowing what fields make up the 'active' dialogs and what dialogs are active? IE in this case, if postcode lookup is active, I may want to jump from the postcode field to the contact methods. But this is this case - elsewhere the field following the postcode may be a completely different field. Does that make sense?


* Screenshot at 2014-03-10 08:47:50 (Edited).png (109.97 KB, 1026x744 - viewed 2232 times.)
Stephen T.
Posts: 114


« Reply #19 on: March 10, 2014, 10:54:39 am »

Quote from: seb
Sorry but I get confused:
The principle of the INITIALIZER combobox attribute is to have the runtime system call the initializer function automatically when a form is loaded/displayed.

Here you write that you call "by hand" your combobox initializers from the MAIN module (through different other functions)...
What are you doing exactly in your code?
Why are you calling the combobox initializers explicitely?
Seb,
The combo boxes are primarily those that are loaded from the DB - so lookup codes, small lists of names etc.
The issue for us is that we allow the users to 'hotkey' to maintenance modules - ie the user is in a main claim entry, and they look at the claim analysis combo and want to add another entry. They can 'hotkey' (ext_hotkey_combos) to the module that maintains the analysis codes and add/change the details. The ext_reload_combos then detects underlying table changes and reloads the combos using ext_init_combos. So ext_init_combos is used on form initialization and again when the underlying data tables change.

Quote from: seb
Maybe you have this "ext_reload_combos" function that must be called in some particular case?
It's quite difficult to help without seeing the code.
Anyway, yes, assuming that ext_init_combos() is the initialization function defined in the INITIALIZER attribute, if that function was called once before OPEN FORM/DISPLAY FORM or OPEN WINDOW, the module containing this function is loaded, and then the function is available for the automatic combobox initialization call. But maybe you are doing the job twice.

But the problem is Seb is that it's now not being done at all (ie the form based initialisation) - no error appears to be  thrown, just that the combos aren't being populated. If I bolt the ext_init_combos code directly into the 'main' module (not IMPORTED, but physically added), then the FORM combo initializers work fine.
ext_init_combos was included in the old 42r because, instead of creating a dummy link as per Reuben, our hotkey function automatically then meant it was included in the linked objects. Now, using IMPORT FGL, the IMPORT of ext_init_combos is not in the main module, but two modules down and then does not appear to be being picked up by the FORM. 
Sebastien F.
Four Js
Posts: 545


« Reply #20 on: March 10, 2014, 05:38:15 pm »

Regarding combos initializers:
I repeat myself: A function from the same imported module of the initializer must be called before loading the form.
Having a call reference in the code is not sufficient, the program flow must go through a call, to load the module:
Imported modules are loaded dynamically on demand.
Seb
Sebastien F.
Four Js
Posts: 545


« Reply #21 on: March 10, 2014, 05:54:26 pm »

Regarding your next field case:
I see no other way except doing a DIALOG.nextField("field_name") + CONTINUE DIALOG, by naming the field explicitely.
NEXT FIELD NEXT / PREVIOUS will not work because when called in the context of an INPUT ARRAY (even in DIALOG), you stay in the same row.
Consider trying DISPLAY ARRAY + modification triggers, it may change a bit the ergonomics (you are no longer in "edit mode" in the lists and you must hit an action to modify/append rows, but it drastically simplifies the dialog coding: You certailty know that INPUT ARRAY programming was always quite difficult.
Seb
Stephen T.
Posts: 114


« Reply #22 on: March 10, 2014, 06:43:55 pm »

Quote from: Seb
Regarding combos initializers:
I repeat myself: A function from the same imported module of the initializer must be called before loading the form.
Having a call reference in the code is not sufficient, the program flow must go through a call, to load the module:
Imported modules are loaded dynamically on demand.

Seb,
I think I got that - but is that then a change in 2,50 in general or is it specifically tied to the use of the IMPORT FGL statements?
Stephen T.
Posts: 114


« Reply #23 on: March 10, 2014, 06:52:41 pm »

Quote from: Seb
Regarding your next field case:
I see no other way except doing a DIALOG.nextField("field_name") + CONTINUE DIALOG, by naming the field explicitely.
NEXT FIELD NEXT / PREVIOUS will not work because when called in the context of an INPUT ARRAY (even in DIALOG), you stay in the same row.
Consider trying DISPLAY ARRAY + modification triggers, it may change a bit the ergonomics (you are no longer in "edit mode" in the lists and you must hit an action to modify/append rows, but it drastically simplifies the dialog coding: You certailty know that INPUT ARRAY programming was always quite difficult.

OK - is there then anything planned to be able to interrogate the dialog structure and to be able to work out where in a complete dialog you are and which fields then follow or precede the current subdialog? If not I'll firm up the array based 'subdialog/field' mechanism that I've been playing with and implement it that way.
Sebastien F.
Four Js
Posts: 545


« Reply #24 on: March 11, 2014, 10:30:40 am »

Regarding IMPORT FGL, nothing changed in 2.50 in the module loading principle: At runtime these are loaded on demand.
Regading the NEXT FIELD need, no dialog introspection is planed.
Seb
Stephen T.
Posts: 114


« Reply #25 on: March 11, 2014, 11:31:59 am »

Seb,
Sorry to be a pain - but I still don't follow.
We had, in 2.4 using 'traditional' linking (ie 42r), the same code. IE the forms called ext_init_combos as the combo initializer. That function was also called via ext_hotkey_combos - ext_reload_combos. It worked fine - the forms found the function ok and the combo boxes were populated.

Under 2.5, the linking has been changed and IMPORT FGL used. The forms have not been altered - so still call ext_init_combos as the combo initializer - and the programs still refer to ext_init_combos via ext_hotkey_combos - ext_reload_combos. But the combos aren't being populated (OK I take on board I can get around the issue by calling the module that contains ext_init_combos before opening the forms) - but what is the cause of the issue in the first place?
Sebastien F.
Four Js
Posts: 545


« Reply #26 on: March 11, 2014, 11:47:26 am »

No prob Stephen...

Understand the different between a function that is referenced in the code and a function that is called at runtime (and obsiously referenced).

Code
  1. IF 1=0 THEN
  2.    CALL myfunction()  -- referenced, but will not be called at runtime
  3. END IF
  4. -- versus:
  5. CALL myfunction()  -- referenced, and will be called at runtime
  6.  

When using IMPORT FGL, modules are loaded on demand (i.e. when one of the module elements (function) is used/called.

According to your previous posts, the ext_reload_combos() is called only when the user wants to add items to the comboboxes.

When the form is loaded, ext_reload_combos() + ext_init_combos() are not yet called, hence the corresponding module is not yet loaded.

We are discussing the fact that combos initializers should load the module automatically, like an explicit CALL does.

Seb
Stephen T.
Posts: 114


« Reply #27 on: March 11, 2014, 01:29:30 pm »

Seb,
That is what I thought - but I must then have misunderstood your comment:
'...Regarding IMPORT FGL, nothing changed in 2.50 in the module loading principle: At runtime these are loaded on demand....'

As I took that to mean that it wasn't the IMPORT statements that were the difference.

Cheers Seb.
Sebastien F.
Four Js
Posts: 545


« Reply #28 on: March 11, 2014, 03:05:29 pm »

We have an ref in the bug database for IMPORT FGL + Combos INITIALIZER: bz#1709
Seb
Pages: 1 [2]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines