HMG4: start, quit, resource, localized

Moderator: Rathinagiri

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

HMG4: start, quit, resource, localized

Post by l3whmg » Fri Jul 01, 2011 7:59 pm

Hi friends.

I've found the way to introduce usage of QLocale: this can be useful to internationalize applications.
Also, I thought it best to manage start end (I'm referring to QApplication) in a different way: centralized.

I will expose later, but before I want fix some things:
- I want change from "s_qApp" to "s_oQtApp"
- I want change from "s_qRes" to "s_oQtRes"
- I want change from "oDefaultParent" to "s_oDefaultParent"
- I want change from "nObjectCounter" to "s_nObjectCounter"
- I want change from "oMainWindow" to "s_oMainWindow"
- I want change from "lGridCellFlag" to "s_lGridCellFlag"
- I want change from "application.prg" to "globshared.prg"
Why these changes?
First: these are all shared variables. Prefixing with "s_" we can catch immediatly in our sources; on the other hand look at the first two rows: when HMG4 start someone use it.
Second: I need to introduce other vars (ie bOnStartUp, bOnShutDown, etc. see the explanation below). With "s_" we can catch immediatly
Third: first two rows from "s_q..." to "s_oQt..." (there are other vars in sources... ie oFont). These are real QT object. I think: for every real Qt object we must use "oQt".
Fourth: because "application" can be misunderstood.

Tell me your opinion. If you are in agreement: I will do.

Well and now the other job.
I want create a HMGAPP class, source file hmgapp.prg OR APPLICATION class, source file application.prg; with this class we can:
1) start and stop Q... in a centralized way. examples: HMGAPP():Start() and HMGAPP():Quit()
2) test if Qt already started or not (adding "s_lQtStarted"). example: IF ::s_lQtStarted == .F. ; HMGAPP():Start() ; ENDIF (note this must/can be inserted in every New method)
3) have a startup procedure (adding "s_bOnStartUp") and/or a shutdown procedure (adding "s_bOnShutDown" ). example (inside Start method): IF hb_IsBlock( ::s_onStartUp ) == .T. ; EVAL( ::s_OnStartUp ) ; ENDIF
4) register resource without start Qapplication: this is a little trick. I preserve "RegisterResource" but this command need QApplication started
5) tell where are the Qt plugins (adding "s_cPlugInDir)
6) set localization. Warning. QT doc say (somewhere): you must set localization before starting GUI application.
Bingo: now HMG4 can do with a centralized starter (adding "s_nLanguage" and "s_nCountry")

FAQ:
A) when Qapplication is started? If we call HMGAPP():Start() or in any HMG object (obviously window.prg) with point 2)
B) when Qapplication end? We have two options:
- connecting the "QEvent_Close" event of the Main Window
ie ::oQTObject:connect( QEvent_Close, {|| HMGAPP():Quit() } ) )
OR
- calling HMG():Quit() inside main program
IMHO the last one it's better, why? Because WND_MAIN can not be the last window!

Tell me your opinion.

Best regards
Luigi from Italy
www.L3W.it

User avatar
Rathinagiri
Posts: 5263
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 169 times
Been thanked: 172 times
Contact:

Post by Rathinagiri » Sat Jul 02, 2011 3:37 am

Great going Luigi. I desperately require unicode implementation. I think what you are suggesting is for good only. Please go ahead.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Sat Jul 02, 2011 2:16 pm

Hi guys.
Today I do a commit, his number is 652. Here the changelog.
2011-07-11 15:30 UTC+0100 Luigi Ferraris ( <luigi at l3w.it> ) ! source/globshared.prg
! source/checkbox.prg
! source/combobox.prg
! source/control.prg
! source/datepicker.prg
! source/grid.prg
! source/ipaddress.prg
! source/printer.prg
! source/resource.prg
! source/spinner.prg
! source/textbox.prg
! source/virtualgrid.prg
! source/window.prg
! source/windowgroup.prg
! change shared var name from "s_qApp" to "s_oQtApp"
! change shared var name from "s_qRes" to "s_oQtRes"
! change shared var name from "oDefaultParent" to "s_oDefalutParent"
! change shared var name from "nObjectCounter" to "s_nObjectCounter"
! change shared var name from "oMainWindow" to "s_oMainWindow"
! change shared var name from "lGridCellFlag" to "s_lGridCellFlag"

