Rework

With version 4.2, I turned my attention to facilitating rework in PAGE. That is, how do you use PAGE to tweak the GUI without loosing the supporting code that you have written? At the same time I want to allow one to view the changes with the run command button in the Python console.

Here is the situation. You built a GUI and generated the Python file, which created skeleton functions in that file. You then fleshed out the skeleton functions to support the GUI and then decided to modify the GUI. If then you again generate the Python code for the GUI, you will have replaced the filled-out functions with new skeleton functions loosing the code you wrote. This is the rework problem: How to save your hard fought code when reworking the GUI.

What needs to be done is to separate as completely as possible the automatically generated GUI code from the added support code. I have made some changes that move in that direction in version 4.2.

My answer is to separate the generation of the GUI code from the supporting code by placing the support portion of the automatically generated code into a separately generated module to be imported by the GUI module. That is, now PAGE generates two modules, one for the GUI and one for the supporting code complete with the necessary linkage.

PAGE implements this schema as follows. Heretofore, a GUI built with PAGE was associated with two files, “<name>.tcl” which is the file suitable for input to PAGE, and “<name>.py” which is output of PAGE containing the Python code for creating the GUI object and skeleton functions and Tkinter variables utilized by the GUI. In the new scheme, the skeleton functions and Tkinter variables are generated in the new file “<name>_support.py” rather than in “<name>.py”. A new item, Generate Import Module, has been added to the Gen_Python submenu of the main menu which generates “<name>_support.py”. The new support file is presumably only generated once and is where the bulk of the code realizing the application is written. “<name>” is the application name selected by the user when the system saves the ”.tcl” or extracted from the file name which may be supplied when invoking PAGE.

Thus, one may alter the “<name>.py” using PAGE without changing the “<name>_support.py”. Of course, if the user changes the GUI to refer to new callback functions or Tkinter variables, then those will have to be manually added to the support module. The style of the skeleton functions and TK variable additions is pretty simple so that they are easy to add manually.

Generation of either Python module will probably attempt to save the tcl file and in do so may ask if you really want to save it. If you do not answer “yes” the root file name may not be known and bad code will be generated.

Let me repeat: You should only generate the support module once; otherwise any code which you added will be lost. Well, just in case you do that inadvertently, PAGE will save some previous versions as backups. If you add new features specifying new callback functions or new Tk variables you will have to add them manually to the supporting module. Also, when saving the support module it will test to see if a support module with the same name exists and if it does, it will question the user as to whether he wishes to continue.

See the WCPE directory in the examples directory. This is a program that displays the program of WCPE which is one of my favorite classical music stations. In this example all of the functional code is located in WCPE_support.py and the GUI is defined in WCPE.py which is the main module. I found it very tricky to deal with time zones and did not want to loose any of that code and have to redo it or to deal with diff’s ; at the same time, I was constantly tweaking the GUI. I generated the import module once and proceeded fill out the init function and the callback functions in WCPE_support.py while tweaking the GUI, i.e., changing its location, color, the size of the display fields, etc..

Also, in the examples directory, you should compare the progress_bar and the rework_progress_bar. The directory rework_progress_bar contains the changes that I made to the files in progress_bar to conform to the new rework scheme. It may be instructive in that it exemplifies an application comprised of two top level windows where one of the windows accesses Tkinter variables in the second window.

With chagrin, I apologize to PAGE user for not having thought of this solution to rework long ago. Even though I have tested the idea with several examples, some of which are included in the section on examples, I worry that I have overlooked something big. So if you find any problems or oversights, please let me know.

Automatic Saving of Modules

One possibly confusing aspect of PAGE is the saving of the three files associated with a PAGE GUI:

  • The tcl file which is the input to the “working” file of PAGE.
  • The Python code generated defining the GUI object.
  • The Python support file containing much of the boiler plate and skeleton functions.

As stated elsewhere the root name is derived from the name of the tcl file. The Python GUI root name is the same as that of the tcl file and the Python support module is that root name concatenated with “_support”.

There are several mechanisms for saving. In addition as noted in the last section, if one attempts to save a support module and one exists, PAGE will inquire whether to con tine the save. This is a feature which might protect a manually coded module.

Save Command in the Menu

When File->Save or File->Save As is selected then the tcl file is saved provided the GUI has changed since the last save action. The previous version of the tcl file is made a backup file.

Save Button in the Python Console

When the Save button in the Console file is selected, the tcl file is saved as above if there has been a change to GUI. Also, the content of the top window of the Python Console is saved if it is different from the last version of the code was saved. That is, if the Python console contains GUI code then the GUI module will be saved if it has been modified since the last safe of the GUI code in the current PAGE invocation. Similarly for the case of the support module being in the Python Console. The Python modules will create backups of existing corresponding modules.

Run Button in the Python Console

When the Run button is selected the code in the Python Console will be saved if it differs from the last save in the current invocation of PAGE. This is necessary because the code is execute by invoking the Python Interpreter against the saved file. Running the Python GUI code will show the actual GUI. If the Run button is selected then the GUI program will be executed. Obviously it will fail if there is no support module.

The logic which I have implemented is fairly complex; I have included below the code which is part of PAGE.

proc vTcl:test_file_content {filename new_content} {
    # Function to determine if we can safely skip the save function.
    # A return value of 0 means that we can skip the actual save.
    # A return value of 1 means that we must save.
    global vTcl
    set save 1
    set skip 0
    # If the Python file does not exist, we clearly have to save it.
    if {[file exists $filename] == 0} {
        return $save
    }
    # If we have edited the Python Console code window, we have to save.
    set modified [$vTcl(code_window) edit modified]
    if {$modified} {
        return $save
    }
    # If the content of the code window is unchanged, we can skip the save.
    if {$new_content == $vTcl(last_save,$vTcl(python_module))} {
        return $skip     ;# Skip the save.
    }
    # If we got this far then we want to save.
    return $save     ;# Do the save.

}

Note that every time that the Python code for either the GUI or the support module is generated the new module will include a current timestamp and so comparing will two generations will always differ if only in the timestamps. Without the timestamps I could probably reduce the number of saves and backup files, but I think the timestamps are very valuable.

Automatic Save at Code Generation

When code has been generated by either Control-i for Control-p, the tcl code for the GUI will be saved if it has changed. Code for the Support module is automatically saved also because it may not be the case that one would attempt to execute that module for reasons given above. The Python code for the GUI is also saved upon generation.

Prior to version 4.2.3, the Python code for the GUI was not saved unless the user selected the Save or Run buttons on the Python Console. For consistency, now both the GUI and the support modules are saved upon generation.

Automatic Save at PAGE Exit

When PAGE is closed by either Quit, Control-q, or Control-c, the save action is the same as for the File->Save. Only changes to the GUI tcl file is changed.