! source/basic.prg
! source/globshared.prg
! source/printer.prg
! source/resource.prg
! change class name from "APPLICATION" to "GLOBSHARED"

! hmg.hbp
! change from "source/application.prg" to "source/globshared.prg"

+ source/globshared.prg
- source/application.prg
* changed source name to prevent misunderstood for the future
This is the first piece of my job. Now I wiil try to introduce the other part.

But it's most important that I know and understand this comment from window.prg

Code: Select all

   DATA bOnRelease                                INIT   {|| .T. }        // Must be an empty block.
Who write but why "Must be an empty block"?

I need to change code inside window.prg:
- into Create method I must add some lines

Code: Select all

......
// Nothing To Do
ELSEIF   ::nType == WND_MAIN   // Main
   IF VALTYPE( ::bOnRelease ) <> "B"  <====
      ::oQTObject:connect( QEvent_Close, {|| HMGAPP():quit() } ) <====
   ENDIF <====
ELSEIF   ::nType == WND_CHILD   // Child
......
I can't introduce my mod. because bOnRelease it's always a Block, but why can't be NIL? Where is the problem?

- into OnRelease method only a little change without problem

Code: Select all

......
IF ::nType == WND_MAIN
   ::oQTObject:connect( QEvent_Close, {|| ( EVAL( ::bOnRelease ), HMGAPP():quit() ) } )
ELSEIF ::nType == WND_MODAL
......
Inside Changelog I don't find any comment about "Must be an empty block". Please give me a answer.

Best regards
Luigi from Italy
www.L3W.it

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Sat Jul 02, 2011 2:33 pm

Hi, I've notice the same problem into the Create method for Modal window:

Code: Select all

........
   ELSEIF   ::nType == WND_MODAL   // Modal
      ::oQTObject:SetWindowModality( 2 )
      IF VALTYPE( ::bOnRelease ) <> "B"   <=====
         ::oQTObject:connect( QEvent_Close, {|| ::oEventLoop:Exit( 0 ) } )   <=====
      ENDIF   <=====
........
I think it's better to add these lines, but bOnrelease it's an empty block!

Best regards
Luigi from Italy
www.L3W.it

mrduck
Posts: 497
Joined: Fri Sep 10, 2010 5:22 pm

Post by mrduck » Sat Jul 02, 2011 3:43 pm

l3whmg wrote: But it's most important that I know and understand this comment from window.prg

Code: Select all

   DATA bOnRelease                                INIT   {|| .T. }        // Must be an empty block.
Who write but why "Must be an empty block"?
Because it is called somewhere without the need to check if it's NUL or a codeblock.

I was talking with Mauricio about this piece of code a couple of days ago. We were modifying this code snippet to intercept when a window is closed clicking on the X.

Rossine
Posts: 87
Joined: Thu Jun 30, 2011 10:04 pm

Post by Rossine » Sat Jul 02, 2011 4:31 pm

Hello All,

This my first post. Excuse me if I'm posting in the wrong place :D

I'm starting with hmg.4 here and did a FIX.

In window.prg I changed to evaluate a block in the output form:

Code: Select all


   // Events
...
   METHOD OnReleaseProcess                        SETGET && Rossine 29/06/11

/*----------------------------------------------------------------------*/

METHOD OnRelease( bValue ) CLASS WINDOW

   IF Pcount() == 0
      RETURN ::bOnRelease
   ELSEIF Pcount() == 1
      IF ::nType == WND_MAIN
         IF .NOT. ::oQTObject:connect( QEvent_Close, { |oEvent| iif( ::OnReleaseProcess( QEvent_Close, oEvent, bValue ), ::s_qApp:Quit(), NIL ) } ) && Rossine 29/06/11
            ::oQTObject:disconnect( QEvent_Close )
            IF .NOT. ::oQTObject:connect( QEvent_Close , { |oEvent|iif( ::OnReleaseProcess( QEvent_Close, oEvent, bValue ), ::s_qApp:Quit(), NIL ) } ) && Rossine 29/06/11
               // Error
            ENDIF
         ENDIF
      ELSEIF ::nType == WND_MODAL
         IF .NOT. ::oQTObject:connect( QEvent_Close , { |oEvent| iif( ::OnReleaseProcess( QEvent_Close, oEvent, bValue ), ::oEventLoop:Exit( 0 ), NIL ) } ) && Rossine 29/06/11
            ::oQTObject:disconnect( QEvent_Close )
            IF .NOT. ::oQTObject:connect( QEvent_Close , { |oEvent| iif( ::OnReleaseProcess( QEvent_Close, oEvent, bValue ), ::oEventLoop:Exit( 0 ), NIL ) } ) && Rossine 29/06/11
               // Error
            ENDIF
         ENDIF
      ELSE
         IF .NOT. ::oQTObject:connect( QEvent_Close , { ||( Eval( bValue ) )  } )
            ::oQTObject:disconnect( QEvent_Close )
            IF .NOT. ::oQTObject:connect( QEvent_Close , { ||( Eval( bValue ) )  } )
               // Error
            ENDIF
         ENDIF
      ENDIF
      ::bOnRelease := bValue
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD OnReleaseProcess( nEvent, oEvent, bValue ) CLASS WINDOW && Rossine 29/06/11

   local lReturnValue := .T.

   do case
      case nEvent == QEvent_Close
         lReturnValue := Eval( bValue )
         if ValType( lReturnValue ) == 'L'
            if lReturnValue
               oEvent:accept()
            else
               oEvent:ignore()
            endif
         else
            oEvent:accept()
         endif
   endcase

   return lReturnValue

Is this correct or is how this work better?

Sorry, I use google translator

Best Regards,

Rossine.

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Sat Jul 02, 2011 5:03 pm

Hi Rossine, please to meet you!

I read your code and some a few days ago I write of this with MrDuck.
IMHO, I think it's not a good idea - inside HMG4 library - check returned value of a block.
Why? Because in your program you want check .T. or .F. (accepted or rejected) or other value (accepted), but in my program I want check "1" or "2" (accepted or rejected) or other value (accepted). This is an example. Someone can add other pow.
What do you think about this example?

Best regards
Luigi from Italy
www.L3W.it

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Sat Jul 02, 2011 5:33 pm

Hi MrDuck.
I understand your answer, but I can figure out where bOnRelease must be an empty block. I find all "connect" where is OnClose but nothing.
Well, I can do a little trick but I must add a var.
lOnReleaseBlock set to .F. by default, inside OnRelease method lOnReleaseBlock set to .T. I can use this var to bypass my problem, but I don't like very much.

Best regards.
Luigi from Italy
www.L3W.it

mrduck
Posts: 497
Joined: Fri Sep 10, 2010 5:22 pm

Post by mrduck » Sat Jul 02, 2011 9:27 pm

Hi Rossine

I'm in talks with concentra about this matter, correct handling of close and release events. I hope Mauricio reads this thread and can get some ideas from your code.

please note that in similar cases the method was called DoOnXXXX instead of onXXXXProcess

Why did you pass the event type ? who also can call that method ? perhaps all these helper methods should be turned private....


Thanks and welcome

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Sun Jul 03, 2011 9:58 am

Hi friends, I do a new commit with the second part of my job.
+ samples/agoodstart
+ samples/agoodstart/build.bat
+ samples/agoodstart/demo_1.hbp
+ samples/agoodstart/demo_1.prg
+ samples/agoodstart/demo_1.qrc
+ samples/agoodstart/demo_2.hbp
+ samples/agoodstart/demo_2.prg
+ samples/agoodstart/demo_2.qrc
+ samples/agoodstart/hbmk.hbm
+ samples/agoodstart/other_res1.qrc
+ samples/agoodstart/other_res2.qrc
+ samples/agoodstart/other_res3.qrc
+ samples/agoodstart/other_res4.qrc
+ samples/agoodstart/qt.conf
+ samples/agoodstart/resource
+ samples/agoodstart/resource/exit.png
+ samples/agoodstart/resource/find.png
+ samples/agoodstart/resource/hmg.png
+ samples/agoodstart/resource/print.png
+ samples/agoodstart/resource/save.png
* to show usage of new hmgapp class and methods

! source/window.prg
! source/windowgroup.prg
* change default value of bOnrelease from {||.T.} to NIL
empty block by default
* change OnRelease and Create methods in according with new hmgapp class
to handle hmgapp():Quit() method
* clean code
! fixed check valtype in every method setget before assign
; TODO: in every source we must do this work!

! source/basic.prg
! source/control.prg
! source/window.prg
+ inside New method check "s_lQtStarted" status;
if false call HMGAPP():Start()

* include/hmg.ch
* command SET RESOURCE TO changed in according with new hmgapp():Resources()
+ command SET QTLOCALE TO in according with new hmgapp():Localized()
+ translate QTLANGUAGE in according with new hmgapp():Language()
+ translate QTCOUNTRY in according with new hmgapp():Country()
+ command STARTUP in according with new hmgapp():Start()
+ command SHUTDOWN in according with new hmgapp():Quit()
+ command ADDQTRESOURCE in according with new hmgapp():RegisterResource()
+ command SET ONSHUTDOWN TO in according with new hmgapp():OnShutDown()
+ command SET ONSTARTUP TO in according with new hmgapp():OnStartUp()
! fixed some Xbase command to respect rule

! source/globshared.prg
- removed New method. unusefull here, see new hmgapp class
- removed HMG4_Reset() function. see hmgapp class, Reset() method
+ add shared vars: s_nCountry, s_nLanguage, s_bOnShutDown, s_bOnStartUp,
s_cPlugInDir, s_oQtLocale, s_lQtStarted

+ include/hmg_qtimage.ch
+ include/hmg_qtlocale.ch
* These sources contain definitions used by QT library. At this moment the
are not present in HbQt library.
; hmg_qtimage: to manage image with QPainter
; hmg_qtlocale: to manage language and country
; TODO These files can be removed when library "HbQT" will contain that

* hmg.hbp
+ hmgapp.prg
- resource.prg

- source/resource.prg
* unused. see new hmgapp class and methods

+ source/hmgapp.prg
* add hmgapp class and methods

* changelog
* fixed wrong data of my previous 652 commit
To show new usage of HMGAPP class, I create "samples/agoodstart" folder. Here you can look the new implementation; a special look to "Localized" method.
I compile and check other demo (winmain, winmodal and resource folders): all work well. I have been able to verify the compatibility of previous programs.

Note: I change bOnRelease value from empty block to NIL. I think this is the right way.

On the other hand, you can look inside window.prg: I've fixed a lot of code when value must be assigned adding check of VALTYPE. I think this must be a must in every source.

IMHO I think it's better to reord source code: please take a look at hmgapp.prg.

Now I want change method to have THISWINDOW and remove "MEMVAR __cActiveWindow". Why? First: I think this is a dangerous method (MEMVAR). Second: I have found some problems somewhere with this. I've already do an experiment with my fork and work well.

Then, I want rewrite menu manager. Also this, to remove use of many vars (see GetPopupVarName). I've already do an experiment with my fork and work well.

Please: use /w3 option during compilation. I have found demo with errors This is another reason to change use of MEMVAR...

Best regards
Luigi from Italy
www.L3W.it

Post Reply