├── .gitignore ├── LICENSE ├── Packages ├── Delphi10Berlin │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj ├── Delphi10Rio │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj ├── Delphi10Seattle │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj ├── Delphi10Sydney │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj ├── Delphi10Tokyo │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj ├── Delphi11Alexandria │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj └── Delphi12Athens │ ├── dclDelphi4PythonExperts.dpk │ └── dclDelphi4PythonExperts.dproj ├── README.md ├── Samples ├── Simple_Demo │ ├── D4P_export_demo.dpr │ ├── D4P_export_demo.dproj │ ├── Python_Export │ │ ├── Export_forms_separately │ │ │ ├── child_window.py │ │ │ ├── child_window.pyfmx │ │ │ ├── parent_window.py │ │ │ └── parent_window.pyfmx │ │ └── Export_whole_project │ │ │ ├── D4P_export_demo.py │ │ │ ├── child_window.py │ │ │ ├── child_window.pyfmx │ │ │ ├── parent_window.py │ │ │ └── parent_window.pyfmx │ ├── child_window.fmx │ ├── child_window.pas │ ├── parent_window.fmx │ └── parent_window.pas └── TipCalculator │ ├── AndroidManifest.template.xml │ ├── Python_Export │ ├── Modified_TipMain │ │ ├── TipCalculator.py │ │ ├── TipMain.py │ │ └── TipMain.pyfmx │ ├── TipCalculator.py │ ├── TipMain.py │ └── TipMain.pyfmx │ ├── TipCalculator.deployproj │ ├── TipCalculator.dpr │ ├── TipCalculator.dproj │ ├── TipCalculator.res │ ├── TipMain.fmx │ └── TipMain.pas ├── Source ├── Design │ ├── PythonTools.Design.Forms.dfm │ ├── PythonTools.Design.Forms.pas │ ├── PythonTools.Design.Project.dfm │ ├── PythonTools.Design.Project.pas │ ├── PythonTools.Design.dfm │ └── PythonTools.Design.pas ├── Exporter │ ├── PythonTools.Exporter.Application.pas │ ├── PythonTools.Exporter.Form.pas │ ├── PythonTools.Exporter.Forms.pas │ └── PythonTools.Exporter.Project.pas ├── Menu │ ├── PythonTools.Menu.ExportForms.pas │ ├── PythonTools.Menu.ExportProject.pas │ └── PythonTools.Menu.pas ├── Model │ ├── Design │ │ ├── PythonTools.Model.Design.Forms.pas │ │ └── PythonTools.Model.Design.Project.pas │ └── Producer │ │ ├── PythonTools.Model.Producer.Application.pas │ │ ├── PythonTools.Model.Producer.Form.pas │ │ ├── PythonTools.Model.Producer.FormFile.pas │ │ └── PythonTools.Model.Producer.pas ├── Producer │ ├── PythonTools.Producer.AbstractForm.pas │ ├── PythonTools.Producer.FMXForm.pas │ ├── PythonTools.Producer.SimpleFactory.pas │ ├── PythonTools.Producer.VCLForm.pas │ └── PythonTools.Producer.pas ├── PythonTools.Common.pas ├── PythonTools.Exceptions.pas ├── PythonTools.IOTAUtils.pas ├── PythonTools.Registration.pas ├── PythonTools.Registry.pas ├── PythonTools.SplashScreen.pas └── PythonTools.inc ├── Tests ├── FMX.Producer.Test.pas ├── PythonExporterTest.dpr ├── PythonExporterTest.dproj ├── VCL.Producer.Test.pas └── data │ ├── Data.FMXForm.fmx │ ├── Data.FMXForm.pas │ ├── Data.VCLForm.dfm │ └── Data.VCLForm.pas └── images ├── EmbarcaderoPython(154px).png ├── EmbarcaderoPython(16px).bmp ├── EmbarcaderoPython(16px).png ├── EmbarcaderoPython(24px).bmp ├── EmbarcaderoPython(24px).png ├── Export2Python.png ├── ExportCurrentProject.png ├── ExportForms.png └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | *.vlb 48 | 49 | # Delphi autogenerated files (duplicated info) 50 | *.cfg 51 | *.hpp 52 | *Resource.rc 53 | 54 | # Delphi local files (user-specific info) 55 | *.local 56 | *.identcache 57 | *.projdata 58 | *.tvsconfig 59 | *.dsk 60 | 61 | # Delphi history and backups 62 | __history/ 63 | __recovery/ 64 | *.~* 65 | 66 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 67 | *.stat 68 | 69 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss 70 | modules/ 71 | 72 | # Library folder 73 | /Library -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Embarcadero Technologies 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Packages/Delphi10Berlin/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | 3 | {$R *.res} 4 | {$R *.dres} 5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 6 | {$ALIGN 8} 7 | {$ASSERTIONS ON} 8 | {$BOOLEVAL OFF} 9 | {$DEBUGINFO OFF} 10 | {$EXTENDEDSYNTAX ON} 11 | {$IMPORTEDDATA ON} 12 | {$IOCHECKS ON} 13 | {$LOCALSYMBOLS ON} 14 | {$LONGSTRINGS ON} 15 | {$OPENSTRINGS ON} 16 | {$OPTIMIZATION OFF} 17 | {$OVERFLOWCHECKS OFF} 18 | {$RANGECHECKS OFF} 19 | {$REFERENCEINFO ON} 20 | {$SAFEDIVIDE OFF} 21 | {$STACKFRAMES ON} 22 | {$TYPEDADDRESS OFF} 23 | {$VARSTRINGCHECKS ON} 24 | {$WRITEABLECONST OFF} 25 | {$MINENUMSIZE 1} 26 | {$IMAGEBASE $400000} 27 | {$DEFINE DEBUG} 28 | {$ENDIF IMPLICITBUILDING} 29 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 30 | {$LIBSUFFIX '240'} 31 | {$DESIGNONLY} 32 | {$IMPLICITBUILD ON} 33 | 34 | requires 35 | rtl, 36 | designide, 37 | fmx, 38 | vcl, 39 | dbrtl, 40 | vcldb, 41 | dsnap, 42 | vclwinx; 43 | 44 | contains 45 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 46 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 47 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 48 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 49 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 50 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 51 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 52 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 53 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 54 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 55 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 56 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 57 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 58 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 59 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 60 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 61 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 62 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 63 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 64 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 65 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 66 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 67 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 68 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 69 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 70 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}; 71 | 72 | end. 73 | -------------------------------------------------------------------------------- /Packages/Delphi10Rio/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | 3 | {$R *.res} 4 | {$R *.dres} 5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 6 | {$ALIGN 8} 7 | {$ASSERTIONS ON} 8 | {$BOOLEVAL OFF} 9 | {$DEBUGINFO OFF} 10 | {$EXTENDEDSYNTAX ON} 11 | {$IMPORTEDDATA ON} 12 | {$IOCHECKS ON} 13 | {$LOCALSYMBOLS ON} 14 | {$LONGSTRINGS ON} 15 | {$OPENSTRINGS ON} 16 | {$OPTIMIZATION OFF} 17 | {$OVERFLOWCHECKS OFF} 18 | {$RANGECHECKS OFF} 19 | {$REFERENCEINFO ON} 20 | {$SAFEDIVIDE OFF} 21 | {$STACKFRAMES ON} 22 | {$TYPEDADDRESS OFF} 23 | {$VARSTRINGCHECKS ON} 24 | {$WRITEABLECONST OFF} 25 | {$MINENUMSIZE 1} 26 | {$IMAGEBASE $400000} 27 | {$DEFINE DEBUG} 28 | {$ENDIF IMPLICITBUILDING} 29 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 30 | {$LIBSUFFIX '260'} 31 | {$DESIGNONLY} 32 | {$IMPLICITBUILD ON} 33 | 34 | requires 35 | rtl, 36 | designide, 37 | fmx, 38 | vcl, 39 | dbrtl, 40 | vcldb, 41 | dsnap, 42 | vclwinx; 43 | 44 | contains 45 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 46 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 47 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 48 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 49 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 50 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 51 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 52 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 53 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 54 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 55 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 56 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 57 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 58 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 59 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 60 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 61 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 62 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 63 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 64 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 65 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 66 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 67 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 68 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 69 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 70 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}; 71 | 72 | end. 73 | -------------------------------------------------------------------------------- /Packages/Delphi10Seattle/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | 3 | {$R *.res} 4 | {$R *.dres} 5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 6 | {$ALIGN 8} 7 | {$ASSERTIONS ON} 8 | {$BOOLEVAL OFF} 9 | {$DEBUGINFO OFF} 10 | {$EXTENDEDSYNTAX ON} 11 | {$IMPORTEDDATA ON} 12 | {$IOCHECKS ON} 13 | {$LOCALSYMBOLS ON} 14 | {$LONGSTRINGS ON} 15 | {$OPENSTRINGS ON} 16 | {$OPTIMIZATION OFF} 17 | {$OVERFLOWCHECKS OFF} 18 | {$RANGECHECKS OFF} 19 | {$REFERENCEINFO ON} 20 | {$SAFEDIVIDE OFF} 21 | {$STACKFRAMES ON} 22 | {$TYPEDADDRESS OFF} 23 | {$VARSTRINGCHECKS ON} 24 | {$WRITEABLECONST OFF} 25 | {$MINENUMSIZE 1} 26 | {$IMAGEBASE $400000} 27 | {$DEFINE DEBUG} 28 | {$ENDIF IMPLICITBUILDING} 29 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 30 | {$LIBSUFFIX '230'} 31 | {$DESIGNONLY} 32 | {$IMPLICITBUILD ON} 33 | 34 | requires 35 | rtl, 36 | designide, 37 | fmx, 38 | vcl, 39 | dbrtl, 40 | vcldb, 41 | dsnap, 42 | vclwinx; 43 | 44 | contains 45 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 46 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 47 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 48 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 49 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 50 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 51 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 52 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 53 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 54 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 55 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 56 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 57 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 58 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 59 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 60 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 61 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 62 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 63 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 64 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 65 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 66 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 67 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 68 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 69 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 70 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}; 71 | 72 | end. 73 | -------------------------------------------------------------------------------- /Packages/Delphi10Sydney/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | 3 | {$R *.res} 4 | {$R *.dres} 5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 6 | {$ALIGN 8} 7 | {$ASSERTIONS ON} 8 | {$BOOLEVAL OFF} 9 | {$DEBUGINFO OFF} 10 | {$EXTENDEDSYNTAX ON} 11 | {$IMPORTEDDATA ON} 12 | {$IOCHECKS ON} 13 | {$LOCALSYMBOLS ON} 14 | {$LONGSTRINGS ON} 15 | {$OPENSTRINGS ON} 16 | {$OPTIMIZATION OFF} 17 | {$OVERFLOWCHECKS OFF} 18 | {$RANGECHECKS OFF} 19 | {$REFERENCEINFO ON} 20 | {$SAFEDIVIDE OFF} 21 | {$STACKFRAMES ON} 22 | {$TYPEDADDRESS OFF} 23 | {$VARSTRINGCHECKS ON} 24 | {$WRITEABLECONST OFF} 25 | {$MINENUMSIZE 1} 26 | {$IMAGEBASE $400000} 27 | {$DEFINE DEBUG} 28 | {$ENDIF IMPLICITBUILDING} 29 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 30 | {$LIBSUFFIX '270'} 31 | {$DESIGNONLY} 32 | {$IMPLICITBUILD ON} 33 | 34 | requires 35 | rtl, 36 | designide, 37 | fmx, 38 | vcl, 39 | dbrtl, 40 | vcldb, 41 | dsnap; 42 | 43 | contains 44 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 45 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 46 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 47 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 48 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 49 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 50 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 51 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 52 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 53 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 54 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 55 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 56 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 57 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 58 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 59 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 60 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 61 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 62 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 63 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 64 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 65 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 66 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 67 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 68 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 69 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}; 70 | 71 | end. 72 | -------------------------------------------------------------------------------- /Packages/Delphi10Tokyo/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | 3 | {$R *.res} 4 | {$R *.dres} 5 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 6 | {$ALIGN 8} 7 | {$ASSERTIONS ON} 8 | {$BOOLEVAL OFF} 9 | {$DEBUGINFO OFF} 10 | {$EXTENDEDSYNTAX ON} 11 | {$IMPORTEDDATA ON} 12 | {$IOCHECKS ON} 13 | {$LOCALSYMBOLS ON} 14 | {$LONGSTRINGS ON} 15 | {$OPENSTRINGS ON} 16 | {$OPTIMIZATION OFF} 17 | {$OVERFLOWCHECKS OFF} 18 | {$RANGECHECKS OFF} 19 | {$REFERENCEINFO ON} 20 | {$SAFEDIVIDE OFF} 21 | {$STACKFRAMES ON} 22 | {$TYPEDADDRESS OFF} 23 | {$VARSTRINGCHECKS ON} 24 | {$WRITEABLECONST OFF} 25 | {$MINENUMSIZE 1} 26 | {$IMAGEBASE $400000} 27 | {$DEFINE DEBUG} 28 | {$ENDIF IMPLICITBUILDING} 29 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 30 | {$LIBSUFFIX '250'} 31 | {$DESIGNONLY} 32 | {$IMPLICITBUILD ON} 33 | 34 | requires 35 | rtl, 36 | designide, 37 | fmx, 38 | vcl, 39 | dbrtl, 40 | vcldb, 41 | dsnap, 42 | vclwinx; 43 | 44 | contains 45 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 46 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 47 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 48 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 49 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 50 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 51 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 52 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 53 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 54 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 55 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 56 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 57 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 58 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 59 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 60 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 61 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 62 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 63 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 64 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 65 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 66 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 67 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 68 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 69 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 70 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}; 71 | 72 | end. 73 | -------------------------------------------------------------------------------- /Packages/Delphi11Alexandria/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | {$R *.res} 3 | {$R *.dres} 4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 5 | {$ALIGN 8} 6 | {$ASSERTIONS ON} 7 | {$BOOLEVAL OFF} 8 | {$DEBUGINFO OFF} 9 | {$EXTENDEDSYNTAX ON} 10 | {$IMPORTEDDATA ON} 11 | {$IOCHECKS ON} 12 | {$LOCALSYMBOLS OFF} 13 | {$LONGSTRINGS ON} 14 | {$OPENSTRINGS ON} 15 | {$OPTIMIZATION ON} 16 | {$OVERFLOWCHECKS OFF} 17 | {$RANGECHECKS OFF} 18 | {$REFERENCEINFO OFF} 19 | {$SAFEDIVIDE OFF} 20 | {$STACKFRAMES OFF} 21 | {$TYPEDADDRESS OFF} 22 | {$VARSTRINGCHECKS ON} 23 | {$WRITEABLECONST OFF} 24 | {$MINENUMSIZE 1} 25 | {$IMAGEBASE $400000} 26 | {$DEFINE RELEASE} 27 | {$ENDIF IMPLICITBUILDING} 28 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 29 | {$LIBSUFFIX AUTO} 30 | {$DESIGNONLY} 31 | {$IMPLICITBUILD ON} 32 | 33 | requires 34 | rtl, 35 | designide, 36 | fmx, 37 | vcl, 38 | dbrtl, 39 | vcldb, 40 | dsnap; 41 | 42 | contains 43 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 44 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 45 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 46 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 47 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 48 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 49 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 50 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 51 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 52 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 53 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 54 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 55 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 56 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 57 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 58 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 59 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 60 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 61 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 62 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 63 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 64 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 65 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 66 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 67 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 68 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}, 69 | PythonTools.Model.Producer in '..\..\Source\Model\Producer\PythonTools.Model.Producer.pas'; 70 | 71 | end. 72 | -------------------------------------------------------------------------------- /Packages/Delphi12Athens/dclDelphi4PythonExperts.dpk: -------------------------------------------------------------------------------- 1 | package dclDelphi4PythonExperts; 2 | {$R *.res} 3 | {$R *.dres} 4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 5 | {$ALIGN 8} 6 | {$ASSERTIONS ON} 7 | {$BOOLEVAL OFF} 8 | {$DEBUGINFO OFF} 9 | {$EXTENDEDSYNTAX ON} 10 | {$IMPORTEDDATA ON} 11 | {$IOCHECKS ON} 12 | {$LOCALSYMBOLS OFF} 13 | {$LONGSTRINGS ON} 14 | {$OPENSTRINGS ON} 15 | {$OPTIMIZATION ON} 16 | {$OVERFLOWCHECKS OFF} 17 | {$RANGECHECKS OFF} 18 | {$REFERENCEINFO OFF} 19 | {$SAFEDIVIDE OFF} 20 | {$STACKFRAMES OFF} 21 | {$TYPEDADDRESS OFF} 22 | {$VARSTRINGCHECKS ON} 23 | {$WRITEABLECONST OFF} 24 | {$MINENUMSIZE 1} 25 | {$IMAGEBASE $400000} 26 | {$DEFINE RELEASE} 27 | {$ENDIF IMPLICITBUILDING} 28 | {$DESCRIPTION 'Delphi4Python - Export forms for Python'} 29 | {$LIBSUFFIX AUTO} 30 | {$DESIGNONLY} 31 | {$IMPLICITBUILD ON} 32 | 33 | requires 34 | rtl, 35 | designide, 36 | fmx, 37 | vcl, 38 | dbrtl, 39 | vcldb, 40 | dsnap; 41 | 42 | contains 43 | PythonTools.Registration in '..\..\Source\PythonTools.Registration.pas', 44 | PythonTools.SplashScreen in '..\..\Source\PythonTools.SplashScreen.pas', 45 | PythonTools.IOTAUtils in '..\..\Source\PythonTools.IOTAUtils.pas', 46 | PythonTools.Exceptions in '..\..\Source\PythonTools.Exceptions.pas', 47 | PythonTools.Common in '..\..\Source\PythonTools.Common.pas', 48 | PythonTools.Menu in '..\..\Source\Menu\PythonTools.Menu.pas', 49 | PythonTools.Menu.ExportProject in '..\..\Source\Menu\PythonTools.Menu.ExportProject.pas', 50 | PythonTools.Menu.ExportForms in '..\..\Source\Menu\PythonTools.Menu.ExportForms.pas', 51 | PythonTools.Design.Project in '..\..\Source\Design\PythonTools.Design.Project.pas' {ProjectExportDialog}, 52 | PythonTools.Exporter.Application in '..\..\Source\Exporter\PythonTools.Exporter.Application.pas', 53 | PythonTools.Exporter.Form in '..\..\Source\Exporter\PythonTools.Exporter.Form.pas', 54 | PythonTools.Exporter.Project in '..\..\Source\Exporter\PythonTools.Exporter.Project.pas', 55 | PythonTools.Producer.FMXForm in '..\..\Source\Producer\PythonTools.Producer.FMXForm.pas', 56 | PythonTools.Producer in '..\..\Source\Producer\PythonTools.Producer.pas', 57 | PythonTools.Producer.SimpleFactory in '..\..\Source\Producer\PythonTools.Producer.SimpleFactory.pas', 58 | PythonTools.Producer.VCLForm in '..\..\Source\Producer\PythonTools.Producer.VCLForm.pas', 59 | PythonTools.Producer.AbstractForm in '..\..\Source\Producer\PythonTools.Producer.AbstractForm.pas', 60 | PythonTools.Design.Forms in '..\..\Source\Design\PythonTools.Design.Forms.pas' {FormsExportDialog}, 61 | PythonTools.Exporter.Forms in '..\..\Source\Exporter\PythonTools.Exporter.Forms.pas', 62 | PythonTools.Model.Producer.Application in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Application.pas', 63 | PythonTools.Model.Producer.FormFile in '..\..\Source\Model\Producer\PythonTools.Model.Producer.FormFile.pas', 64 | PythonTools.Model.Producer.Form in '..\..\Source\Model\Producer\PythonTools.Model.Producer.Form.pas', 65 | PythonTools.Model.Design.Forms in '..\..\Source\Model\Design\PythonTools.Model.Design.Forms.pas', 66 | PythonTools.Model.Design.Project in '..\..\Source\Model\Design\PythonTools.Model.Design.Project.pas', 67 | PythonTools.Registry in '..\..\Source\PythonTools.Registry.pas', 68 | PythonTools.Design in '..\..\Source\Design\PythonTools.Design.pas' {DesignForm}, 69 | PythonTools.Model.Producer in '..\..\Source\Model\Producer\PythonTools.Model.Producer.pas'; 70 | 71 | end. 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Delphi4PythonExporterPython for Delphi Exporter 2 | For use with [DelphiFMX4Python](https://github.com/Embarcadero/DelphiFMX4Python) or [DelphiVCL4Python](https://github.com/Embarcadero/DelphiVCL4Python). 3 | 4 | Design your Python GUI using Delphi's VCL and FMX designers and then export them for Python use. 5 | 6 | ## eBook, Webinar, and Styles Bundle 7 | 8 | There is an free [eBook and styles bundle](https://embt.co/PythonGUIBundle) with 29 custom styles and 50 pages of content. 9 | Download the free eBook and Python styles bundle. 10 | 11 | ## Usage 12 | 13 | Install this Export in Delphi, C++Builder, or RAD Studio 11 Alexandria. Design your GUI forms with VCL or FireMonkey (FMX) and then select **Tools** -> **Export to Python**. 14 | 15 | The easiest way to install is via the [GetIt Package Manager](https://getitnow.embarcadero.com/?q=Delphi4PythonExporter). Instructions for [installing via GetIt](https://docwiki.embarcadero.com/RADStudio/en/Installing_a_Package_Using_GetIt_Package_Manager). 16 | 17 | ![Export2Python](https://github.com/Embarcadero/Delphi4PythonExporter/raw/main/images/Export2Python.png) 18 | 19 | ![Export2Python](https://github.com/Embarcadero/Delphi4PythonExporter/raw/main/images/ExportCurrentProject.png) 20 | 21 | * Text format is easier to edit 22 | * Binary format is more space efficient 23 | 24 | ![Export2Python](https://github.com/Embarcadero/Delphi4PythonExporter/raw/main/images/ExportForms.png) 25 | 26 | Powered by [Python4Delphi](https://github.com/Embarcadero/python4delphi) and [Embarcadero Delphi](https://embarcadero.com/products/delphi). 27 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/D4P_export_demo.dpr: -------------------------------------------------------------------------------- 1 | program D4P_export_demo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | parent_window in 'parent_window.pas' {Parent_Form}, 7 | child_window in 'child_window.pas' {Child_Form}; 8 | 9 | {$R *.res} 10 | 11 | begin 12 | Application.Initialize; 13 | Application.CreateForm(TParent_Form, Parent_Form); 14 | Application.CreateForm(TChild_Form, Child_Form); 15 | Application.Run; 16 | end. 17 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_forms_separately/child_window.py: -------------------------------------------------------------------------------- 1 | import os 2 | from delphifmx import * 3 | 4 | class Child_Form(Form): 5 | 6 | def __init__(self, owner): 7 | self.child_heading = None 8 | self.result_text_heading = None 9 | self.result_text_label = None 10 | self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "child_window.pyfmx")) -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_forms_separately/child_window.pyfmx: -------------------------------------------------------------------------------- 1 | object Child_Form: TChild_Form 2 | Left = 0 3 | Top = 0 4 | Caption = 'Child Window' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object child_heading: TLabel 12 | StyledSettings = [Family, FontColor] 13 | Position.X = 192.000000000000000000 14 | Position.Y = 40.000000000000000000 15 | Size.Width = 161.000000000000000000 16 | Size.Height = 41.000000000000000000 17 | Size.PlatformDefault = False 18 | TextSettings.Font.Size = 20.000000000000000000 19 | TextSettings.Font.StyleExt = {00070000000000000004000000} 20 | Text = 'I'#39'm a child form' 21 | TabOrder = 0 22 | end 23 | object result_text_heading: TLabel 24 | Position.X = 16.000000000000000000 25 | Position.Y = 128.000000000000000000 26 | Size.Width = 201.000000000000000000 27 | Size.Height = 17.000000000000000000 28 | Size.PlatformDefault = False 29 | Text = 'Text you entered in the Mainform is:' 30 | TabOrder = 1 31 | end 32 | object result_text_label: TLabel 33 | Position.X = 225.000000000000000000 34 | Position.Y = 128.000000000000000000 35 | Size.Width = 384.000000000000000000 36 | Size.Height = 17.000000000000000000 37 | Size.PlatformDefault = False 38 | TabOrder = 2 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_forms_separately/parent_window.py: -------------------------------------------------------------------------------- 1 | import os 2 | from delphifmx import * 3 | 4 | class Parent_Form(Form): 5 | 6 | def __init__(self, owner): 7 | self.my_button = None 8 | self.enter_text_edit = None 9 | self.enter_text_label = None 10 | self.main_heading = None 11 | self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "parent_window.pyfmx")) 12 | 13 | def my_buttonClick(self, Sender): 14 | pass 15 | 16 | def main(): 17 | Application.Initialize() 18 | Application.Title = 'Parent Window' 19 | Application.MainForm = Parent_Form(Application) 20 | Application.MainForm.Show() 21 | Application.Run() 22 | Application.MainForm.Destroy() 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_forms_separately/parent_window.pyfmx: -------------------------------------------------------------------------------- 1 | object Parent_Form: TParent_Form 2 | Left = 0 3 | Top = 0 4 | Caption = 'Parent Window' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object my_button: TButton 12 | Position.X = 241.000000000000000000 13 | Position.Y = 192.000000000000000000 14 | TabOrder = 0 15 | Text = 'Press Me' 16 | OnClick = my_buttonClick 17 | end 18 | object enter_text_edit: TEdit 19 | Touch.InteractiveGestures = [LongTap, DoubleTap] 20 | TabOrder = 1 21 | Position.X = 176.000000000000000000 22 | Position.Y = 144.000000000000000000 23 | Size.Width = 209.000000000000000000 24 | Size.Height = 30.000000000000000000 25 | Size.PlatformDefault = False 26 | end 27 | object enter_text_label: TLabel 28 | Position.X = 176.000000000000000000 29 | Position.Y = 119.000000000000000000 30 | Size.Width = 217.000000000000000000 31 | Size.Height = 17.000000000000000000 32 | Size.PlatformDefault = False 33 | Text = 'Please enter something in the Edit box' 34 | TabOrder = 2 35 | end 36 | object main_heading: TLabel 37 | StyledSettings = [Family, FontColor] 38 | Position.X = 136.000000000000000000 39 | Position.Y = 32.000000000000000000 40 | Size.Width = 281.000000000000000000 41 | Size.Height = 41.000000000000000000 42 | Size.PlatformDefault = False 43 | TextSettings.Font.Size = 30.000000000000000000 44 | TextSettings.Font.StyleExt = {00070000000000000004000000} 45 | Text = 'I'#39'm the MainForm' 46 | TabOrder = 3 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_whole_project/D4P_export_demo.py: -------------------------------------------------------------------------------- 1 | from delphifmx import * 2 | from parent_window import Parent_Form 3 | 4 | def main(): 5 | Application.Initialize() 6 | Application.Title = 'Exporter Demo' 7 | Application.MainForm = Parent_Form(Application) 8 | Application.MainForm.Show() 9 | Application.Run() 10 | Application.MainForm.Destroy() 11 | 12 | if __name__ == '__main__': 13 | main() 14 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_whole_project/child_window.py: -------------------------------------------------------------------------------- 1 | import os 2 | from delphifmx import * 3 | 4 | class Child_Form(Form): 5 | 6 | def __init__(self, owner): 7 | self.child_heading = None 8 | self.result_text_heading = None 9 | self.result_text_label = None 10 | self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "child_window.pyfmx")) -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_whole_project/child_window.pyfmx: -------------------------------------------------------------------------------- 1 | object Child_Form: TChild_Form 2 | Left = 0 3 | Top = 0 4 | Caption = 'Child Window' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object child_heading: TLabel 12 | StyledSettings = [Family, FontColor] 13 | Position.X = 192.000000000000000000 14 | Position.Y = 40.000000000000000000 15 | Size.Width = 161.000000000000000000 16 | Size.Height = 41.000000000000000000 17 | Size.PlatformDefault = False 18 | TextSettings.Font.Size = 20.000000000000000000 19 | TextSettings.Font.StyleExt = {00070000000000000004000000} 20 | Text = 'I'#39'm a child form' 21 | TabOrder = 0 22 | end 23 | object result_text_heading: TLabel 24 | Position.X = 16.000000000000000000 25 | Position.Y = 128.000000000000000000 26 | Size.Width = 201.000000000000000000 27 | Size.Height = 17.000000000000000000 28 | Size.PlatformDefault = False 29 | Text = 'Text you entered in the Mainform is:' 30 | TabOrder = 1 31 | end 32 | object result_text_label: TLabel 33 | Position.X = 225.000000000000000000 34 | Position.Y = 128.000000000000000000 35 | Size.Width = 384.000000000000000000 36 | Size.Height = 17.000000000000000000 37 | Size.PlatformDefault = False 38 | TabOrder = 3 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_whole_project/parent_window.py: -------------------------------------------------------------------------------- 1 | import os 2 | from delphifmx import * 3 | 4 | class Parent_Form(Form): 5 | 6 | def __init__(self, owner): 7 | self.my_button = None 8 | self.enter_text_edit = None 9 | self.enter_text_label = None 10 | self.main_heading = None 11 | self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "parent_window.pyfmx")) 12 | 13 | def my_buttonClick(self, Sender): 14 | pass 15 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/Python_Export/Export_whole_project/parent_window.pyfmx: -------------------------------------------------------------------------------- 1 | object Parent_Form: TParent_Form 2 | Left = 0 3 | Top = 0 4 | Caption = 'Parent Window' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object my_button: TButton 12 | Position.X = 241.000000000000000000 13 | Position.Y = 192.000000000000000000 14 | TabOrder = 0 15 | Text = 'Press Me' 16 | OnClick = my_buttonClick 17 | end 18 | object enter_text_edit: TEdit 19 | Touch.InteractiveGestures = [LongTap, DoubleTap] 20 | TabOrder = 1 21 | Position.X = 176.000000000000000000 22 | Position.Y = 144.000000000000000000 23 | Size.Width = 209.000000000000000000 24 | Size.Height = 22.000000000000000000 25 | Size.PlatformDefault = False 26 | end 27 | object enter_text_label: TLabel 28 | Position.X = 176.000000000000000000 29 | Position.Y = 119.000000000000000000 30 | Size.Width = 217.000000000000000000 31 | Size.Height = 17.000000000000000000 32 | Size.PlatformDefault = False 33 | Text = 'Please enter something in the Edit box' 34 | TabOrder = 2 35 | end 36 | object main_heading: TLabel 37 | StyledSettings = [Family, FontColor] 38 | Position.X = 136.000000000000000000 39 | Position.Y = 32.000000000000000000 40 | Size.Width = 281.000000000000000000 41 | Size.Height = 41.000000000000000000 42 | Size.PlatformDefault = False 43 | TextSettings.Font.Size = 30.000000000000000000 44 | TextSettings.Font.StyleExt = {00070000000000000004000000} 45 | Text = 'I'#39'm the MainForm' 46 | TabOrder = 3 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/child_window.fmx: -------------------------------------------------------------------------------- 1 | object Child_Form: TChild_Form 2 | Left = 0 3 | Top = 0 4 | Caption = 'Child Window' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object child_heading: TLabel 12 | StyledSettings = [Family, FontColor] 13 | Position.X = 192.000000000000000000 14 | Position.Y = 40.000000000000000000 15 | Size.Width = 161.000000000000000000 16 | Size.Height = 41.000000000000000000 17 | Size.PlatformDefault = False 18 | TextSettings.Font.Size = 20.000000000000000000 19 | TextSettings.Font.StyleExt = {00070000000000000004000000} 20 | Text = 'I'#39'm a child form' 21 | TabOrder = 0 22 | end 23 | object result_text_heading: TLabel 24 | Position.X = 16.000000000000000000 25 | Position.Y = 128.000000000000000000 26 | Size.Width = 201.000000000000000000 27 | Size.Height = 17.000000000000000000 28 | Size.PlatformDefault = False 29 | Text = 'Text you entered in the Mainform is:' 30 | TabOrder = 1 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/child_window.pas: -------------------------------------------------------------------------------- 1 | unit child_window; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, 8 | FMX.Controls.Presentation, FMX.StdCtrls; 9 | 10 | type 11 | TChild_Form = class(TForm) 12 | child_heading: TLabel; 13 | result_text_heading: TLabel; 14 | private 15 | { Private declarations } 16 | public 17 | { Public declarations } 18 | end; 19 | 20 | var 21 | Child_Form: TChild_Form; 22 | 23 | implementation 24 | 25 | {$R *.fmx} 26 | 27 | end. 28 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/parent_window.fmx: -------------------------------------------------------------------------------- 1 | object Parent_Form: TParent_Form 2 | Left = 0 3 | Top = 0 4 | Caption = 'Parent Window' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object my_button: TButton 12 | Position.X = 241.000000000000000000 13 | Position.Y = 192.000000000000000000 14 | TabOrder = 0 15 | Text = 'Press Me' 16 | OnClick = my_buttonClick 17 | end 18 | object enter_text_edit: TEdit 19 | Touch.InteractiveGestures = [LongTap, DoubleTap] 20 | TabOrder = 1 21 | Position.X = 176.000000000000000000 22 | Position.Y = 144.000000000000000000 23 | Size.Width = 209.000000000000000000 24 | Size.Height = 22.000000000000000000 25 | Size.PlatformDefault = False 26 | end 27 | object enter_text_label: TLabel 28 | Position.X = 176.000000000000000000 29 | Position.Y = 119.000000000000000000 30 | Size.Width = 217.000000000000000000 31 | Size.Height = 17.000000000000000000 32 | Size.PlatformDefault = False 33 | Text = 'Please enter something in the Edit box' 34 | TabOrder = 2 35 | end 36 | object main_heading: TLabel 37 | StyledSettings = [Family, FontColor] 38 | Position.X = 136.000000000000000000 39 | Position.Y = 32.000000000000000000 40 | Size.Width = 281.000000000000000000 41 | Size.Height = 41.000000000000000000 42 | Size.PlatformDefault = False 43 | TextSettings.Font.Size = 30.000000000000000000 44 | TextSettings.Font.StyleExt = {00070000000000000004000000} 45 | Text = 'I'#39'm the MainForm' 46 | TabOrder = 3 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /Samples/Simple_Demo/parent_window.pas: -------------------------------------------------------------------------------- 1 | unit parent_window; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, 8 | FMX.Edit, FMX.Controls.Presentation; 9 | 10 | type 11 | TParent_Form = class(TForm) 12 | my_button: TButton; 13 | enter_text_edit: TEdit; 14 | enter_text_label: TLabel; 15 | main_heading: TLabel; 16 | procedure my_buttonClick(Sender: TObject); 17 | private 18 | { Private declarations } 19 | public 20 | { Public declarations } 21 | end; 22 | 23 | var 24 | Parent_Form: TParent_Form; 25 | 26 | implementation 27 | 28 | {$R *.fmx} 29 | 30 | procedure TParent_Form.my_buttonClick(Sender: TObject); 31 | begin 32 | // 33 | end; 34 | 35 | end. 36 | -------------------------------------------------------------------------------- /Samples/TipCalculator/AndroidManifest.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | <%uses-permission%> 10 | 11 | 12 | <%queries-child-elements%> 13 | 14 | 25 | <%provider%> 26 | <%application-meta-data%> 27 | <%uses-libraries%> 28 | <%services%> 29 | 31 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | <%activity%> 46 | <%receivers%> 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Samples/TipCalculator/Python_Export/Modified_TipMain/TipCalculator.py: -------------------------------------------------------------------------------- 1 | from delphifmx import * 2 | from TipMain import Main_Window 3 | 4 | def main(): 5 | Application.Initialize() 6 | Application.Title = 'Tip Calculator' 7 | Application.MainForm = Main_Window(Application) 8 | Application.MainForm.Show() 9 | Application.Run() 10 | Application.MainForm.Destroy() 11 | 12 | if __name__ == '__main__': 13 | main() 14 | -------------------------------------------------------------------------------- /Samples/TipCalculator/Python_Export/Modified_TipMain/TipMain.py: -------------------------------------------------------------------------------- 1 | import os 2 | from delphifmx import * 3 | 4 | class Main_Window(Form): 5 | 6 | def __init__(self, owner): 7 | self.styleRuby = None 8 | self.styleLight = None 9 | self.ListBox1 = None 10 | self.ListBoxItem1 = None 11 | self.editTotal = None 12 | self.Label6 = None 13 | self.ListBoxItem2 = None 14 | self.Label7 = None 15 | self.editTip = None 16 | self.ListBoxItem3 = None 17 | self.trackTip = None 18 | self.ListBoxItem4 = None 19 | self.editPeople = None 20 | self.Label3 = None 21 | self.ListBoxItem5 = None 22 | self.trackPeople = None 23 | self.ListBoxItem6 = None 24 | self.Layout2 = None 25 | self.ListBoxItem7 = None 26 | self.per_person_share = None 27 | self.Label1 = None 28 | self.ListBoxItem8 = None 29 | self.bill_plus_tip = None 30 | self.Label5 = None 31 | self.ListBoxItem9 = None 32 | self.gold_style_btn = None 33 | self.ruby_style_btn = None 34 | self.light_style_btn = None 35 | self.default_style = None 36 | self.styleGold = None 37 | self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "TipMain.pyfmx")) 38 | self.editTotal.OnChange = self.editTotalChange 39 | self.editTotal.Value = 100 40 | self.editTip.Value = 20 41 | self.editPeople.Value = 4 42 | 43 | def calc_bill_plus_tip(self): 44 | total = self.editTotal.Value 45 | tip_percent = self.editTip.Value 46 | 47 | if total != 0: 48 | self.bill_plus_tip.Text = str(round(total + (tip_percent*total)/100, 2)) 49 | print(round(total + (tip_percent/total)*100, 2)) 50 | else: 51 | self.bill_plus_tip.Text = str(0) 52 | 53 | def calc_per_person_share(self): 54 | persons = self.editPeople.Value 55 | 56 | self.per_person_share.Text = str(round(float(self.bill_plus_tip.Text) / persons, 2)) 57 | 58 | def editTotalChange(self, Sender): 59 | self.calc_bill_plus_tip() 60 | self.calc_per_person_share() 61 | 62 | def editTipChange(self, Sender): 63 | self.trackTip.Value = self.editTip.Value 64 | self.calc_bill_plus_tip() 65 | self.calc_per_person_share() 66 | 67 | def trackTipChange(self, Sender): 68 | self.editTip.Value = self.trackTip.Value 69 | self.calc_bill_plus_tip() 70 | self.calc_per_person_share() 71 | 72 | def editPeopleChange(self, Sender): 73 | self.trackPeople.Value = self.editPeople.Value 74 | self.calc_bill_plus_tip() 75 | self.calc_per_person_share() 76 | 77 | def trackPeopleChange(self, Sender): 78 | self.editPeople.Value = self.trackPeople.Value 79 | self.calc_bill_plus_tip() 80 | self.calc_per_person_share() 81 | 82 | def gold_style_btnClick(self, Sender): 83 | self.styleBook = self.styleGold 84 | 85 | def ruby_style_btnClick(self, Sender): 86 | self.styleBook = self.styleRuby 87 | 88 | def light_style_btnClick(self, Sender): 89 | self.styleBook = self.styleLight 90 | 91 | def default_styleClick(self, Sender): 92 | self.styleBook = None -------------------------------------------------------------------------------- /Samples/TipCalculator/Python_Export/TipCalculator.py: -------------------------------------------------------------------------------- 1 | from delphifmx import * 2 | from TipMain import Main_Window 3 | 4 | def main(): 5 | Application.Initialize() 6 | Application.Title = 'Tip Calculator' 7 | Application.MainForm = Main_Window(Application) 8 | Application.MainForm.Show() 9 | Application.Run() 10 | Application.MainForm.Destroy() 11 | 12 | if __name__ == '__main__': 13 | main() 14 | -------------------------------------------------------------------------------- /Samples/TipCalculator/Python_Export/TipMain.py: -------------------------------------------------------------------------------- 1 | import os 2 | from delphifmx import * 3 | 4 | class Main_Window(Form): 5 | 6 | def __init__(self, owner): 7 | self.styleRuby = None 8 | self.styleLight = None 9 | self.ListBox1 = None 10 | self.ListBoxItem1 = None 11 | self.editTotal = None 12 | self.Label6 = None 13 | self.ListBoxItem2 = None 14 | self.Label7 = None 15 | self.editTip = None 16 | self.ListBoxItem3 = None 17 | self.trackTip = None 18 | self.ListBoxItem4 = None 19 | self.editPeople = None 20 | self.Label3 = None 21 | self.ListBoxItem5 = None 22 | self.trackPeople = None 23 | self.ListBoxItem6 = None 24 | self.Layout2 = None 25 | self.ListBoxItem7 = None 26 | self.per_person_share = None 27 | self.Label1 = None 28 | self.ListBoxItem8 = None 29 | self.bill_plus_tip = None 30 | self.Label5 = None 31 | self.ListBoxItem9 = None 32 | self.gold_style_btn = None 33 | self.ruby_style_btn = None 34 | self.light_style_btn = None 35 | self.default_style = None 36 | self.styleGold = None 37 | self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "TipMain.pyfmx")) 38 | 39 | def editTipChange(self, Sender): 40 | pass 41 | 42 | def trackTipChange(self, Sender): 43 | pass 44 | 45 | def editPeopleChange(self, Sender): 46 | pass 47 | 48 | def trackPeopleChange(self, Sender): 49 | pass 50 | 51 | def gold_style_btnClick(self, Sender): 52 | pass 53 | 54 | def ruby_style_btnClick(self, Sender): 55 | pass 56 | 57 | def light_style_btnClick(self, Sender): 58 | pass 59 | 60 | def default_styleClick(self, Sender): 61 | pass -------------------------------------------------------------------------------- /Samples/TipCalculator/TipCalculator.deployproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 12 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | TipCalculator\library\lib\armeabi-v7a\ 16 | libTipCalculator.so 17 | AndroidLibnativeArmeabiv7aFile 18 | 1 19 | 20 | 21 | True 22 | 23 | 24 | TipCalculator\res\drawable-mdpi\ 25 | ic_notification.png 26 | Android_NotificationIcon24 27 | 1 28 | 29 | 30 | True 31 | 32 | 33 | TipCalculator\res\drawable-ldpi\ 34 | ic_launcher.png 35 | Android_LauncherIcon36 36 | 1 37 | 38 | 39 | True 40 | 41 | 42 | TipCalculator\res\drawable-hdpi\ 43 | ic_launcher.png 44 | Android_LauncherIcon72 45 | 1 46 | 47 | 48 | True 49 | 50 | 51 | TipCalculator\res\drawable-xlarge\ 52 | splash_image.png 53 | Android_SplashImage960 54 | 1 55 | 56 | 57 | True 58 | 59 | 60 | TipCalculator\ 61 | AndroidManifest.xml 62 | ProjectAndroidManifest 63 | 1 64 | 65 | 66 | True 67 | 68 | 69 | TipCalculator\res\drawable-mdpi\ 70 | ic_launcher.png 71 | Android_LauncherIcon48 72 | 1 73 | 74 | 75 | True 76 | 77 | 78 | TipCalculator\library\lib\arm64-v8a\ 79 | libTipCalculator.so 80 | ProjectOutput 81 | 1 82 | 83 | 84 | True 85 | True 86 | 87 | 88 | TipCalculator\res\drawable-xxhdpi\ 89 | ic_launcher.png 90 | Android_LauncherIcon144 91 | 1 92 | 93 | 94 | True 95 | 96 | 97 | TipCalculator\res\drawable-xxxhdpi\ 98 | ic_launcher.png 99 | Android_LauncherIcon192 100 | 1 101 | 102 | 103 | True 104 | 105 | 106 | TipCalculator\res\values\ 107 | styles.xml 108 | AndroidSplashStyles 109 | 1 110 | 111 | 112 | True 113 | 114 | 115 | TipCalculator\res\drawable-xhdpi\ 116 | ic_notification.png 117 | Android_NotificationIcon48 118 | 1 119 | 120 | 121 | True 122 | 123 | 124 | TipCalculator\res\drawable-small\ 125 | splash_image.png 126 | Android_SplashImage426 127 | 1 128 | 129 | 130 | True 131 | 132 | 133 | TipCalculator\res\drawable-large\ 134 | splash_image.png 135 | Android_SplashImage640 136 | 1 137 | 138 | 139 | True 140 | 141 | 142 | TipCalculator\library\lib\armeabi\ 143 | libTipCalculator.so 144 | AndroidLibnativeArmeabiFile 145 | 1 146 | 147 | 148 | True 149 | 150 | 151 | TipCalculator\classes\ 152 | TipCalculator.classes 153 | AndroidClasses 154 | 64 155 | 156 | 157 | True 158 | 159 | 160 | TipCalculator\res\values\ 161 | strings.xml 162 | Android_Strings 163 | 1 164 | 165 | 166 | True 167 | 168 | 169 | TipCalculator\res\values-v21\ 170 | styles.xml 171 | AndroidSplashStylesV21 172 | 1 173 | 174 | 175 | True 176 | 177 | 178 | TipCalculator\res\values\ 179 | colors.xml 180 | Android_Colors 181 | 1 182 | 183 | 184 | True 185 | 186 | 187 | TipCalculator\res\drawable\ 188 | splash_image_def.xml 189 | AndroidSplashImageDef 190 | 1 191 | 192 | 193 | True 194 | 195 | 196 | TipCalculator\res\drawable-hdpi\ 197 | ic_notification.png 198 | Android_NotificationIcon36 199 | 1 200 | 201 | 202 | True 203 | 204 | 205 | TipCalculator\res\drawable-xxhdpi\ 206 | ic_notification.png 207 | Android_NotificationIcon72 208 | 1 209 | 210 | 211 | True 212 | 213 | 214 | TipCalculator\res\drawable-xxxhdpi\ 215 | ic_notification.png 216 | Android_NotificationIcon96 217 | 1 218 | 219 | 220 | True 221 | 222 | 223 | TipCalculator\library\lib\mips\ 224 | libTipCalculator.so 225 | AndroidLibnativeMipsFile 226 | 1 227 | 228 | 229 | True 230 | 231 | 232 | TipCalculator\res\drawable-xhdpi\ 233 | ic_launcher.png 234 | Android_LauncherIcon96 235 | 1 236 | 237 | 238 | True 239 | 240 | 241 | TipCalculator\res\drawable-normal\ 242 | splash_image.png 243 | Android_SplashImage470 244 | 1 245 | 246 | 247 | True 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /Samples/TipCalculator/TipCalculator.dpr: -------------------------------------------------------------------------------- 1 | program TipCalculator; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | TipMain in 'TipMain.pas' {Main_Window}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TMain_Window, Main_Window); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Samples/TipCalculator/TipCalculator.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/Samples/TipCalculator/TipCalculator.res -------------------------------------------------------------------------------- /Samples/TipCalculator/TipMain.pas: -------------------------------------------------------------------------------- 1 | unit TipMain; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit, 8 | FMX.EditBox, FMX.SpinBox, FMX.Controls.Presentation, FMX.StdCtrls, 9 | Data.Bind.EngExt, Fmx.Bind.DBEngExt, System.Rtti, 10 | System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.Components, 11 | FMX.Objects, FMX.ListBox, FMX.Layouts; 12 | 13 | type 14 | TMain_Window = class(TForm) 15 | styleGold: TStyleBook; 16 | styleRuby: TStyleBook; 17 | styleLight: TStyleBook; 18 | ListBox1: TListBox; 19 | ListBoxItem1: TListBoxItem; 20 | editTotal: TSpinBox; 21 | ListBoxItem2: TListBoxItem; 22 | ListBoxItem3: TListBoxItem; 23 | ListBoxItem4: TListBoxItem; 24 | ListBoxItem5: TListBoxItem; 25 | Label7: TLabel; 26 | Label6: TLabel; 27 | editTip: TSpinBox; 28 | trackTip: TTrackBar; 29 | ListBoxItem6: TListBoxItem; 30 | ListBoxItem7: TListBoxItem; 31 | trackPeople: TTrackBar; 32 | editPeople: TSpinBox; 33 | Label3: TLabel; 34 | Layout2: TLayout; 35 | ListBoxItem8: TListBoxItem; 36 | bill_plus_tip: TEdit; 37 | per_person_share: TEdit; 38 | Label1: TLabel; 39 | Label5: TLabel; 40 | ListBoxItem9: TListBoxItem; 41 | gold_style_btn: TButton; 42 | ruby_style_btn: TButton; 43 | light_style_btn: TButton; 44 | default_style: TButton; 45 | procedure gold_style_btnClick(Sender: TObject); 46 | procedure ruby_style_btnClick(Sender: TObject); 47 | procedure light_style_btnClick(Sender: TObject); 48 | procedure default_styleClick(Sender: TObject); 49 | procedure editTipChange(Sender: TObject); 50 | procedure trackTipChange(Sender: TObject); 51 | procedure editPeopleChange(Sender: TObject); 52 | procedure trackPeopleChange(Sender: TObject); 53 | procedure btnUpClick(Sender: TObject); 54 | procedure btnDownClick(Sender: TObject); 55 | private 56 | { Private declarations } 57 | public 58 | { Public declarations } 59 | end; 60 | 61 | var 62 | Main_Window: TMain_Window; 63 | 64 | implementation 65 | 66 | {$R *.fmx} 67 | 68 | procedure TMain_Window.gold_style_btnClick(Sender: TObject); 69 | begin 70 | StyleBook := styleGold; 71 | end; 72 | 73 | procedure TMain_Window.ruby_style_btnClick(Sender: TObject); 74 | begin 75 | StyleBook := styleRuby; 76 | end; 77 | 78 | procedure TMain_Window.light_style_btnClick(Sender: TObject); 79 | begin 80 | StyleBook := styleLight; 81 | end; 82 | 83 | procedure TMain_Window.btnDownClick(Sender: TObject); 84 | begin 85 | // 86 | end; 87 | 88 | procedure TMain_Window.btnUpClick(Sender: TObject); 89 | begin 90 | // 91 | end; 92 | 93 | procedure TMain_Window.default_styleClick(Sender: TObject); 94 | begin 95 | StyleBook := nil; 96 | end; 97 | 98 | procedure TMain_Window.editPeopleChange(Sender: TObject); 99 | begin 100 | // 101 | end; 102 | 103 | procedure TMain_Window.editTipChange(Sender: TObject); 104 | begin 105 | // 106 | end; 107 | 108 | procedure TMain_Window.trackPeopleChange(Sender: TObject); 109 | begin 110 | // 111 | end; 112 | 113 | procedure TMain_Window.trackTipChange(Sender: TObject); 114 | begin 115 | // 116 | end; 117 | 118 | end. 119 | -------------------------------------------------------------------------------- /Source/Design/PythonTools.Design.Forms.pas: -------------------------------------------------------------------------------- 1 | {$I PythonTools.inc} 2 | unit PythonTools.Design.Forms; 3 | 4 | interface 5 | 6 | uses 7 | System.SysUtils, System.Variants, System.Classes, 8 | Data.DB, Datasnap.DBClient, Vcl.Dialogs, 9 | Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids, Vcl.Buttons, Vcl.Imaging.pngimage, 10 | Vcl.ExtCtrls, Vcl.Controls, Vcl.Forms, System.Types, 11 | PythonTools.Design, PythonTools.Model.Design.Forms; 12 | 13 | {$WARN SYMBOL_PLATFORM OFF} 14 | 15 | type 16 | TDBGrid = class(Vcl.DBGrids.TDBGrid) 17 | protected 18 | procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override; 19 | public 20 | function ScaleValue(const Value: Integer): Integer; overload; 21 | function ScaleValue(const Value: TSize): TSize; overload; 22 | end; 23 | 24 | TFormsExportDialog = class(TDesignForm) 25 | FileOpenDialog1: TFileOpenDialog; 26 | pnlHeader: TPanel; 27 | imgExport: TImage; 28 | lblDescription: TLabel; 29 | lblExport: TLabel; 30 | spHeader: TShape; 31 | pnlContents: TPanel; 32 | pnlAppDir: TPanel; 33 | lblApplicationDirectory: TLabel; 34 | edtDirectory: TEdit; 35 | plnFooter: TPanel; 36 | btnCancel: TButton; 37 | btnExport: TButton; 38 | pnlGrid: TPanel; 39 | grForms: TDBGrid; 40 | cdsForms: TClientDataSet; 41 | dsForms: TDataSource; 42 | cdsFormsFL_EXPORT: TBooleanField; 43 | cdsFormsDESC_FORM: TStringField; 44 | cdsFormsTITLE: TStringField; 45 | cdsFormsFL_INITIALIZE: TBooleanField; 46 | cdsFormsFL_FORM_FILE_KIND: TStringField; 47 | btnSelectDir: TButton; 48 | llblNotification: TLinkLabel; 49 | cbShowExportedFiles: TCheckBox; 50 | pnlFormFileOptions: TPanel; 51 | cbFormFileCompatibleMode: TCheckBox; 52 | procedure btnExportClick(Sender: TObject); 53 | procedure btnSelectDirClick(Sender: TObject); 54 | procedure FormCreate(Sender: TObject); 55 | procedure grFormsKeyPress(Sender: TObject; var Key: Char); 56 | procedure grFormsCellClick(Column: TColumn); 57 | procedure cdsFormsFL_EXPORTGetText(Sender: TField; var Text: string; 58 | DisplayText: Boolean); 59 | procedure grFormsColEnter(Sender: TObject); 60 | procedure cdsFormsFL_INITIALIZEGetText(Sender: TField; var Text: string; 61 | DisplayText: Boolean); 62 | procedure grFormsTitleClick(Column: TColumn); 63 | procedure grFormsDrawColumnCell(Sender: TObject; const Rect: TRect; 64 | DataCol: Integer; Column: TColumn; State: TGridDrawState); 65 | procedure llblNotificationLinkClick(Sender: TObject; const Link: string; 66 | LinkType: TSysLinkType); 67 | public 68 | function Execute(const AModel: TExportFormsDesignModel): boolean; 69 | end; 70 | 71 | var 72 | FormsExportDialog: TFormsExportDialog; 73 | 74 | implementation 75 | 76 | uses 77 | System.Generics.Collections, System.Math, 78 | CommCtrl, Vcl.Themes, 79 | ShellApi, 80 | Winapi.Windows, 81 | Vcl.Graphics, 82 | PythonTools.Common; 83 | 84 | var 85 | gCheckBoxElement: TCheckBox; 86 | 87 | {$R *.dfm} 88 | 89 | function RectVCenter(var R: TRect; Bounds: TRect): TRect; 90 | begin 91 | OffsetRect(R, -R.Left, -R.Top); 92 | OffsetRect(R, Bounds.Right - (R.Width div 2), (Bounds.Height - R.Height) div 2); 93 | OffsetRect(R, Bounds.Left, Bounds.Top); 94 | 95 | Result := R; 96 | end; 97 | 98 | procedure DrawCheckBox(const ADBGrid: TDBGrid; const AColumn: TColumn; 99 | ARect: TRect; const AChecked: boolean; AState: TGridDrawState); 100 | const 101 | IS_CHECKED: array[boolean] of integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED); 102 | var 103 | LStyle: TCustomStyleServices; 104 | LBoxSize: TSize; 105 | LDetail: TThemedButton; 106 | LDetails: TThemedElementDetails; 107 | LRect: TRect; 108 | begin 109 | ADBGrid.Canvas.FillRect(ARect); 110 | 111 | LStyle := StyleServices; 112 | if LStyle.Available then begin 113 | LDetail := tbCheckBoxUncheckedNormal; 114 | 115 | if (gdPressed in AState) then 116 | LDetail := tbCheckBoxUncheckedPressed 117 | else if (gdFocused in AState) then 118 | LDetail := tbCheckBoxUncheckedHot; 119 | 120 | if AChecked then 121 | LDetail := TThemedButton(Integer(LDetail) + 4); 122 | 123 | LDetails := LStyle.GetElementDetails(tbCheckBoxUncheckedNormal); 124 | if not LStyle.GetElementSize(gCheckBoxElement.Handle, LDetails, esActual, LBoxSize {$IFDEF DELPHI10_3_UP}, ADBGrid.CurrentPPI {$ENDIF}) then 125 | begin 126 | LBoxSize.cx := GetSystemMetrics(SM_CXMENUCHECK); 127 | LBoxSize.cy := GetSystemMetrics(SM_CYMENUCHECK); 128 | end; 129 | 130 | if LStyle.IsSystemStyle then 131 | LBoxSize := ADBGrid.ScaleValue(LBoxSize); 132 | 133 | LRect := Rect(0, 0, LBoxSize.cx, LBoxSize.cy); 134 | RectVCenter(LRect, Rect(0, ARect.Top, ARect.Right, ARect.Bottom)); 135 | 136 | LDetails := LStyle.GetElementDetails(LDetail); 137 | LStyle.DrawElement(ADBGrid.Canvas.Handle, LDetails, LRect, nil {$IFDEF DELPHI10_3_UP}, ADBGrid.CurrentPPI {$ENDIF}); 138 | 139 | if not (gdFocused in AState) then 140 | ADBGrid.Canvas.Brush.Color := LStyle.GetSystemColor(clHighlight); 141 | end else 142 | DrawFrameControl(ADBGrid.Canvas.Handle, ARect, DFC_BUTTON, IS_CHECKED[AChecked]); 143 | end; 144 | 145 | procedure TFormsExportDialog.btnExportClick(Sender: TObject); 146 | var 147 | LMark: TArray; 148 | LHasSelection: boolean; 149 | begin 150 | //Make some validations 151 | if Trim(edtDirectory.Text) = String.Empty then 152 | raise Exception.Create('Select the Directory.'); 153 | 154 | cdsForms.DisableControls(); 155 | try 156 | LMark := cdsForms.Bookmark; 157 | try 158 | cdsForms.Filter := 'FL_EXPORT = True'; 159 | cdsForms.Filtered := true; 160 | LHasSelection := not cdsForms.IsEmpty(); 161 | cdsForms.Filtered := false; 162 | finally 163 | if cdsForms.BookmarkValid(LMark) then 164 | cdsForms.Bookmark := LMark; 165 | end; 166 | finally 167 | cdsForms.EnableControls(); 168 | end; 169 | 170 | if not LHasSelection then 171 | raise Exception.Create('Select one form at least.'); 172 | 173 | ModalResult := mrOk; 174 | end; 175 | 176 | procedure TFormsExportDialog.btnSelectDirClick(Sender: TObject); 177 | begin 178 | with FileOpenDialog1 do begin 179 | DefaultFolder := edtDirectory.Text; 180 | FileName := edtDirectory.Text; 181 | if Execute then 182 | edtDirectory.Text := FileName 183 | else 184 | edtDirectory.Text := String.Empty; 185 | end; 186 | end; 187 | 188 | procedure TFormsExportDialog.cdsFormsFL_EXPORTGetText(Sender: TField; 189 | var Text: string; DisplayText: Boolean); 190 | begin 191 | Text := ' '; 192 | end; 193 | 194 | procedure TFormsExportDialog.cdsFormsFL_INITIALIZEGetText(Sender: TField; 195 | var Text: string; DisplayText: Boolean); 196 | begin 197 | Text := ' '; 198 | end; 199 | 200 | procedure TFormsExportDialog.grFormsCellClick(Column: TColumn); 201 | begin 202 | if Column.Field.DataType = ftBoolean then begin 203 | cdsForms.Edit(); 204 | Column.Field.AsBoolean := not Column.Field.AsBoolean; 205 | cdsForms.Post(); 206 | end; 207 | end; 208 | 209 | procedure TFormsExportDialog.grFormsColEnter(Sender: TObject); 210 | begin 211 | with Sender as TDBGrid do 212 | if (SelectedField.DataType = ftBoolean) then 213 | Options := Options - [dgEditing] 214 | else 215 | Options := Options + [dgEditing]; 216 | end; 217 | 218 | procedure TFormsExportDialog.grFormsDrawColumnCell(Sender: TObject; 219 | const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); 220 | var 221 | LRect: TRect; 222 | begin 223 | inherited; 224 | if Column.Field.DataType = ftBoolean then begin 225 | LRect := System.Classes.Rect( 226 | Rect.Left, 227 | Rect.Top, 228 | Rect.Right - (Column.Width div 2), 229 | Rect.Bottom 230 | ); 231 | DrawCheckBox(TDBGrid(Sender), Column, LRect, Column.Field.AsBoolean, State); 232 | end; 233 | end; 234 | 235 | procedure TFormsExportDialog.grFormsKeyPress(Sender: TObject; var Key: Char); 236 | begin 237 | if (key = Chr(9)) then 238 | Exit; 239 | 240 | with Sender as TDBGrid do 241 | if Assigned(SelectedField) and (Ord(Key) in [VK_RETURN, VK_SPACE]) then begin 242 | cdsForms.Edit(); 243 | SelectedField.AsBoolean := not SelectedField.AsBoolean; 244 | cdsForms.Post(); 245 | end; 246 | end; 247 | 248 | procedure TFormsExportDialog.grFormsTitleClick(Column: TColumn); 249 | var 250 | LMark: TArray; 251 | begin 252 | if Column.Field.DataType = ftBoolean then begin 253 | Column.Field.Tag := Integer(not Boolean(Column.Field.Tag)); 254 | 255 | cdsForms.DisableControls(); 256 | try 257 | LMark := cdsForms.Bookmark; 258 | try 259 | cdsForms.First(); 260 | while not cdsForms.Eof do begin 261 | cdsForms.Edit(); 262 | Column.Field.AsBoolean := Boolean(Column.Field.Tag); 263 | cdsForms.Post(); 264 | cdsForms.Next(); 265 | end; 266 | finally 267 | if cdsForms.BookmarkValid(LMark) then 268 | cdsForms.Bookmark := LMark; 269 | end; 270 | finally 271 | cdsForms.EnableControls(); 272 | end; 273 | end; 274 | end; 275 | 276 | procedure TFormsExportDialog.llblNotificationLinkClick(Sender: TObject; 277 | const Link: string; LinkType: TSysLinkType); 278 | begin 279 | ShellExecute(0, 'open', pchar(Link), nil, nil, SW_NORMAL); 280 | end; 281 | 282 | function TFormsExportDialog.Execute(const AModel: TExportFormsDesignModel): boolean; 283 | var 284 | LInput: TInputForm; 285 | LOutput: TList; 286 | LFormFileMode: TFormFileMode; 287 | begin 288 | edtDirectory.Text := AModel.Directory; 289 | cbShowExportedFiles.Checked := AModel.ShowInExplorer; 290 | 291 | cdsForms.EmptyDataSet(); 292 | for LInput in AModel.InputForms do begin 293 | cdsForms.AppendRecord([ 294 | true, 295 | LInput.Form.CombineFileAndFormName(), 296 | LInput.Title, 297 | True, 298 | TFormFileKind.ffkText.ToString() 299 | ]); 300 | end; 301 | cdsForms.First(); 302 | 303 | with grForms do 304 | if SelectedField.DataType = ftBoolean then 305 | Options := Options - [dgEditing]; 306 | 307 | Result := ShowModal() = mrOk; 308 | 309 | if not Result then 310 | Exit(); 311 | 312 | AModel.Directory := edtDirectory.Text; 313 | AModel.ShowInExplorer := cbShowExportedFiles.Checked; 314 | 315 | LFormFileMode := TFormFileMode.ffmPython; 316 | if cbFormFileCompatibleMode.Checked then 317 | LFormFileMode := TFormFileMode.ffmCompatible; 318 | 319 | LOutput := TList.Create(); 320 | try 321 | cdsForms.DisableControls(); 322 | try 323 | cdsForms.First(); 324 | for LInput in AModel.InputForms do begin 325 | if cdsForms.Locate('DESC_FORM', LInput.Form.CombineFileAndFormName(), []) then begin 326 | if not cdsFormsFL_EXPORT.AsBoolean then 327 | Continue; 328 | LOutput.Add(TOutputForm.Create( 329 | LInput.Form, 330 | cdsFormsFL_INITIALIZE.AsBoolean, 331 | cdsFormsTITLE.AsString, 332 | TFormFileKind.FromString(cdsFormsFL_FORM_FILE_KIND.AsString), 333 | LFormFileMode 334 | )); 335 | end; 336 | end; 337 | finally 338 | cdsForms.EnableControls(); 339 | end; 340 | AModel.OutputForms := LOutput.ToArray(); 341 | finally 342 | LOutput.Free(); 343 | end; 344 | end; 345 | 346 | procedure TFormsExportDialog.FormCreate(Sender: TObject); 347 | begin 348 | inherited; 349 | gCheckBoxElement := cbShowExportedFiles; 350 | cdsForms.CreateDataSet(); 351 | end; 352 | 353 | { TDBGrid } 354 | 355 | procedure TDBGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; 356 | AState: TGridDrawState); 357 | const 358 | TEXT_LEFT_OFFSET = 15; 359 | var 360 | LRect: TRect; 361 | LChecked: Boolean; 362 | begin 363 | inherited; 364 | Dec(ARow); 365 | if ARow < 0 then 366 | if Columns[ACol].Field.DataType = ftBoolean then begin 367 | LRect := ARect; 368 | LRect.Right := LRect.Right - ( 369 | (ColWidths[ACol] div 2) 370 | + (Canvas.TextWidth(Columns[ACol].Title.Caption) div 2) 371 | + ScaleValue(TEXT_LEFT_OFFSET) 372 | ); 373 | LChecked := Boolean(Columns[ACol].Field.Tag); 374 | DrawCheckBox(Self, Columns[ACol], LRect, LChecked, AState); 375 | end; 376 | end; 377 | 378 | function TDBGrid.ScaleValue(const Value: TSize): TSize; 379 | begin 380 | {$IFDEF DELPHI10_4_UP} 381 | Result := inherited; 382 | {$ELSE} 383 | Result := Value; 384 | {$ENDIF} 385 | end; 386 | 387 | function TDBGrid.ScaleValue(const Value: Integer): Integer; 388 | begin 389 | {$IFDEF DELPHI10_4_UP} 390 | Result := inherited; 391 | {$ELSE} 392 | Result := Value; 393 | {$ENDIF} 394 | end; 395 | 396 | end. 397 | -------------------------------------------------------------------------------- /Source/Design/PythonTools.Design.Project.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Design.Project; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.Imaging.pngimage, 8 | Vcl.StdCtrls, Vcl.Buttons, 9 | PythonTools.Design, 10 | PythonTools.Common, 11 | PythonTools.Model.Design.Project, Vcl.WinXCtrls; 12 | 13 | {$WARN SYMBOL_PLATFORM OFF} 14 | 15 | type 16 | TProjectExportDialog = class(TDesignForm) 17 | pnlHeader: TPanel; 18 | plnFooter: TPanel; 19 | pnlAppDir: TPanel; 20 | pnlAppSettings: TPanel; 21 | imgExport: TImage; 22 | lblExport: TLabel; 23 | lblProjectName: TLabel; 24 | spHeader: TShape; 25 | lblAppTitle: TLabel; 26 | edtApplicationTitle: TEdit; 27 | lblAppMainForm: TLabel; 28 | cbApplicationMainForm: TComboBox; 29 | FileOpenDialog1: TFileOpenDialog; 30 | lblApplicationDirectory: TLabel; 31 | edtApplicationDirectory: TEdit; 32 | btnCancel: TButton; 33 | btnExport: TButton; 34 | pnlFormFileOptions: TPanel; 35 | lblFormFileKind: TLabel; 36 | swFormFileKind: TToggleSwitch; 37 | Label1: TLabel; 38 | Label2: TLabel; 39 | llblNotification: TLinkLabel; 40 | pnlContents: TPanel; 41 | lbForms: TListBox; 42 | pnlClient: TPanel; 43 | cbShowExportedFiles: TCheckBox; 44 | btnSelectDir: TButton; 45 | cbFormFileCompatibleMode: TCheckBox; 46 | procedure btnExportClick(Sender: TObject); 47 | procedure btnSelectDirClick(Sender: TObject); 48 | procedure Label1Click(Sender: TObject); 49 | procedure Label2Click(Sender: TObject); 50 | procedure llblNotificationLinkClick(Sender: TObject; const Link: string; 51 | LinkType: TSysLinkType); 52 | procedure FormShow(Sender: TObject); 53 | private 54 | procedure EnableHorizontalScrollBar(const AListBox: TListBox); 55 | public 56 | function Execute(const AModel: TExportProjectDesignModel): boolean; 57 | end; 58 | 59 | var 60 | ProjectExportDialog: TProjectExportDialog; 61 | 62 | implementation 63 | 64 | {$R *.dfm} 65 | 66 | uses ShellApi; 67 | 68 | procedure TProjectExportDialog.btnExportClick(Sender: TObject); 69 | begin 70 | //Make some validations 71 | if Trim(edtApplicationTitle.Text) = String.Empty then 72 | raise Exception.Create('Type the Application Title.'); 73 | 74 | if cbApplicationMainForm.ItemIndex = -1 then 75 | raise Exception.Create('Select the Application Main Form'); 76 | 77 | if Trim(edtApplicationDirectory.Text) = String.Empty then 78 | raise Exception.Create('Select the Application Directory.'); 79 | 80 | ModalResult := mrOk; 81 | end; 82 | 83 | procedure TProjectExportDialog.EnableHorizontalScrollBar( 84 | const AListBox: TListBox); 85 | var 86 | I: integer; 87 | LMaxWidth: integer; 88 | LWidth: integer; 89 | begin 90 | inherited; 91 | LMaxWidth := AListBox.Width; 92 | for I := 0 to Pred(AListBox.Items.Count) do begin 93 | LWidth := Canvas.TextWidth(AListBox.Items[I]); 94 | if LWidth > LMaxWidth then 95 | LMaxWidth := LWidth; 96 | end; 97 | 98 | if (LMaxWidth > AListBox.Width) then 99 | SendMessage(AListBox.Handle, LB_SETHORIZONTALEXTENT, 100 | LMaxWidth + GetSystemMetrics(SM_CXFRAME), 0); 101 | end; 102 | 103 | function TProjectExportDialog.Execute(const AModel: TExportProjectDesignModel): boolean; 104 | var 105 | LFormNameAndFile: TFormNameAndFile; 106 | begin 107 | lblProjectName.Caption := AModel.ApplicationName; 108 | edtApplicationTitle.Text := AModel.ApplicationTitle; 109 | edtApplicationDirectory.Text := AModel.ApplicationDirectory; 110 | cbShowExportedFiles.Checked := AModel.ShowInExplorer; 111 | 112 | for LFormNameAndFile in AModel.ApplicationForms do begin 113 | cbApplicationMainForm.Items.Add(LFormNameAndFile.CombineFileAndFormName()); 114 | lbForms.Items.Add(LFormNameAndFile.CombineFileAndFormName()); 115 | end; 116 | 117 | if (AModel.ApplicationMainForm.CombineFileAndFormName() <> String.Empty) then 118 | cbApplicationMainForm.ItemIndex := cbApplicationMainForm.Items.IndexOf( 119 | AModel.ApplicationMainForm.CombineFileAndFormName()) 120 | else if (cbApplicationMainForm.Items.Count > 0) then 121 | cbApplicationMainForm.ItemIndex := 0; 122 | 123 | case AModel.FormFileKind of 124 | ffkText: swFormFileKind.State := tssOff; 125 | ffkBinary: swFormFileKind.State := tssOn; 126 | end; 127 | 128 | Result := ShowModal() = mrOk; 129 | 130 | if not Result then 131 | Exit(); 132 | 133 | AModel.ApplicationTitle := edtApplicationTitle.Text; 134 | AModel.ApplicationMainForm := AModel.ApplicationForms[cbApplicationMainForm.ItemIndex]; 135 | AModel.ApplicationDirectory := edtApplicationDirectory.Text; 136 | if cbFormFileCompatibleMode.Checked then 137 | AModel.FormFileMode := TFormFileMode.ffmCompatible 138 | else 139 | AModel.FormFileMode := TFormFileMode.ffmPython; 140 | Amodel.ShowInExplorer := cbShowExportedFiles.Checked; 141 | 142 | case swFormFileKind.State of 143 | tssOff: AModel.FormFileKind := ffkText; 144 | tssOn: AModel.FormFileKind := ffkBinary; 145 | end; 146 | end; 147 | 148 | procedure TProjectExportDialog.FormShow(Sender: TObject); 149 | begin 150 | inherited; 151 | EnableHorizontalScrollBar(lbForms); 152 | end; 153 | 154 | procedure TProjectExportDialog.Label1Click(Sender: TObject); 155 | begin 156 | swFormFileKind.State := tssOn; 157 | end; 158 | 159 | procedure TProjectExportDialog.Label2Click(Sender: TObject); 160 | begin 161 | swFormFileKind.State := tssOff; 162 | end; 163 | 164 | procedure TProjectExportDialog.llblNotificationLinkClick(Sender: TObject; 165 | const Link: string; LinkType: TSysLinkType); 166 | Begin 167 | ShellExecute(0, 'open', pchar(Link), nil, nil, SW_NORMAL); 168 | end; 169 | 170 | procedure TProjectExportDialog.btnSelectDirClick(Sender: TObject); 171 | begin 172 | with FileOpenDialog1 do begin 173 | DefaultFolder := edtApplicationDirectory.Text; 174 | FileName := edtApplicationDirectory.Text; 175 | if Execute then 176 | edtApplicationDirectory.Text := FileName 177 | else 178 | edtApplicationDirectory.Text := String.Empty; 179 | end; 180 | end; 181 | 182 | end. 183 | -------------------------------------------------------------------------------- /Source/Design/PythonTools.Design.dfm: -------------------------------------------------------------------------------- 1 | object DesignForm: TDesignForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'DesignForm' 5 | ClientHeight = 464 6 | ClientWidth = 644 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -12 11 | Font.Name = 'Segoe UI' 12 | Font.Style = [] 13 | TextHeight = 15 14 | end 15 | -------------------------------------------------------------------------------- /Source/Design/PythonTools.Design.pas: -------------------------------------------------------------------------------- 1 | {$I PythonTools.inc} 2 | unit PythonTools.Design; 3 | 4 | interface 5 | 6 | uses 7 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 8 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ToolsAPI; 9 | 10 | type 11 | TDesignForm = class(TForm {$IFDEF DELPHI10_2_UP}, INTAIDEThemingServicesNotifier{$ENDIF DELPHI10_2_UP}) 12 | private 13 | {$IFDEF DELPHI10_2_UP} 14 | FIDEThemingNotifierId: integer; 15 | {$ENDIF DELPHI10_2_UP} 16 | private 17 | {$IFDEF DELPHI10_2_UP} 18 | //IOTANotifier 19 | procedure AfterSave; 20 | procedure BeforeSave; 21 | procedure Destroyed; 22 | procedure Modified; 23 | //INTAIDEThemingServicesNotifier 24 | procedure ChangingTheme(); 25 | procedure ChangedTheme(); 26 | {$ENDIF DELPHI10_2_UP} 27 | protected 28 | procedure RegisterIDEThemingNotifier(); 29 | procedure UnRegisterIDEThemingNotifier(); 30 | procedure ApplyIDETheming(); 31 | public 32 | constructor Create(AOwner: TComponent); override; 33 | destructor Destroy(); override; 34 | end; 35 | 36 | var 37 | DesignForm: TDesignForm; 38 | 39 | implementation 40 | 41 | {$R *.dfm} 42 | 43 | { TDesignForm } 44 | 45 | constructor TDesignForm.Create(AOwner: TComponent); 46 | begin 47 | inherited; 48 | {$IFDEF DELPHI10_2_UP} 49 | {$IFDEF DELPHI10_4_UP} 50 | with (BorlandIDEServices as IOTAIDEThemingServices) do begin 51 | {$ELSE} 52 | with (BorlandIDEServices as IOTAIDEThemingServices250) do begin 53 | {$ENDIF DELPHI10_4_UP} 54 | RegisterFormClass(TCustomFormClass(Self.ClassType)); 55 | ApplyIDETheming(); 56 | RegisterIDEThemingNotifier(); 57 | end; 58 | {$ENDIF DELPHI10_2_UP} 59 | end; 60 | 61 | destructor TDesignForm.Destroy; 62 | begin 63 | UnRegisterIDEThemingNotifier(); 64 | inherited; 65 | end; 66 | 67 | {$IFDEF DELPHI10_2_UP} 68 | 69 | procedure TDesignForm.AfterSave; 70 | begin 71 | end; 72 | 73 | procedure TDesignForm.BeforeSave; 74 | begin 75 | end; 76 | 77 | procedure TDesignForm.Destroyed; 78 | begin 79 | end; 80 | 81 | procedure TDesignForm.Modified; 82 | begin 83 | end; 84 | 85 | procedure TDesignForm.ChangingTheme; 86 | begin 87 | end; 88 | 89 | procedure TDesignForm.ChangedTheme; 90 | begin 91 | ApplyIDETheming(); 92 | end; 93 | 94 | {$ENDIF DELPHI10_2_UP} 95 | 96 | procedure TDesignForm.ApplyIDETheming; 97 | begin 98 | {$IFDEF DELPHI10_2_UP} 99 | with (BorlandIDEServices as IOTAIDEThemingServices) do begin 100 | ApplyTheme(Self); 101 | end; 102 | {$ENDIF DELPHI10_2_UP} 103 | end; 104 | 105 | procedure TDesignForm.RegisterIDEThemingNotifier; 106 | begin 107 | {$IFDEF DELPHI10_2_UP} 108 | with (BorlandIDEServices as IOTAIDEThemingServices) do begin 109 | FIDEThemingNotifierId := AddNotifier(Self); 110 | end; 111 | {$ENDIF DELPHI10_2_UP} 112 | end; 113 | 114 | procedure TDesignForm.UnRegisterIDEThemingNotifier; 115 | begin 116 | {$IFDEF DELPHI10_2_UP} 117 | with (BorlandIDEServices as IOTAIDEThemingServices) do begin 118 | RemoveNotifier(FIDEThemingNotifierId); 119 | end; 120 | {$ENDIF DELPHI10_2_UP} 121 | end; 122 | 123 | end. 124 | -------------------------------------------------------------------------------- /Source/Exporter/PythonTools.Exporter.Application.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Exporter.Application; 2 | 3 | interface 4 | 5 | uses 6 | ToolsAPI, 7 | PythonTools.Common, 8 | PythonTools.Producer, 9 | PythonTools.Producer.SimpleFactory, 10 | PythonTools.Model.Design.Project, 11 | PythonTools.Model.Producer.Application; 12 | 13 | type 14 | TApplicationExporter = class 15 | private 16 | FModel: TExportProjectDesignModel; 17 | FProject: IOTAProject; 18 | protected 19 | //Producers models 20 | function BuildApplicationProducerModel: TApplicationProducerModel; 21 | //Exporters 22 | procedure DoExportApplication; 23 | public 24 | constructor Create(const AExportProjectModel: TExportProjectDesignModel; 25 | const AProject: IOTAProject); 26 | 27 | procedure ExportApplication; 28 | end; 29 | 30 | implementation 31 | 32 | uses 33 | System.IOUtils, 34 | System.Classes, 35 | System.SysUtils; 36 | 37 | { TApplicationExporter } 38 | 39 | function TApplicationExporter.BuildApplicationProducerModel: TApplicationProducerModel; 40 | begin 41 | Result := TApplicationProducerModel.Create(); 42 | try 43 | Result.Directory := FModel.ApplicationDirectory; 44 | Result.FileName := ChangeFileExt(ExtractFileName(FProject.FileName), ''); 45 | Result.MainForm := FModel.ApplicationMainForm.FormName; 46 | Result.Title := FModel.ApplicationTitle; 47 | Result.ImportedForms := [FModel.ApplicationMainForm]; 48 | except 49 | on E: Exception do begin 50 | FreeAndNil(Result); 51 | raise; 52 | end; 53 | end; 54 | end; 55 | 56 | constructor TApplicationExporter.Create( 57 | const AExportProjectModel: TExportProjectDesignModel; const AProject: IOTAProject); 58 | begin 59 | FModel := AExportProjectModel; 60 | FProject := AProject; 61 | end; 62 | 63 | procedure TApplicationExporter.DoExportApplication; 64 | var 65 | LProducer: IPythonCodeProducer; 66 | LProducerModel: TApplicationProducerModel; 67 | begin 68 | LProducer := TProducerSimpleFactory.CreateProducer(FProject.FrameworkType); 69 | 70 | LProducerModel := BuildApplicationProducerModel(); 71 | try 72 | LProducer.SavePyApplicationFile(LProducerModel, LProducerModel.Stream); 73 | finally 74 | LProducerModel.Free(); 75 | end; 76 | end; 77 | 78 | procedure TApplicationExporter.ExportApplication; 79 | begin 80 | DoExportApplication(); 81 | end; 82 | 83 | end. 84 | -------------------------------------------------------------------------------- /Source/Exporter/PythonTools.Exporter.Form.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Exporter.Form; 2 | 3 | interface 4 | 5 | uses 6 | DesignIntf, 7 | System.Classes, System.Generics.Collections, System.Rtti, 8 | PythonTools.Common, 9 | PythonTools.IOTAUtils, 10 | PythonTools.Model.Producer.Form, 11 | PythonTools.Model.Producer.FormFile, 12 | PythonTools.Model.Design.Forms, 13 | PythonTools.Model.Design.Project; 14 | 15 | type 16 | TFormExporter = class abstract 17 | private 18 | //Utils 19 | function FindComponents(): TExportedComponents; 20 | function FindEvents(): TExportedEvents; 21 | protected 22 | FormInfo: TIOTAFormInfo; 23 | //Producer models 24 | function BuildFormModel: TFormProducerModel; virtual; 25 | function BuildFormFileModel: TFormFileProducerModel; virtual; 26 | //Exporters 27 | procedure DoExportForm(const AFormModel: TFormProducerModel; 28 | const AFormFileModel: TFormFileProducerModel); 29 | procedure DoExportFormFileBin(const AModel: TFormFileProducerModel); 30 | procedure DoExportFormFileTxt(const AModel: TFormFileProducerModel); 31 | public 32 | constructor Create(const AFormInfo: TIOTAFormInfo); 33 | 34 | procedure ExportForm; 35 | procedure ExportFormFile(const AFormFileKind: TFormFileKind); 36 | end; 37 | 38 | TFormExporterFromProject = class sealed(TFormExporter) 39 | private 40 | FModel: TExportProjectDesignModel; 41 | protected 42 | //Producer models 43 | function BuildFormModel: TFormProducerModel; override; 44 | function BuildFormFileModel: TFormFileProducerModel; override; 45 | public 46 | constructor Create(const AModel: TExportProjectDesignModel; 47 | const AFormInfo: TIOTAFormInfo); 48 | end; 49 | 50 | TFormExporterFromForms = class sealed(TFormExporter) 51 | private 52 | FModel: TExportFormsDesignModel; 53 | FCurrentForm: integer; 54 | protected 55 | //Producer models 56 | function BuildFormModel: TFormProducerModel; override; 57 | function BuildFormFileModel: TFormFileProducerModel; override; 58 | public 59 | constructor Create(const AModel: TExportFormsDesignModel; 60 | const ACurrentForm: integer; const AFormInfo: TIOTAFormInfo); 61 | end; 62 | 63 | implementation 64 | 65 | uses 66 | System.SysUtils, 67 | PythonTools.Exceptions, 68 | PythonTools.Producer, 69 | PythonTools.Producer.SimpleFactory; 70 | 71 | { TFormExporter } 72 | 73 | constructor TFormExporter.Create(const AFormInfo: TIOTAFormInfo); 74 | begin 75 | FormInfo := AFormInfo; 76 | end; 77 | 78 | function TFormExporter.FindComponents(): TExportedComponents; 79 | begin 80 | Result := TIOTAUtils.FindComponents(FormInfo.Editor); 81 | end; 82 | 83 | function TFormExporter.FindEvents(): TExportedEvents; 84 | begin 85 | Result := TIOTAUtils.FindEvents(FormInfo.Editor, FormInfo.Designer); 86 | end; 87 | 88 | procedure TFormExporter.ExportForm; 89 | var 90 | LFormProducerModel: TFormProducerModel; 91 | LFormFileProducerModel: TFormFileProducerModel; 92 | begin 93 | LFormProducerModel := BuildFormModel(); 94 | try 95 | LFormFileProducerModel := BuildFormFileModel(); 96 | try 97 | DoExportForm(LFormProducerModel, LFormFileProducerModel); 98 | finally 99 | LFormFileProducerModel.Free(); 100 | end; 101 | finally 102 | LFormProducerModel.Free(); 103 | end; 104 | end; 105 | 106 | procedure TFormExporter.ExportFormFile(const AFormFileKind: TFormFileKind); 107 | var 108 | LProducerModel: TFormFileProducerModel; 109 | begin 110 | LProducerModel := BuildFormFileModel(); 111 | try 112 | if (AFormFileKind = ffkText) then 113 | DoExportFormFileTxt(LProducerModel) 114 | else if (AFormFileKind = ffkBinary) then 115 | DoExportFormFileBin(LProducerModel) 116 | else 117 | raise EInvalidFormFileKind.Create('Invalid form file kind.'); 118 | finally 119 | LProducerModel.Free(); 120 | end; 121 | end; 122 | 123 | function TFormExporter.BuildFormModel: TFormProducerModel; 124 | begin 125 | Result := TFormProducerModel.Create(); 126 | try 127 | with Result do begin 128 | FormName := FormInfo.FormName; 129 | FormParentName := System.Copy( 130 | FormInfo.Designer.Root.ClassParent.ClassName, 131 | 2, 132 | FormInfo.Designer.Root.ClassParent.ClassName.Length); 133 | FileName := ChangeFileExt(ExtractFileName(FormInfo.FileName), ''); 134 | ExportedComponents := FindComponents(); 135 | ExportedEvents := FindEvents(); 136 | with ModuleInitialization do begin 137 | GenerateInitialization := false; 138 | end; 139 | end; 140 | except 141 | on E: Exception do begin 142 | FreeAndNil(Result); 143 | raise; 144 | end; 145 | end; 146 | end; 147 | 148 | function TFormExporter.BuildFormFileModel: TFormFileProducerModel; 149 | begin 150 | Result := TFormFileProducerModel.Create(); 151 | try 152 | with Result do begin 153 | FileName := ChangeFileExt(ExtractFileName(FormInfo.FileName), ''); 154 | Form := FormInfo.Designer.Root; 155 | FormInfo.Editor.GetFormResource(TStreamAdapter.Create(FormResource)); 156 | FormResource.Position := 0; 157 | end; 158 | except 159 | on E: Exception do begin 160 | FreeAndNil(Result); 161 | raise; 162 | end; 163 | end; 164 | end; 165 | 166 | procedure TFormExporter.DoExportForm(const AFormModel: TFormProducerModel; 167 | const AFormFileModel: TFormFileProducerModel); 168 | var 169 | LProducer: IPythonCodeProducer; 170 | begin 171 | LProducer := TProducerSimpleFactory.CreateProducer(FormInfo.FrameworkType); 172 | 173 | if not LProducer.IsValidFormInheritance(FormInfo.Designer.Root.ClassParent) then 174 | raise EFormInheritanceNotSupported.CreateFmt( 175 | '%s TForm direct inheritance only', [FormInfo.FrameworkType]); 176 | 177 | LProducer.SavePyForm(AFormModel, AFormFileModel, AFormModel.Stream); 178 | end; 179 | 180 | procedure TFormExporter.DoExportFormFileTxt(const AModel: TFormFileProducerModel); 181 | var 182 | LProducer: IPythonCodeProducer; 183 | begin 184 | LProducer := TProducerSimpleFactory.CreateProducer(FormInfo.FrameworkType); 185 | LProducer.SavePyFormFileTxt(AModel, AModel.Stream); 186 | end; 187 | 188 | procedure TFormExporter.DoExportFormFileBin(const AModel: TFormFileProducerModel); 189 | var 190 | LProducer: IPythonCodeProducer; 191 | begin 192 | LProducer := TProducerSimpleFactory.CreateProducer(FormInfo.FrameworkType); 193 | LProducer.SavePyFormFileBin(AModel, AModel.Stream); 194 | end; 195 | 196 | { TFormExporterFromProject } 197 | 198 | constructor TFormExporterFromProject.Create( 199 | const AModel: TExportProjectDesignModel; const AFormInfo: TIOTAFormInfo); 200 | begin 201 | inherited Create(AFormInfo); 202 | FModel := AModel; 203 | end; 204 | 205 | function TFormExporterFromProject.BuildFormModel: TFormProducerModel; 206 | begin 207 | Result := inherited; 208 | Result.Directory := FModel.ApplicationDirectory; 209 | Result.FileName := ChangeFileExt(ExtractFileName(FormInfo.FileName), ''); 210 | end; 211 | 212 | function TFormExporterFromProject.BuildFormFileModel: TFormFileProducerModel; 213 | begin 214 | Result := inherited; 215 | Result.Directory := FModel.ApplicationDirectory; 216 | Result.FileName := ChangeFileExt(ExtractFileName(FormInfo.FileName), ''); 217 | Result.Mode := FModel.FormFileMode; 218 | Result.FrameworkType := FormInfo.FrameworkType; 219 | end; 220 | 221 | { TFormExporterFromForms } 222 | 223 | constructor TFormExporterFromForms.Create(const AModel: TExportFormsDesignModel; 224 | const ACurrentForm: integer; const AFormInfo: TIOTAFormInfo); 225 | begin 226 | inherited Create(AFormInfo); 227 | FModel := AModel; 228 | FCurrentForm := ACurrentForm; 229 | end; 230 | 231 | function TFormExporterFromForms.BuildFormModel: TFormProducerModel; 232 | var 233 | LForm: TOutputForm; 234 | begin 235 | Result := inherited; 236 | Result.Directory := FModel.Directory; 237 | Result.FileName := ChangeFileExt(ExtractFileName(FormInfo.FileName), ''); 238 | with Result.ModuleInitialization do begin 239 | LForm := FModel.OutputForms[FCurrentForm]; 240 | //Generate the initialization section for the MainForm only 241 | if LForm.GenerateInitialization 242 | and (Result.FormName = LForm.Form.FormName) then 243 | begin 244 | GenerateInitialization := true; 245 | Title := LForm.Title; 246 | MainForm := LForm.Form.FormName; 247 | end else 248 | GenerateInitialization := false; 249 | end; 250 | end; 251 | 252 | function TFormExporterFromForms.BuildFormFileModel: TFormFileProducerModel; 253 | begin 254 | Result := inherited; 255 | Result.Directory := FModel.Directory; 256 | Result.FileName := ChangeFileExt(ExtractFileName(FormInfo.FileName), ''); 257 | Result.Mode := FModel.OutputForms[FCurrentForm].FormFileMode; 258 | Result.FrameworkType := FormInfo.FrameworkType; 259 | end; 260 | 261 | end. 262 | -------------------------------------------------------------------------------- /Source/Exporter/PythonTools.Exporter.Forms.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Exporter.Forms; 2 | 3 | interface 4 | 5 | uses 6 | ToolsAPI, 7 | PythonTools.IOTAUtils, 8 | PythonTools.Model.Design.Forms; 9 | 10 | type 11 | TFormsExporter = class 12 | protected 13 | //Producer models 14 | function BuildExportFormsModel: TExportFormsDesignModel; 15 | public 16 | //constructor Create(const AProject: IOTAProject); 17 | //Request export project info 18 | function RequestExportInfo(const AModel: TExportFormsDesignModel): boolean; 19 | //Export the given project 20 | function ExportForms(): boolean; 21 | end; 22 | 23 | implementation 24 | 25 | uses 26 | System.SysUtils, System.Generics.Collections, 27 | ShellApi, Winapi.Windows, 28 | PythonTools.Exceptions, PythonTools.Common, PythonTools.Registry, 29 | PythonTools.Exporter.Form, 30 | PythonTools.Design.Forms; 31 | 32 | { TFormsExporter } 33 | 34 | function TFormsExporter.BuildExportFormsModel: TExportFormsDesignModel; 35 | var 36 | LInputs: TList; 37 | LInput: TInputForm; 38 | begin 39 | Result := TExportFormsDesignModel.Create(); 40 | try 41 | // Result.Title := String.Empty; 42 | Result.Directory := String.Empty; 43 | LInputs := TList.Create(); 44 | try 45 | TIOTAUtils.EnumForms(procedure(AFormInfo: TIOTAFormInfo) begin 46 | LInput.Form := TFormNameAndFile.Create( 47 | AFormInfo.FormName, 48 | ChangeFileExt(ExtractFileName(AFormInfo.FileName), '')); 49 | LInput.Title := AFormInfo.Caption; 50 | LInputs.Add(LInput); 51 | end); 52 | 53 | Result.InputForms := LInputs.ToArray(); 54 | finally 55 | LInputs.Free(); 56 | end; 57 | except 58 | on E: Exception do begin 59 | FreeAndNil(Result); 60 | raise; 61 | end; 62 | end; 63 | end; 64 | 65 | function TFormsExporter.ExportForms: boolean; 66 | var 67 | I: integer; 68 | LExportModel: TExportFormsDesignModel; 69 | LFormInfo: TIOTAFormInfo; 70 | LFormExporter: TFormExporterFromForms; 71 | begin 72 | LExportModel := BuildExportFormsModel(); 73 | try 74 | TExporterRegistry.LoadFormsModel(LExportModel); 75 | //Request user info 76 | if not RequestExportInfo(LExportModel) then 77 | Exit(false); 78 | TExporterRegistry.SaveFormsModel(LExportModel); 79 | 80 | //Export each selected form 81 | for I := Low(LExportModel.OutputForms) to High(LExportModel.OutputForms) do 82 | if TIOTAUtils.FindForm(LExportModel.OutputForms[I].Form.FormName, LFormInfo) then begin 83 | //Export the current form 84 | LFormExporter := TFormExporterFromForms.Create(LExportModel, I, LFormInfo); 85 | try 86 | //Export current form 87 | LFormExporter.ExportForm(); 88 | //Export current form dfm/fmx 89 | LFormExporter.ExportFormFile(LExportModel.OutputForms[I].FormFileKind); 90 | finally 91 | LFormExporter.Free(); 92 | end; 93 | end; 94 | 95 | if LExportModel.ShowInExplorer then 96 | ShellExecute(0, 'open', PChar(LExportModel.Directory), nil, nil, SW_NORMAL); 97 | finally 98 | LExportModel.Free(); 99 | end; 100 | Result := true; 101 | end; 102 | 103 | function TFormsExporter.RequestExportInfo( 104 | const AModel: TExportFormsDesignModel): boolean; 105 | var 106 | LForm: TFormsExportDialog; 107 | begin 108 | LForm := TFormsExportDialog.Create(nil); 109 | try 110 | Result := LForm.Execute(AModel); 111 | finally 112 | LForm.Free(); 113 | end; 114 | end; 115 | 116 | end. 117 | -------------------------------------------------------------------------------- /Source/Exporter/PythonTools.Exporter.Project.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Exporter.Project; 2 | 3 | interface 4 | 5 | uses 6 | ToolsAPI, 7 | PythonTools.IOTAUtils, 8 | PythonTools.Model.Design.Project; 9 | 10 | type 11 | TProjectExporter = class 12 | private 13 | FProject: IOTAProject; 14 | protected 15 | //Checks 16 | procedure CheckDesigner(const AFormInfo: TIOTAFormInfo); 17 | //Producer models 18 | function BuildExportProjectModel: TExportProjectDesignModel; 19 | public 20 | constructor Create(const AProject: IOTAProject); 21 | //Request export project info 22 | function RequestExportInfo(const AModel: TExportProjectDesignModel): boolean; 23 | //Export the given project 24 | function ExportProject(): boolean; 25 | end; 26 | 27 | implementation 28 | 29 | uses 30 | System.SysUtils, 31 | ShellApi, Winapi.Windows, 32 | PythonTools.Exceptions, PythonTools.Common, PythonTools.Registry, 33 | PythonTools.Exporter.Application, 34 | PythonTools.Exporter.Form, 35 | PythonTools.Design.Project; 36 | 37 | { TProjectExporter } 38 | 39 | constructor TProjectExporter.Create(const AProject: IOTAProject); 40 | begin 41 | FProject := AProject; 42 | end; 43 | 44 | function TProjectExporter.ExportProject: boolean; 45 | var 46 | LExportProjectModel: TExportProjectDesignModel; 47 | LAppExporter: TApplicationExporter; 48 | begin 49 | LExportProjectModel := BuildExportProjectModel(); 50 | try 51 | TExporterRegistry.LoadProjectModel(LExportProjectModel); 52 | //Request user info 53 | if not RequestExportInfo(LExportProjectModel) then 54 | Exit(false); 55 | TExporterRegistry.SaveProjectModel(LExportProjectModel); 56 | //Export the application file as the app initializer 57 | LAppExporter := TApplicationExporter.Create(LExportProjectModel, FProject); 58 | try 59 | LAppExporter.ExportApplication(); 60 | finally 61 | LAppExporter.Free(); 62 | end; 63 | 64 | //Navigate through all forms 65 | TIOTAUtils.EnumForms(FProject, procedure(AFormInfo: TIOTAFormInfo) 66 | var 67 | LFormExporter: TFormExporter; 68 | begin 69 | //Check for valid instances 70 | CheckDesigner(AFormInfo); 71 | //Export the current form 72 | LFormExporter := TFormExporterFromProject.Create(LExportProjectModel, AFormInfo); 73 | try 74 | //Export current form 75 | LFormExporter.ExportForm(); 76 | //Export current form dfm/fmx 77 | LFormExporter.ExportFormFile(LExportProjectModel.FormFileKind); 78 | finally 79 | LFormExporter.Free(); 80 | end; 81 | end); 82 | 83 | if LExportProjectModel.ShowInExplorer then 84 | ShellExecute(0, 'open', PChar(LExportProjectModel.ApplicationDirectory), nil, nil, SW_NORMAL); 85 | 86 | Result := true; 87 | finally 88 | LExportProjectModel.Free(); 89 | end; 90 | end; 91 | 92 | procedure TProjectExporter.CheckDesigner(const AFormInfo: TIOTAFormInfo); 93 | begin 94 | if not Assigned(AFormInfo.Designer) then 95 | raise EUnableToObtainFormDesigner.CreateFmt( 96 | 'Unable to obtain the form designer for type %s.', [AFormInfo.FormName]); 97 | end; 98 | 99 | function TProjectExporter.BuildExportProjectModel: TExportProjectDesignModel; 100 | var 101 | LFormInfo: TFormNameAndFileList; 102 | begin 103 | Result := TExportProjectDesignModel.Create(); 104 | try 105 | Result.ApplicationId := FProject.GetProjectGUID(); 106 | Result.ApplicationName := ChangeFileExt( 107 | ExtractFileName(FProject.FileName), String.Empty); 108 | LFormInfo := TFormNameAndFileList.Create(); 109 | try 110 | TIOTAUtils.EnumForms(FProject, procedure(AFormInfo: TIOTAFormInfo) begin 111 | LFormInfo.Add(TFormNameAndFile.Create( 112 | AFormInfo.FormName, 113 | ChangeFileExt(ExtractFileName(AFormInfo.FileName), ''))); 114 | end); 115 | Result.ApplicationForms := LFormInfo.ToArray(); 116 | finally 117 | LFormInfo.Free(); 118 | end; 119 | except 120 | on E: Exception do begin 121 | FreeAndNil(Result); 122 | raise; 123 | end; 124 | end; 125 | end; 126 | 127 | function TProjectExporter.RequestExportInfo( 128 | const AModel: TExportProjectDesignModel): boolean; 129 | var 130 | LForm: TProjectExportDialog; 131 | begin 132 | LForm := TProjectExportDialog.Create(nil); 133 | try 134 | Result := LForm.Execute(AModel); 135 | finally 136 | LForm.Free(); 137 | end; 138 | end; 139 | 140 | end. 141 | -------------------------------------------------------------------------------- /Source/Menu/PythonTools.Menu.ExportForms.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Menu.ExportForms; 2 | 3 | interface 4 | 5 | uses 6 | Vcl.ActnList, Vcl.Menus; 7 | 8 | type 9 | TPythonToolsExportFormsMenuAction = class(TCustomAction) 10 | private 11 | procedure DoExportForms(Sender: TObject); 12 | public 13 | procedure AfterConstruction(); override; 14 | 15 | function Update: boolean; override; 16 | end; 17 | 18 | TPythonToolsExportFormsMenuItem = class(TMenuItem) 19 | public 20 | procedure AfterConstruction(); override; 21 | end; 22 | 23 | implementation 24 | 25 | uses 26 | Vcl.Dialogs, 27 | PythonTools.IOTAUtils, 28 | PythonTools.Exporter.Forms; 29 | 30 | { TPythonToolsExportFormsMenuAction } 31 | 32 | procedure TPythonToolsExportFormsMenuAction.AfterConstruction; 33 | begin 34 | inherited; 35 | Name := 'PythonToolsExportFormsAction'; 36 | Caption := 'Export Select Forms'; 37 | OnExecute := DoExportForms; 38 | end; 39 | 40 | procedure TPythonToolsExportFormsMenuAction.DoExportForms(Sender: TObject); 41 | var 42 | LExporter: TFormsExporter; 43 | begin 44 | //Exports the current project 45 | LExporter := TFormsExporter.Create(); 46 | try 47 | if LExporter.ExportForms() then 48 | ShowMessage('Forms successfully exported.'); 49 | finally 50 | LExporter.Free(); 51 | end; 52 | end; 53 | 54 | function TPythonToolsExportFormsMenuAction.Update: boolean; 55 | begin 56 | Enabled := TIOTAUtils.HasForms(); 57 | Result := inherited; 58 | end; 59 | 60 | { TPythonToolsExportFormsMenuItem } 61 | 62 | procedure TPythonToolsExportFormsMenuItem.AfterConstruction; 63 | begin 64 | inherited; 65 | Name := 'PythonToolsExportFormsMenu'; 66 | end; 67 | 68 | end. 69 | -------------------------------------------------------------------------------- /Source/Menu/PythonTools.Menu.ExportProject.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Menu.ExportProject; 2 | 3 | interface 4 | 5 | uses 6 | ToolsAPI, 7 | System.Classes, System.SysUtils, 8 | Vcl.ActnList, Vcl.Menus, Vcl.Dialogs; 9 | 10 | type 11 | TPythonToolsExportProjectMenuAction = class(TCustomAction) 12 | private 13 | procedure DoExportProject(Sender: TObject); 14 | public 15 | constructor Create(AOwner: TComponent); override; 16 | 17 | function Update: boolean; override; 18 | end; 19 | 20 | TPythonToolsExportProjectMenuItem = class(TMenuItem) 21 | public 22 | procedure AfterConstruction(); override; 23 | end; 24 | 25 | implementation 26 | 27 | uses 28 | System.StrUtils, 29 | PythonTools.Exporter.Project; 30 | 31 | { TPythonToolsExportProjectMenuAction } 32 | 33 | constructor TPythonToolsExportProjectMenuAction.Create(AOwner: TComponent); 34 | begin 35 | inherited; 36 | Name := 'PythonToolsExportProjectAction'; 37 | Caption := 'Export Entire Current Project'; 38 | OnExecute := DoExportProject; 39 | end; 40 | 41 | function TPythonToolsExportProjectMenuAction.Update: boolean; 42 | begin 43 | Enabled := Assigned(GetActiveProject()); 44 | Result := inherited; 45 | end; 46 | 47 | procedure TPythonToolsExportProjectMenuAction.DoExportProject(Sender: TObject); 48 | var 49 | LExporter: TProjectExporter; 50 | begin 51 | //Exports the current project 52 | LExporter := TProjectExporter.Create(GetActiveProject()); 53 | try 54 | if LExporter.ExportProject() then 55 | ShowMessage('Project successfully exported.'); 56 | finally 57 | LExporter.Free(); 58 | end; 59 | end; 60 | 61 | { TPythonToolsExportProjectMenuItem } 62 | 63 | procedure TPythonToolsExportProjectMenuItem.AfterConstruction; 64 | begin 65 | inherited; 66 | Name := 'PythonToolsExportProjectMenu'; 67 | end; 68 | 69 | end. 70 | -------------------------------------------------------------------------------- /Source/Menu/PythonTools.Menu.pas: -------------------------------------------------------------------------------- 1 | {$I PythonTools.inc} 2 | 3 | unit PythonTools.Menu; 4 | 5 | interface 6 | 7 | uses 8 | ToolsAPI, System.SysUtils, System.Classes, System.Generics.Collections, 9 | Winapi.Messages, 10 | Vcl.Menus, Vcl.ImgList, Vcl.Graphics, Vcl.ActnList, Vcl.Controls; 11 | 12 | type 13 | TToolsMenuEventHook = class; 14 | 15 | TPythonToolsMenu = class 16 | private 17 | class var FInstance: TPythonToolsMenu; 18 | private 19 | FToolsMenuItems: TObjectList; 20 | FToolsMenuHook: TToolsMenuEventHook; 21 | function GetINTAServices(): INTAServices; 22 | function GetToolsMenu(): TMenuItem; 23 | function LoadPythonToolMenuImage(): integer; 24 | 25 | procedure DoCreateMenuHooked(Sender: TObject); 26 | procedure DoDestroyMenu(); 27 | public 28 | class procedure Initialize(); 29 | class procedure Finalize(); 30 | 31 | constructor Create(); 32 | destructor Destroy(); override; 33 | 34 | //Include the PythonTools menu under Tools 35 | procedure BuildMenu(); 36 | 37 | //Hook the menu creation to a event 38 | procedure HookMenu(); 39 | procedure UnHookMenu(); 40 | 41 | function BuildPythonToolsSeparatorMenuItem(): TMenuItem; 42 | function BuildPythonToolsMenuItem(const ACallback: TProc): TMenuItem; 43 | function BuildPythonToolsExportProjectMenuItem(AOwner: TMenuItem): TMenuItem; 44 | function BuildPythonToolsExportFormsMenuItem(AOwner: TMenuItem): TMenuItem; 45 | 46 | class property Instance: TPythonToolsMenu read FInstance; 47 | end; 48 | 49 | {**** We're creating the menu after the first user's click on the "Tools" menu. ****} 50 | {**** The coreide lib rebuilds the "Tools" menu, removing unknown items at the ending of the list ****} 51 | TToolsMenuEventHook = class 52 | private 53 | FMenuItem: TMenuItem; 54 | FHook: TNotifyEvent; 55 | FDefaultAction: TNotifyEvent; 56 | procedure DoEvent(Sender: TObject); 57 | public 58 | constructor Create(AMenuItem: TMenuItem); reintroduce; 59 | destructor Destroy(); override; 60 | 61 | procedure Hook(AEvt: TNotifyEvent); 62 | procedure UnHook(AEvt: TNotifyEvent); 63 | end; 64 | 65 | implementation 66 | 67 | uses 68 | Vcl.Imaging.pngimage, 69 | PythonTools.Menu.ExportProject, PythonTools.Menu.ExportForms; 70 | 71 | const 72 | sToolsMenu = 'ToolsMenu'; 73 | sPythonToolsMenuItem = 'PythonToolsMenuItem'; 74 | 75 | type 76 | TPythonToolsMenuAction = class(TCustomAction) 77 | end; 78 | 79 | TPythonToolsMenuItem = class(TMenuItem) 80 | end; 81 | 82 | { TPythonToolsMenu } 83 | 84 | class procedure TPythonToolsMenu.Initialize; 85 | begin 86 | FInstance := TPythonToolsMenu.Create(); 87 | end; 88 | 89 | class procedure TPythonToolsMenu.Finalize; 90 | begin 91 | FInstance.Free(); 92 | end; 93 | 94 | constructor TPythonToolsMenu.Create; 95 | begin 96 | FToolsMenuItems := TObjectList.Create(); 97 | FToolsMenuHook := TToolsMenuEventHook.Create(GetToolsMenu()); 98 | end; 99 | 100 | destructor TPythonToolsMenu.Destroy; 101 | begin 102 | DoDestroyMenu(); 103 | FToolsMenuItems.Free(); 104 | FToolsMenuHook.Free(); 105 | inherited; 106 | end; 107 | 108 | function TPythonToolsMenu.GetToolsMenu: TMenuItem; 109 | var 110 | LMenuItem: TMenuItem; 111 | begin 112 | for LMenuItem in GetINTAServices().MainMenu.Items do begin 113 | if (LMenuItem.Name = sToolsMenu) then 114 | Exit(LMenuItem); 115 | end; 116 | raise Exception.Create('Tools menu not found.'); 117 | end; 118 | 119 | function TPythonToolsMenu.GetINTAServices: INTAServices; 120 | begin 121 | if not Supports(BorlandIDEServices, INTAServices, Result) then 122 | raise Exception.Create('An error ocurred while accessing the IDE services.'); 123 | end; 124 | 125 | procedure TPythonToolsMenu.HookMenu; 126 | begin 127 | if Assigned(FToolsMenuHook) then 128 | FToolsMenuHook.Hook(DoCreateMenuHooked); 129 | end; 130 | 131 | procedure TPythonToolsMenu.UnHookMenu; 132 | begin 133 | if Assigned(FToolsMenuHook) then 134 | FToolsMenuHook.UnHook(DoCreateMenuHooked); 135 | end; 136 | 137 | procedure TPythonToolsMenu.BuildMenu; 138 | var 139 | LServices: INTAServices; 140 | begin 141 | LServices := GetINTAServices(); 142 | LServices.MenuBeginUpdate(); 143 | try 144 | //Tools->--------- 145 | LServices.AddActionMenu(sToolsMenu, nil, BuildPythonToolsSeparatorMenuItem(), true, true); 146 | //Tools->Export to Python 147 | BuildPythonToolsMenuItem(procedure(AMenuItem: TMenuItem; AAction: TCustomAction) begin 148 | LServices.AddActionMenu(sToolsMenu, AAction, AMenuItem, true, true); 149 | AMenuItem.Add([ 150 | //Tools->Export to Python->Export Current Project 151 | BuildPythonToolsExportProjectMenuItem(AMenuItem), 152 | //Tools->Export to Python->Export Forms 153 | BuildPythonToolsExportFormsMenuItem(AMenuItem) 154 | ]); 155 | end); 156 | finally 157 | LServices.MenuEndUpdate(); 158 | end; 159 | end; 160 | 161 | function TPythonToolsMenu.LoadPythonToolMenuImage(): integer; 162 | const 163 | EMB_PY_IMG = 'embarcaderopython_16px'; 164 | var 165 | LImg: {$IFDEF DELPHI11_UP}TPngImage{$ELSE}TBitmap{$ENDIF DELPHI11_UP}; 166 | begin 167 | LImg := {$IFDEF DELPHI11_UP}TPngImage{$ELSE}TBitmap{$ENDIF DELPHI11_UP}.Create(); 168 | try 169 | LImg.LoadFromResourceName(HInstance, EMB_PY_IMG); 170 | {$IFDEF DELPHI11_UP} 171 | Result := GetINTAServices().AddImage(EMB_PY_IMG, [LImg]); 172 | {$ELSE} 173 | Result := GetINTAServices().AddMasked(LImg, LImg.Handle, EMB_PY_IMG); 174 | {$ENDIF DELPHI11_UP} 175 | finally 176 | LImg.Free(); 177 | end; 178 | end; 179 | 180 | function TPythonToolsMenu.BuildPythonToolsExportFormsMenuItem(AOwner: TMenuItem): TMenuItem; 181 | begin 182 | Result := TPythonToolsExportFormsMenuItem.Create(AOwner); 183 | Result.Action := TPythonToolsExportFormsMenuAction.Create(Result); 184 | end; 185 | 186 | function TPythonToolsMenu.BuildPythonToolsExportProjectMenuItem(AOwner: TMenuItem): TMenuItem; 187 | begin 188 | Result := TPythonToolsExportProjectMenuItem.Create(AOwner); 189 | Result.Action := TPythonToolsExportProjectMenuAction.Create(Result); 190 | end; 191 | 192 | function TPythonToolsMenu.BuildPythonToolsMenuItem( 193 | const ACallback: TProc): TMenuItem; 194 | var 195 | LAction: TPythonToolsMenuAction; 196 | begin 197 | Result := TPythonToolsMenuItem.Create(nil); 198 | try 199 | LAction := TPythonToolsMenuAction.Create(Result); 200 | LAction.Caption := 'Export to Python'; 201 | LAction.ImageIndex := LoadPythonToolMenuImage(); 202 | ACallback(Result, TCustomAction(Result.Action)); 203 | Result.Action := LAction; 204 | Result.Name := sPythonToolsMenuItem; 205 | Result.ImageIndex := LAction.ImageIndex; 206 | Result.AutoHotkeys := maAutomatic; 207 | finally 208 | FToolsMenuItems.Add(Result) 209 | end; 210 | end; 211 | 212 | function TPythonToolsMenu.BuildPythonToolsSeparatorMenuItem: TMenuItem; 213 | begin 214 | Result := TMenuItem.Create(nil); 215 | try 216 | Result.Caption := '-'; 217 | finally 218 | FToolsMenuItems.Add(Result); 219 | end; 220 | end; 221 | 222 | procedure TPythonToolsMenu.DoCreateMenuHooked(Sender: TObject); 223 | begin 224 | try 225 | BuildMenu(); 226 | finally 227 | UnHookMenu(); 228 | end; 229 | end; 230 | 231 | procedure TPythonToolsMenu.DoDestroyMenu; 232 | var 233 | LRoot: TMenuItem; 234 | LMenuItem: TMenuItem; 235 | begin 236 | LRoot := GetToolsMenu(); 237 | if Assigned(LRoot) then begin 238 | with GetINTAServices() do begin 239 | MenuBeginUpdate(); 240 | try 241 | for LMenuItem in FToolsMenuItems do begin 242 | LRoot.Remove(LMenuItem); 243 | end; 244 | FToolsMenuItems.Clear(); 245 | finally 246 | MenuEndUpdate(); 247 | end; 248 | end; 249 | end; 250 | end; 251 | 252 | { TToolsMenuEventHook } 253 | 254 | constructor TToolsMenuEventHook.Create(AMenuItem: TMenuItem); 255 | begin 256 | inherited Create(); 257 | FMenuItem := AMenuItem; 258 | if Assigned(FMenuItem.Action) and Assigned(FMenuItem.Action.OnExecute) then begin 259 | FDefaultAction := FMenuItem.Action.OnExecute; 260 | FMenuItem.Action.OnExecute := DoEvent; 261 | end else begin 262 | if Assigned(FMenuItem.OnClick) then 263 | FDefaultAction := FMenuItem.OnClick 264 | else 265 | FDefaultAction := nil; 266 | FMenuItem.OnClick := DoEvent; 267 | end; 268 | end; 269 | 270 | destructor TToolsMenuEventHook.Destroy; 271 | begin 272 | if Assigned(FMenuItem.Action) and Assigned(FMenuItem.Action.OnExecute) then begin 273 | FMenuItem.Action.OnExecute := FDefaultAction; 274 | end else begin 275 | FMenuItem.OnClick := FDefaultAction; 276 | end; 277 | inherited; 278 | end; 279 | 280 | procedure TToolsMenuEventHook.DoEvent(Sender: TObject); 281 | begin 282 | if Assigned(FDefaultAction) then 283 | FDefaultAction(Sender); 284 | 285 | if Assigned(FHook) then 286 | FHook(Sender); 287 | end; 288 | 289 | procedure TToolsMenuEventHook.Hook(AEvt: TNotifyEvent); 290 | begin 291 | FHook := AEvt; 292 | end; 293 | 294 | procedure TToolsMenuEventHook.UnHook(AEvt: TNotifyEvent); 295 | begin 296 | if (TMethod(FHook).Code = TMethod(AEvt).Code) 297 | and (TMethod(FHook).Data = TMethod(AEvt).Data) then 298 | FHook := nil; 299 | end; 300 | 301 | initialization 302 | TPythonToolsMenu.Initialize(); 303 | 304 | finalization 305 | TPythonToolsMenu.Finalize(); 306 | 307 | end. 308 | -------------------------------------------------------------------------------- /Source/Model/Design/PythonTools.Model.Design.Forms.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Model.Design.Forms; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | PythonTools.Common; 8 | 9 | type 10 | TOutputForm = record 11 | private 12 | FForm: TFormNameAndFile; 13 | FGenerateInitialization: boolean; 14 | FTitle: string; 15 | FFormFileKind: TFormFileKind; 16 | FFormFileMode: TFormFileMode; 17 | public 18 | constructor Create(const AForm: TFormNameAndFile; 19 | const AGenerateInitialization: boolean; 20 | const ATitle: string; 21 | const AFormFileKind: TFormFileKind; 22 | const AFormFileMode: TFormFileMode); 23 | 24 | property Form: TFormNameAndFile read FForm write FForm; 25 | property GenerateInitialization: boolean read FGenerateInitialization write FGenerateInitialization; 26 | property Title: string read FTitle write FTitle; 27 | property FormFileKind: TFormFileKind read FFormFileKind write FFormFileKind; 28 | property FormFileMode: TFormFileMode read FFormFileMode write FFormFileMode; 29 | end; 30 | 31 | TInputForm = record 32 | private 33 | FForm: TFormNameAndFile; 34 | FTitle: string; 35 | public 36 | property Form: TFormNameAndFile read FForm write FForm; 37 | property Title: string read FTitle write FTitle; 38 | end; 39 | 40 | TExportFormsDesignModel = class 41 | private 42 | FInputForms: TArray; 43 | FDirectory: string; 44 | FOutputForms: TArray; 45 | FShowInExplorer: boolean; 46 | public 47 | property InputForms: TArray read FInputForms write FInputForms; 48 | property OutputForms: TArray read FOutputForms write FOutputForms; 49 | property Directory: string read FDirectory write FDirectory; 50 | property ShowInExplorer: boolean read FShowInExplorer write FShowInExplorer; 51 | end; 52 | 53 | implementation 54 | 55 | { TOutputForm } 56 | 57 | constructor TOutputForm.Create(const AForm: TFormNameAndFile; 58 | const AGenerateInitialization: boolean; const ATitle: string; 59 | const AFormFileKind: TFormFileKind; const AFormFileMode: TFormFileMode); 60 | begin 61 | Form := AForm; 62 | GenerateInitialization := AGenerateInitialization; 63 | Title := ATitle; 64 | FormFileKind := AFormFileKind; 65 | FormFileMode := AFormFileMode; 66 | end; 67 | 68 | end. 69 | -------------------------------------------------------------------------------- /Source/Model/Design/PythonTools.Model.Design.Project.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Model.Design.Project; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | PythonTools.Common; 8 | 9 | type 10 | TExportProjectDesignModel = class 11 | private 12 | FApplicationId: TGUID; 13 | FApplicationName: string; 14 | FApplicationDirectory: string; 15 | FApplicationTitle: string; 16 | FApplicationForms: TFormNamesAndFiles; 17 | FApplicationMainForm: TFormNameAndFile; 18 | FFormFileKind: TFormFileKind; 19 | FFormFileMode: TFormFileMode; 20 | FShowInExplorer: boolean; 21 | public 22 | property ApplicationId: TGUID read FApplicationId write FApplicationId; 23 | property ApplicationName: string read FApplicationName write FApplicationName; 24 | property ApplicationTitle: string read FApplicationTitle write FApplicationTitle; 25 | property ApplicationForms: TFormNamesAndFiles read FApplicationForms write FApplicationForms; 26 | property ApplicationMainForm: TFormNameAndFile read FApplicationMainForm write FApplicationMainForm; 27 | property ApplicationDirectory: string read FApplicationDirectory write FApplicationDirectory; 28 | property FormFileKind: TFormFileKind read FFormFileKind write FFormFileKind; 29 | property FormFileMode: TFormFileMode read FFormFileMode write FFormFileMode; 30 | property ShowInExplorer: boolean read FShowInExplorer write FShowInExplorer; 31 | end; 32 | 33 | implementation 34 | 35 | { TExportProjectModel } 36 | 37 | end. 38 | -------------------------------------------------------------------------------- /Source/Model/Producer/PythonTools.Model.Producer.Application.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Model.Producer.Application; 2 | 3 | interface 4 | 5 | uses 6 | PythonTools.Common, 7 | PythonTools.Model.Producer; 8 | 9 | type 10 | TApplicationProducerModel = class(TAbastractProducerModel) 11 | private 12 | FTitle: string; 13 | FMainForm: string; 14 | FImportedForms: TFormNamesAndFiles; 15 | function GetApplicationFile: TApplicationFile; 16 | protected 17 | function GetPythonFileName: string; override; 18 | public 19 | /// 20 | /// The application file name. 21 | /// 22 | property ApplicationFile: TApplicationFile read GetApplicationFile; 23 | /// 24 | /// The GUI application main form 25 | /// 26 | property MainForm: string read FMainForm write FMainForm; 27 | /// 28 | /// The application title 29 | /// 30 | property Title: string read FTitle write FTitle; 31 | /// 32 | /// Forms included in the import section 33 | /// 34 | property ImportedForms: TFormNamesAndFiles read FImportedForms write FImportedForms; 35 | end; 36 | 37 | implementation 38 | 39 | uses 40 | System.IOUtils; 41 | 42 | { TApplicationProducerModel } 43 | 44 | function TApplicationProducerModel.GetApplicationFile: TApplicationFile; 45 | begin 46 | Result := TApplicationFile(FileName); 47 | end; 48 | 49 | function TApplicationProducerModel.GetPythonFileName: string; 50 | begin 51 | Result := TPath.Combine(Directory, ApplicationFile.AsPython()) 52 | end; 53 | 54 | end. 55 | -------------------------------------------------------------------------------- /Source/Model/Producer/PythonTools.Model.Producer.Form.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Model.Producer.Form; 2 | 3 | interface 4 | 5 | uses 6 | System.Rtti, 7 | System.Classes, 8 | PythonTools.Common, 9 | PythonTools.Model.Producer; 10 | 11 | type 12 | TBaseFormProducerModel = class(TAbastractProducerModel) 13 | private type 14 | TModuleInitialization = class 15 | private 16 | FGenerateInitialization: boolean; 17 | FTitle: string; 18 | FMainForm: string; 19 | public 20 | /// 21 | /// Generate the Python module app GUI initialization section 22 | /// 23 | property GenerateInitialization: boolean read FGenerateInitialization write FGenerateInitialization; 24 | /// 25 | /// The GUI application title 26 | /// 27 | property Title: string read FTitle write FTitle; 28 | /// 29 | /// The GUI application Main Form 30 | /// 31 | property MainForm: string read FMainForm write FMainForm; 32 | end; 33 | private 34 | FFormName: string; 35 | FFormParentName: string; 36 | FExportedComponents: TExportedComponents; 37 | FModuleInitialization: TModuleInitialization; 38 | FExportedEvents: TExportedEvents; 39 | public 40 | constructor Create(); override; 41 | destructor Destroy(); override; 42 | /// 43 | /// The Form name: used to generate the Python class name 44 | /// 45 | property FormName: string read FFormName write FFormName; 46 | /// 47 | /// The Form parent class name: used to the Form inheritance chain 48 | /// 49 | property FormParentName: string read FFormParentName write FFormParentName; 50 | /// 51 | /// List of exported components 52 | /// 53 | property ExportedComponents: TExportedComponents read FExportedComponents write FExportedComponents; 54 | /// 55 | /// List of exported events 56 | /// 57 | property ExportedEvents: TExportedEvents read FExportedEvents write FExportedEvents; 58 | /// 59 | /// Generates the model initialization section 60 | /// 61 | property ModuleInitialization: TModuleInitialization read FModuleInitialization; 62 | end; 63 | 64 | TFormProducerModel = class(TBaseFormProducerModel); 65 | 66 | implementation 67 | 68 | { TBaseFormProducerModel } 69 | 70 | constructor TBaseFormProducerModel.Create; 71 | begin 72 | inherited; 73 | FModuleInitialization := TModuleInitialization.Create(); 74 | end; 75 | 76 | destructor TBaseFormProducerModel.Destroy; 77 | begin 78 | FModuleInitialization.Free(); 79 | inherited; 80 | end; 81 | 82 | end. 83 | -------------------------------------------------------------------------------- /Source/Model/Producer/PythonTools.Model.Producer.FormFile.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Model.Producer.FormFile; 2 | interface 3 | uses 4 | System.Classes, 5 | PythonTools.Common, 6 | PythonTools.Model.Producer; 7 | type 8 | TFormFileProducerModel = class(TAbastractProducerModel) 9 | private 10 | FForm: TComponent; 11 | FFormResource: TStream; 12 | FMode: TFormFileMode; 13 | FFrameworkType: string; 14 | function GetFormFile: TFormFile; 15 | procedure SetFormResource(const Value: TStream); 16 | protected 17 | function GetPythonFileName: string; override; 18 | public 19 | constructor Create(); overload; override; 20 | constructor Create(const AFrameworkType, ADirectory: string; const AFileName: TFileName); overload; 21 | destructor Destroy(); override; 22 | /// 23 | /// The .dfm/.fmx file name. 24 | /// 25 | property FormFile: TFormFile read GetFormFile; 26 | /// 27 | /// The exported form 28 | /// 29 | property Form: TComponent read FForm write FForm; 30 | /// 31 | /// The .dfm/.fmx text stream. 32 | /// 33 | property FormResource: TStream read FFormResource write SetFormResource; 34 | /// 35 | /// Delphi and Python can share the same .dfm/.fmx in compatible mode. 36 | /// 37 | property Mode: TFormFileMode read FMode write FMode; 38 | /// 39 | /// Define if we're going to use .dfm or .fmx. 40 | /// 41 | property FrameworkType: string read FFrameworkType write FFrameworkType; 42 | end; 43 | implementation 44 | uses 45 | System.IOUtils; 46 | { TFormFileProducerModel } 47 | constructor TFormFileProducerModel.Create; 48 | begin 49 | inherited; 50 | FFormResource := TMemoryStream.Create(); 51 | FMode := TFormFileMode.ffmCompatible; 52 | end; 53 | constructor TFormFileProducerModel.Create(const AFrameworkType, 54 | ADirectory: string; const AFileName: TFileName); 55 | begin 56 | inherited Create(ADirectory, AFileName); 57 | FFrameworkType := AFrameworkType; 58 | end; 59 | 60 | destructor TFormFileProducerModel.Destroy; 61 | begin 62 | FFormResource.Free(); 63 | inherited; 64 | end; 65 | function TFormFileProducerModel.GetPythonFileName: string; 66 | begin 67 | if FFrameworkType = 'VCL' then 68 | Result := TPath.Combine(Directory, FormFile.AsDfm(FMode)) 69 | else if FFrameworkType = 'FMX' then 70 | Result := TPath.Combine(Directory, FormFile.AsFmx(FMode)) 71 | else 72 | Result := inherited; 73 | end; 74 | function TFormFileProducerModel.GetFormFile: TFormFile; 75 | begin 76 | Result := TFormFile(FileName); 77 | end; 78 | 79 | procedure TFormFileProducerModel.SetFormResource(const Value: TStream); 80 | begin 81 | FFormResource.Size := 0; 82 | FFormResource.Position := 0; 83 | FFormResource.CopyFrom(Value, Value.Size); 84 | end; 85 | end. 86 | -------------------------------------------------------------------------------- /Source/Model/Producer/PythonTools.Model.Producer.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Model.Producer; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | System.SysUtils, 8 | PythonTools.Common; 9 | 10 | type 11 | TAbastractProducerModel = class 12 | private 13 | FDirectory: string; 14 | FFileName: TFileName; 15 | FOwned: boolean; 16 | FStream: TStream; 17 | function GetStream: TStream; 18 | procedure SetFileName(const Value: TFileName); 19 | protected 20 | function GetPythonFileName: string; virtual; 21 | public 22 | constructor Create(); overload; virtual; 23 | constructor Create(const AStream: TStream; const AOwned: boolean = true); overload; 24 | constructor Create(const ADirectory: string; const AFileName: TFileName); overload; 25 | destructor Destroy(); override; 26 | 27 | /// 28 | /// The directory where the generated files will be saved 29 | /// 30 | property Directory: string read FDirectory write FDirectory; 31 | /// 32 | /// The Delphi file name: used to generate the Python (.py) file name. 33 | /// 34 | property FileName: TFileName read FFileName write SetFileName; 35 | /// 36 | /// The final Python file name. 37 | /// 38 | property PythonFileName: string read GetPythonFileName; 39 | /// 40 | /// Producers will use this stream to save Python code. 41 | /// 42 | property Stream: TStream read GetStream; 43 | end; 44 | 45 | implementation 46 | 47 | uses 48 | System.IOUtils; 49 | 50 | { TAbastractProducerModel } 51 | 52 | constructor TAbastractProducerModel.Create; 53 | begin 54 | inherited; 55 | end; 56 | 57 | constructor TAbastractProducerModel.Create(const AStream: TStream; 58 | const AOwned: boolean); 59 | begin 60 | Create(); 61 | FStream := AStream; 62 | FOwned := AOwned; 63 | end; 64 | 65 | constructor TAbastractProducerModel.Create(const ADirectory: string; 66 | const AFileName: TFileName); 67 | begin 68 | Create(); 69 | FDirectory := ADirectory; 70 | SetFileName(AFileName); 71 | end; 72 | 73 | destructor TAbastractProducerModel.Destroy; 74 | begin 75 | if FOwned then 76 | FStream.Free(); 77 | inherited; 78 | end; 79 | 80 | function TAbastractProducerModel.GetPythonFileName: string; 81 | begin 82 | Result := TPath.Combine(FDirectory, FFileName.AsPython()); 83 | end; 84 | 85 | function TAbastractProducerModel.GetStream: TStream; 86 | begin 87 | if not Assigned(FStream) then begin 88 | FStream := TFileStream.Create(GetPythonFileName(), fmCreate or fmOpenWrite or fmShareDenyWrite); 89 | FOwned := true; 90 | end; 91 | 92 | Result := FStream; 93 | end; 94 | 95 | procedure TAbastractProducerModel.SetFileName(const Value: TFileName); 96 | begin 97 | FFileName := TFileName( 98 | ExtractFileName(Value) 99 | .Replace('.pas', '', []) 100 | .Replace('.dfm', '', []) 101 | .Replace('.fmx', '', []) 102 | .Replace('.dpr', '', []) 103 | .Replace('.dproj', '', []) 104 | ); 105 | end; 106 | 107 | end. 108 | -------------------------------------------------------------------------------- /Source/Producer/PythonTools.Producer.AbstractForm.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Producer.AbstractForm; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, System.SysUtils, System.Generics.Collections, 7 | PythonTools.Common, 8 | PythonTools.Producer, 9 | PythonTools.Model.Producer.Application, 10 | PythonTools.Model.Producer.Form, 11 | PythonTools.Model.Producer.FormFile; 12 | 13 | type 14 | TAbstractFormProducer = class abstract(TInterfacedObject) 15 | protected 16 | function GetPythonModuleName(): string; virtual; abstract; 17 | function GetPythonFormFileExtension( 18 | const AMode: TFormFileMode): string; virtual; abstract; 19 | function GetAppInitializationSection(): string; virtual; abstract; 20 | //File generators 21 | procedure GeneratePyApplicationFile(const AStream: TStream; 22 | const AModel: TApplicationProducerModel); 23 | procedure GeneratePyFormFile(const AStream: TStream; 24 | const AFormModel: TFormProducerModel; 25 | const AFormFileModel: TFormFileProducerModel); 26 | procedure GeneratePyFormFileBin(const AStream: TStream; 27 | const AModel: TFormFileProducerModel); 28 | procedure GeneratePyFormFileTxt(const AStream: TStream; 29 | const AModel: TFormFileProducerModel); 30 | public 31 | 32 | end; 33 | 34 | implementation 35 | 36 | uses 37 | TypInfo, System.StrUtils; 38 | 39 | const 40 | PY_APP_IMPORTED_FORMS = 41 | 'from @MODULE_NAME import *' 42 | + sLineBreak 43 | + '@IMPORTED_FORMS'; 44 | 45 | PY_APP_IMPORT = 46 | 'from @FILE import @FORM'; 47 | 48 | PY_MODULE_IMPORT = 49 | 'import os' 50 | + sLineBreak 51 | + 'from @MODULE_NAME import *'; 52 | 53 | PY_MODULE_CLASS = 54 | 'class @CLASSNAME(@CLASSPARENT):' 55 | + sLineBreak 56 | + sLineBreak 57 | + sIdentation1 58 | + 'def __init__(self, owner):'; 59 | 60 | PY_MODULE_PROPS = 61 | sIdentation2 62 | + '@PROPERTIES'; 63 | 64 | PY_MODULE_LOAD_PROPS = 65 | sIdentation2 66 | + 'self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "@FILE@FORMFILEEXT"))'; 67 | 68 | PY_MODULE_EVTS = 69 | sIdentation1 70 | + '@EVENTS'; 71 | 72 | { TAbstractFormProducer } 73 | 74 | procedure TAbstractFormProducer.GeneratePyApplicationFile( 75 | const AStream: TStream; const AModel: TApplicationProducerModel); 76 | var 77 | LImportedForms: string; 78 | LFormInfo: TFormNameAndFile; 79 | LStrFile: string; 80 | LBytes: TBytes; 81 | begin 82 | LImportedForms := String.Empty; 83 | for LFormInfo in AModel.ImportedForms do begin 84 | if not LImportedForms.IsEmpty() then 85 | LImportedForms := LImportedForms + sLineBreak; 86 | 87 | LImportedForms := LImportedForms 88 | + PY_APP_IMPORT 89 | .Replace('@FILE', LFormInfo.FileName) 90 | .Replace('@FORM', LFormInfo.FormName); 91 | end; 92 | 93 | LStrFile := String.Empty; 94 | if not LImportedForms.IsEmpty() then 95 | LStrFile := 96 | PY_APP_IMPORTED_FORMS 97 | .Replace('@MODULE_NAME', GetPythonModuleName()) 98 | .Replace('@IMPORTED_FORMS', LImportedForms) 99 | + sLineBreak 100 | + sLineBreak; 101 | 102 | LStrFile := LStrFile 103 | + GetAppInitializationSection() 104 | .Replace('@APP_TITLE', AModel.Title.QuotedString()) 105 | .Replace('@CLASSNAME', AModel.MainForm); 106 | 107 | LBytes := TEncoding.UTF8.GetBytes(LStrFile); 108 | AStream.WriteData(LBytes, Length(LBytes)); 109 | end; 110 | 111 | procedure TAbstractFormProducer.GeneratePyFormFile(const AStream: TStream; 112 | const AFormModel: TFormProducerModel; 113 | const AFormFileModel: TFormFileProducerModel); 114 | var 115 | LProps: string; 116 | LComp: TExportedComponent; 117 | LEvts: string; 118 | LEvt: TExportedEvent; 119 | LParam: string; 120 | LStrFile: string; 121 | LBytes: TBytes; 122 | begin 123 | LProps := String.Empty; 124 | for LComp in AFormModel.ExportedComponents do begin 125 | if not LProps.IsEmpty() then 126 | LProps := LProps 127 | + sLineBreak 128 | + sIdentation2; 129 | LProps := LProps + 'self.' + LComp.ComponentName + ' = None'; 130 | end; 131 | 132 | LEvts := String.Empty; 133 | for LEvt in AFormModel.ExportedEvents do begin 134 | if not LEvts.IsEmpty then 135 | LEvts := LEvts 136 | + sLineBreak 137 | + sLineBreak 138 | + sIdentation1; 139 | LEvts := LEvts + 'def ' + LEvt.MethodName + '(self'; 140 | for LParam in LEvt.MethodParams do begin 141 | LEvts := LEvts + ', ' + LParam 142 | end; 143 | LEvts := LEvts + '):' 144 | + sLineBreak 145 | + sIdentation2 146 | + 'pass'; 147 | end; 148 | 149 | LStrFile := 150 | PY_MODULE_IMPORT 151 | .Replace('@MODULE_NAME', GetPythonModuleName()) 152 | + sLineBreak 153 | + sLineBreak 154 | + PY_MODULE_CLASS 155 | .Replace('@CLASSNAME', AFormModel.FormName) 156 | .Replace('@CLASSPARENT', AFormModel.FormParentName); 157 | 158 | if not LProps.IsEmpty() then 159 | LStrFile := LStrFile 160 | + sLineBreak 161 | + PY_MODULE_PROPS 162 | .Replace('@PROPERTIES', LProps); 163 | 164 | LStrFile := LStrFile 165 | + sLineBreak 166 | + PY_MODULE_LOAD_PROPS 167 | .Replace('@FILE', AFormModel.FileName) 168 | .Replace('@FORMFILEEXT', GetPythonFormFileExtension(AFormFileModel.Mode)); 169 | 170 | if not LEvts.IsEmpty() then 171 | LStrFile := LStrFile 172 | + sLineBreak 173 | + sLineBreak 174 | + PY_MODULE_EVTS 175 | .Replace('@EVENTS', LEvts); 176 | 177 | if AFormModel.ModuleInitialization.GenerateInitialization then 178 | LStrFile := LStrFile 179 | + sLineBreak 180 | + sLineBreak 181 | + GetAppInitializationSection() 182 | .Replace('@APP_TITLE', AFormModel.ModuleInitialization.Title.QuotedString()) 183 | .Replace('@CLASSNAME', AFormModel.ModuleInitialization.MainForm); 184 | 185 | LBytes := TEncoding.UTF8.GetBytes(LStrFile); 186 | AStream.WriteData(LBytes, Length(LBytes)); 187 | end; 188 | 189 | procedure TAbstractFormProducer.GeneratePyFormFileBin(const AStream: TStream; 190 | const AModel: TFormFileProducerModel); 191 | begin 192 | AStream.WriteComponent(AModel.Form); 193 | end; 194 | 195 | procedure TAbstractFormProducer.GeneratePyFormFileTxt(const AStream: TStream; 196 | const AModel: TFormFileProducerModel); 197 | begin 198 | AStream.CopyFrom(AModel.FormResource, AModel.FormResource.Size); 199 | end; 200 | 201 | end. 202 | -------------------------------------------------------------------------------- /Source/Producer/PythonTools.Producer.FMXForm.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Producer.FMXForm; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | PythonTools.Common, 8 | PythonTools.Producer, 9 | PythonTools.Producer.AbstractForm, 10 | PythonTools.Model.Producer.Application, 11 | PythonTools.Model.Producer.Form, 12 | PythonTools.Model.Producer.FormFile; 13 | 14 | type 15 | TFMXFormProducer = class(TAbstractFormProducer, IPythonCodeProducer) 16 | protected 17 | function GetPythonModuleName(): string; override; 18 | function GetPythonFormFileExtension(const AMode: TFormFileMode): string; override; 19 | function GetAppInitializationSection(): string; override; 20 | public 21 | function IsValidFormInheritance(const AClass: TClass): boolean; 22 | 23 | procedure SavePyApplicationFile( 24 | const AModel: TApplicationProducerModel; 25 | const AStream: TStream); 26 | procedure SavePyForm( 27 | const AFormModel: TFormProducerModel; 28 | const AFormFileModel: TFormFileProducerModel; 29 | const AStream: TStream); 30 | procedure SavePyFormFileBin( 31 | const AModel: TFormFileProducerModel; 32 | const AStream: TStream); 33 | procedure SavePyFormFileTxt( 34 | const AModel: TFormFileProducerModel; 35 | const AStream: TStream); 36 | end; 37 | 38 | implementation 39 | 40 | uses 41 | System.SysUtils, System.IOUtils, FMX.Forms, 42 | PythonTools.Exceptions; 43 | 44 | const 45 | DELPHI_FMX_MODULE_NAME = 'delphifmx'; 46 | 47 | PY_MODULE_APP_INITIALIZATION = 48 | 'def main():' 49 | + sLineBreak 50 | + sIdentation1 51 | + 'Application.Initialize()' 52 | + sLineBreak 53 | + sIdentation1 54 | + 'Application.Title = @APP_TITLE' 55 | + sLineBreak 56 | + sIdentation1 57 | + 'Application.MainForm = @CLASSNAME(Application)' 58 | + sLineBreak 59 | + sIdentation1 60 | + 'Application.MainForm.Show()' 61 | + sLineBreak 62 | + sIdentation1 63 | + 'Application.Run()' 64 | + sLineBreak 65 | + sIdentation1 66 | + 'Application.MainForm.Destroy()' 67 | + sLineBreak 68 | + sLineBreak 69 | + 'if __name__ == ''__main__'':' 70 | + sLineBreak 71 | + sIdentation1 72 | + 'main()' 73 | + sLineBreak; 74 | 75 | { TFMXFormProducer } 76 | 77 | function TFMXFormProducer.GetPythonFormFileExtension( 78 | const AMode: TFormFileMode): string; 79 | begin 80 | Result := TFormFile('').AsFmx(AMode); 81 | end; 82 | 83 | function TFMXFormProducer.GetPythonModuleName: string; 84 | begin 85 | Result := DELPHI_FMX_MODULE_NAME; 86 | end; 87 | 88 | function TFMXFormProducer.GetAppInitializationSection: string; 89 | begin 90 | Result := PY_MODULE_APP_INITIALIZATION; 91 | end; 92 | 93 | function TFMXFormProducer.IsValidFormInheritance(const AClass: TClass): boolean; 94 | begin 95 | Result := AClass = TForm; 96 | end; 97 | 98 | procedure TFMXFormProducer.SavePyApplicationFile( 99 | const AModel: TApplicationProducerModel; const AStream: TStream); 100 | begin 101 | GeneratePyApplicationFile(AStream, AModel); 102 | end; 103 | 104 | procedure TFMXFormProducer.SavePyForm(const AFormModel: TFormProducerModel; 105 | const AFormFileModel: TFormFileProducerModel; const AStream: TStream); 106 | begin 107 | GeneratePyFormFile(AStream, AFormModel, AFormFileModel); 108 | end; 109 | 110 | procedure TFMXFormProducer.SavePyFormFileBin( 111 | const AModel: TFormFileProducerModel; const AStream: TStream); 112 | begin 113 | GeneratePyFormFileBin(AStream, AModel); 114 | end; 115 | 116 | procedure TFMXFormProducer.SavePyFormFileTxt( 117 | const AModel: TFormFileProducerModel; const AStream: TStream); 118 | begin 119 | GeneratePyFormFileTxt(AStream, AModel); 120 | end; 121 | 122 | end. 123 | -------------------------------------------------------------------------------- /Source/Producer/PythonTools.Producer.SimpleFactory.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Producer.SimpleFactory; 2 | 3 | interface 4 | 5 | uses 6 | PythonTools.Producer; 7 | 8 | type 9 | TProducerSimpleFactory = class 10 | public 11 | class function CreateProducer(const AFrameworkType: string): IPythonCodeProducer; 12 | end; 13 | 14 | implementation 15 | 16 | uses 17 | System.SysUtils, 18 | PythonTools.Exceptions, 19 | PythonTools.Producer.FMXForm, 20 | PythonTools.Producer.VCLForm; 21 | 22 | { TProducerSimpleFactory } 23 | 24 | class function TProducerSimpleFactory.CreateProducer( 25 | const AFrameworkType: string): IPythonCodeProducer; 26 | begin 27 | if CompareText(AFrameworkType, 'FMX') = 0 then 28 | Result := TFMXFormProducer.Create() 29 | else if CompareText(AFrameworkType, 'VCL') = 0 then 30 | Result := TVCLFormProducer.Create() 31 | else 32 | raise EProducerNotFound.CreateFmt('Producer not found for framework type %s', [ 33 | AFrameworkType]); 34 | end; 35 | 36 | end. 37 | -------------------------------------------------------------------------------- /Source/Producer/PythonTools.Producer.VCLForm.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Producer.VCLForm; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | PythonTools.Common, 8 | PythonTools.Producer, 9 | PythonTools.Producer.AbstractForm, 10 | PythonTools.Model.Producer.Application, 11 | PythonTools.Model.Producer.Form, 12 | PythonTools.Model.Producer.FormFile; 13 | 14 | type 15 | TVCLFormProducer = class(TAbstractFormProducer, IPythonCodeProducer) 16 | protected 17 | function GetPythonModuleName(): string; override; 18 | function GetPythonFormFileExtension(const AMode: TFormFileMode): string; override; 19 | function GetAppInitializationSection(): string; override; 20 | public 21 | function IsValidFormInheritance(const AClass: TClass): boolean; 22 | 23 | procedure SavePyApplicationFile( 24 | const AModel: TApplicationProducerModel; 25 | const AStream: TStream); 26 | procedure SavePyForm( 27 | const AFormModel: TFormProducerModel; 28 | const AFormFileModel: TFormFileProducerModel; 29 | const AStream: TStream); 30 | procedure SavePyFormFileBin( 31 | const AModel: TFormFileProducerModel; 32 | const AStream: TStream); 33 | procedure SavePyFormFileTxt( 34 | const AModel: TFormFileProducerModel; 35 | const AStream: TStream); 36 | end; 37 | 38 | implementation 39 | 40 | uses 41 | System.SysUtils, System.IOUtils, Vcl.Forms, 42 | PythonTools.Exceptions; 43 | 44 | const 45 | DELPHI_VCL_MODULE_NAME = 'delphivcl'; 46 | 47 | PY_MODULE_APP_INITIALIZATION = 48 | 'def main():' 49 | + sLineBreak 50 | + sIdentation1 51 | + 'Application.Initialize()' 52 | + sLineBreak 53 | + sIdentation1 54 | + 'Application.Title = @APP_TITLE' 55 | + sLineBreak 56 | + sIdentation1 57 | + 'MainForm = @CLASSNAME(Application)' 58 | + sLineBreak 59 | + sIdentation1 60 | + 'MainForm.Show()' 61 | + sLineBreak 62 | + sIdentation1 63 | + 'FreeConsole()' 64 | + sLineBreak 65 | + sIdentation1 66 | + 'Application.Run()' 67 | + sLineBreak 68 | + sLineBreak 69 | + 'if __name__ == ''__main__'':' 70 | + sLineBreak 71 | + sIdentation1 72 | + 'main()' 73 | + sLineBreak; 74 | 75 | { TVCLFormProducer } 76 | 77 | function TVCLFormProducer.GetPythonFormFileExtension( 78 | const AMode: TFormFileMode): string; 79 | begin 80 | Result := TFormFile('').AsDfm(AMode); 81 | end; 82 | 83 | function TVCLFormProducer.GetPythonModuleName: string; 84 | begin 85 | Result := DELPHI_VCL_MODULE_NAME; 86 | end; 87 | 88 | function TVCLFormProducer.GetAppInitializationSection: string; 89 | begin 90 | Result := PY_MODULE_APP_INITIALIZATION; 91 | end; 92 | 93 | function TVCLFormProducer.IsValidFormInheritance(const AClass: TClass): boolean; 94 | begin 95 | Result := AClass = TForm; 96 | end; 97 | 98 | procedure TVCLFormProducer.SavePyApplicationFile( 99 | const AModel: TApplicationProducerModel; const AStream: TStream); 100 | begin 101 | GeneratePyApplicationFile(AStream, AModel); 102 | end; 103 | 104 | procedure TVCLFormProducer.SavePyForm(const AFormModel: TFormProducerModel; 105 | const AFormFileModel: TFormFileProducerModel; const AStream: TStream); 106 | begin 107 | GeneratePyFormFile(AStream, AFormModel, AFormFileModel); 108 | end; 109 | 110 | procedure TVCLFormProducer.SavePyFormFileBin( 111 | const AModel: TFormFileProducerModel; const AStream: TStream); 112 | begin 113 | GeneratePyFormFileBin(AStream, AModel); 114 | end; 115 | 116 | procedure TVCLFormProducer.SavePyFormFileTxt( 117 | const AModel: TFormFileProducerModel; const AStream: TStream); 118 | begin 119 | GeneratePyFormFileTxt(AStream, AModel); 120 | end; 121 | 122 | end. 123 | -------------------------------------------------------------------------------- /Source/Producer/PythonTools.Producer.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Producer; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, System.Generics.Collections, 7 | PythonTools.Common, 8 | PythonTools.Model.Producer.Application, 9 | PythonTools.Model.Producer.Form, 10 | PythonTools.Model.Producer.FormFile; 11 | 12 | type 13 | IPythonCodeProducer = interface 14 | ['{D3A5C0FE-EAF4-4301-9DA9-E867B3081E21}'] 15 | function IsValidFormInheritance(const AClass: TClass): boolean; 16 | procedure SavePyApplicationFile( 17 | const AModel: TApplicationProducerModel; 18 | const AStream: TStream); 19 | procedure SavePyForm( 20 | const AFormModel: TFormProducerModel; 21 | const AFormFileModel: TFormFileProducerModel; 22 | const AStream: TStream); 23 | procedure SavePyFormFileBin( 24 | const AModel: TFormFileProducerModel; 25 | const AStream: TStream); 26 | procedure SavePyFormFileTxt( 27 | const AModel: TFormFileProducerModel; 28 | const AStream: TStream); 29 | end; 30 | 31 | const 32 | //Using 4 spaces identation 33 | sIdentation1 = ' '; 34 | sIdentation2 = sIdentation1 + sIdentation1; 35 | 36 | implementation 37 | 38 | end. 39 | -------------------------------------------------------------------------------- /Source/PythonTools.Common.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Common; 2 | 3 | interface 4 | 5 | uses 6 | System.Generics.Collections, System.SysUtils; 7 | 8 | type 9 | TFormFileKind = (ffkText, ffkBinary); 10 | TFormFileMode = (ffmDelphi, ffmPython, ffmCompatible); 11 | 12 | TFormNameAndFile = record 13 | public 14 | FormName: string; 15 | FileName: string; 16 | public 17 | constructor Create(const AFormName, AFileName: string); 18 | function CombineFileAndFormName(): string; 19 | end; 20 | 21 | TFormNamesAndFiles = TArray; 22 | TFormNameAndFileList = TList; 23 | 24 | TExportedComponent = record 25 | public 26 | ComponentName: string; 27 | public 28 | constructor Create(const AComponentName: string); 29 | end; 30 | 31 | TExportedComponents = TArray; 32 | TExportedComponentList = TList; 33 | 34 | TExportedEvent = record 35 | public 36 | MethodName: string; 37 | MethodParams: TArray; 38 | public 39 | constructor Create(const AMethodName: string; const AMethodParams: TArray); 40 | end; 41 | 42 | TExportedEvents = TArray; 43 | TExportedEventList = TList; 44 | TApplicationFile = System.SysUtils.TFileName; 45 | TFileName = System.SysUtils.TFileName; 46 | TFormFile = type string; 47 | TFormFilePath = TFormFile; 48 | 49 | TApplicationFileHelper = record helper for TApplicationFile 50 | public 51 | function AsDelphi(): string; 52 | function AsPython(): string; 53 | end; 54 | 55 | TFileNameHelper = record helper for TFileName 56 | public 57 | function AsDelphi(): string; 58 | function AsPython(): string; 59 | end; 60 | 61 | TFormFileHelper = record helper for TFormFile 62 | public 63 | function AsDelphiDfm(): string; 64 | function AsDelphiFmx(): string; 65 | function AsPythonDfm(): string; 66 | function AsPythonFmx(): string; 67 | function AsDfm(const AMode: TFormFileMode): string; 68 | function AsFmx(const AMode: TFormFileMode): string; 69 | end; 70 | 71 | TFormFileKindHelper = record helper for TFormFileKind 72 | public 73 | function ToString(): string; 74 | class function FromString(const AValue: string): TFormFileKind; static; 75 | end; 76 | 77 | implementation 78 | 79 | { TFormNameAndFile } 80 | 81 | function TFormNameAndFile.CombineFileAndFormName: string; 82 | begin 83 | if (FileName = String.Empty) and (FormName = String.Empty) then 84 | Result := String.Empty 85 | else 86 | Result := FileName + '.' + FormName; 87 | end; 88 | 89 | constructor TFormNameAndFile.Create(const AFormName, AFileName: string); 90 | begin 91 | FormName := AFormName; 92 | FileName := AFileName; 93 | end; 94 | 95 | { TExportedComponent } 96 | 97 | constructor TExportedComponent.Create(const AComponentName: string); 98 | begin 99 | ComponentName := AComponentName; 100 | end; 101 | 102 | { TExportedEvent } 103 | 104 | constructor TExportedEvent.Create(const AMethodName: string; 105 | const AMethodParams: TArray); 106 | begin 107 | MethodName := AMethodName; 108 | MethodParams := AMethodParams; 109 | end; 110 | 111 | { TApplicationFileHelper } 112 | 113 | function TApplicationFileHelper.AsDelphi: string; 114 | begin 115 | Result := Self + '.dpr' 116 | end; 117 | 118 | function TApplicationFileHelper.AsPython: string; 119 | begin 120 | Result := Self + '.py' 121 | end; 122 | 123 | { TFileNameHelper } 124 | 125 | function TFileNameHelper.AsDelphi: string; 126 | begin 127 | Result := Self + '.pas'; 128 | end; 129 | 130 | function TFileNameHelper.AsPython: string; 131 | begin 132 | Result := Self + '.py'; 133 | end; 134 | 135 | { TFormFileHelper } 136 | 137 | function TFormFileHelper.AsDelphiDfm: string; 138 | begin 139 | Result := Self + '.dfm'; 140 | end; 141 | 142 | function TFormFileHelper.AsDelphiFmx: string; 143 | begin 144 | Result := Self + '.fmx'; 145 | end; 146 | 147 | function TFormFileHelper.AsPythonDfm: string; 148 | begin 149 | Result := Self + '.pydfm'; 150 | end; 151 | 152 | function TFormFileHelper.AsPythonFmx: string; 153 | begin 154 | Result := Self + '.pyfmx'; 155 | end; 156 | 157 | function TFormFileHelper.AsDfm(const AMode: TFormFileMode): string; 158 | begin 159 | case AMode of 160 | ffmCompatible, 161 | ffmDelphi: 162 | Result := AsDelphiDfm(); 163 | ffmPython: 164 | Result := AsPythonDfm(); 165 | else 166 | Result := String.Empty; 167 | end; 168 | end; 169 | 170 | function TFormFileHelper.AsFmx(const AMode: TFormFileMode): string; 171 | begin 172 | case AMode of 173 | ffmCompatible, 174 | ffmDelphi: 175 | Result := AsDelphiFmx(); 176 | ffmPython: 177 | Result := AsPythonFmx(); 178 | else 179 | Result := String.Empty; 180 | end; 181 | end; 182 | 183 | { TFormFileKindHelper } 184 | 185 | class function TFormFileKindHelper.FromString( 186 | const AValue: string): TFormFileKind; 187 | begin 188 | if AValue = 'Text' then 189 | Result := ffkText 190 | else if AValue = 'Binary' then 191 | Result := ffkBinary 192 | else 193 | raise ENotImplemented.Create('Form file kind not found.'); 194 | end; 195 | 196 | function TFormFileKindHelper.ToString: string; 197 | begin 198 | case Self of 199 | ffkText: 200 | Result := 'Text'; 201 | ffkBinary: 202 | Result := 'Binary'; 203 | else 204 | raise ENotImplemented.Create('Form file kind not found.'); 205 | end; 206 | end; 207 | 208 | end. 209 | -------------------------------------------------------------------------------- /Source/PythonTools.Exceptions.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Exceptions; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils; 7 | 8 | type 9 | EFormInheritanceNotSupported = class(Exception) 10 | end; 11 | 12 | EUnableToObtainFormDesigner = class(Exception) 13 | end; 14 | 15 | EInvalidFormFileKind = class(Exception) 16 | end; 17 | 18 | EUnknownFrameworkType = class(Exception) 19 | end; 20 | 21 | EProducerNotFound = class(Exception) 22 | end; 23 | 24 | implementation 25 | 26 | end. 27 | -------------------------------------------------------------------------------- /Source/PythonTools.IOTAUtils.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.IOTAUtils; 2 | 3 | interface 4 | 5 | uses 6 | DesignIntf, ToolsAPI, 7 | System.Classes, System.Generics.Collections, System.SysUtils, System.Rtti, 8 | PythonTools.Common; 9 | 10 | type 11 | TIOTAFormInfo = record 12 | FormName: string; 13 | FileName: string; 14 | Caption: string; 15 | FrameworkType: string; 16 | Module: IOTAModule; 17 | Editor: IOTAFormEditor; 18 | Designer: IDesigner; 19 | end; 20 | 21 | TFormClassName = string; 22 | TFormGlobalVarName = string; 23 | TDprEntry = TPair; 24 | TDprEntries = TArray; 25 | 26 | TIOTAUtils = class 27 | private 28 | class function ModuleIsPas(const AModule: IOTAModule): boolean; 29 | class function ModuleIsCpp(const AModule: IOTAModule): boolean; 30 | class function ModuleIsForm(const AModule: IOTAModule): boolean; 31 | class function ModuleIsExportable(const AModule: IOTAModule): boolean; 32 | class procedure EnumComps(const AFormEditor: IOTAFormEditor; const ACallback: TProc); 33 | class function GetFormCaption(const AComponent: TComponent): string; 34 | class function ScanDprEntries(const AProject: IOTAProject): TDprEntries; 35 | public 36 | class function FindComponents(const AFormEditor: IOTAFormEditor): TExportedComponents; 37 | class function FindEvents(const AFormEditor: IOTAFormEditor; const ADesigner: IDesigner): TExportedEvents; 38 | class function HasForms(): boolean; 39 | class procedure EnumForms(const AProc: TProc); overload; 40 | class procedure EnumForms(const AProject: IOTAProject; const AProc: TProc); overload; 41 | class function FindForm(const AFormName: string; out AFormInfo: TIOTAFormInfo): boolean; 42 | class function FindDelphiProjectEditor(const AProject: IOTAProject): IOTAEditor; 43 | class function GuessMainForm(const AProject: IOTAProject): IOTAModule; 44 | class function GetEditorContentFromEditor(const AEditor: IOTAEditor): IOTAEditorContent; 45 | class function GetFormEditorFromModule(const AModule: IOTAModule): IOTAFormEditor; 46 | class function GetFrameworkTypeFromDesigner(const ADesigner: IDesigner): string; 47 | end; 48 | 49 | implementation 50 | 51 | uses 52 | System.TypInfo, 53 | System.Generics.Defaults, 54 | System.RegularExpressions, 55 | Vcl.AxCtrls, 56 | Vcl.Forms, 57 | Fmx.Forms, 58 | PythonTools.Exceptions; 59 | 60 | { TIOTAUtils } 61 | 62 | class procedure TIOTAUtils.EnumForms(const AProject: IOTAProject; 63 | const AProc: TProc); 64 | var 65 | LFormPredicate: TPredicate; 66 | I: integer; 67 | LModuleInfo: IOTAModuleInfo; 68 | LResult: TIOTAFormInfo; 69 | begin 70 | LFormPredicate := function(AModuleInfo: IOTAModuleInfo): boolean begin 71 | Result := (AModuleInfo.ModuleType = omtForm) 72 | and not AModuleInfo.FormName.Trim().IsEmpty(); 73 | end; 74 | for I := 0 to AProject.GetModuleCount() - 1 do begin 75 | LModuleInfo := AProject.GetModule(I); 76 | if not LFormPredicate(LModuleInfo) then 77 | Continue; 78 | LResult.Module := LModuleInfo.OpenModule(); 79 | LResult.Editor := TIOTAUtils.GetFormEditorFromModule(LResult.Module); 80 | LResult.Designer := (LResult.Editor as INTAFormEditor).FormDesigner; 81 | LResult.FileName := LModuleInfo.FileName; 82 | LResult.FormName := LModuleInfo.FormName; 83 | LResult.Caption := GetFormCaption(LResult.Designer.Root); 84 | LResult.FrameworkType := GetFrameworkTypeFromDesigner(LResult.Designer); 85 | AProc(LResult); 86 | end; 87 | end; 88 | 89 | class procedure TIOTAUtils.EnumForms(const AProc: TProc); 90 | var 91 | I: integer; 92 | LModuleServices: IOTAModuleServices; 93 | LProject: IOTAProject; 94 | LModule: IOTAModule; 95 | LEditor: IOTAFormEditor; 96 | LDesigner: IDesigner; 97 | LResult: TIOTAFormInfo; 98 | begin 99 | LModuleServices := (BorlandIDEServices as IOTAModuleServices); 100 | //User has created a project and added files on it. 101 | if Assigned(LModuleServices.MainProjectGroup) then begin 102 | for I := 0 to LModuleServices.MainProjectGroup.ProjectCount - 1 do begin 103 | LProject := LModuleServices.MainProjectGroup.Projects[I]; 104 | EnumForms(LProject, AProc); 105 | end; 106 | end else 107 | //User has created files out of a project. 108 | for I := 0 to LModuleServices.ModuleCount - 1 do begin 109 | LModule := LModuleServices.Modules[I]; 110 | LEditor := GetFormEditorFromModule(LModule); 111 | if not ModuleIsExportable(LModule) then 112 | Continue; 113 | LDesigner := (LEditor as INTAFormEditor).FormDesigner; 114 | if not Assigned(LDesigner) then 115 | Continue; 116 | LResult.FileName := LModule.FileName; 117 | LResult.FormName := LDesigner.Root.Name; 118 | LResult.Caption := GetFormCaption(LDesigner.Root); 119 | LResult.FrameworkType := GetFrameworkTypeFromDesigner(LDesigner); 120 | LResult.Module := LModule; 121 | LResult.Editor := LEditor; 122 | LResult.Designer := LDesigner; 123 | AProc(LResult); 124 | end; 125 | end; 126 | 127 | class function TIOTAUtils.FindComponents(const AFormEditor: IOTAFormEditor): TExportedComponents; 128 | var 129 | LCompList: TExportedComponentList; 130 | begin 131 | LCompList := TExportedComponentList.Create(); 132 | try 133 | EnumComps(AFormEditor, procedure(AComponent: TComponent) begin 134 | LCompList.Add(TExportedComponent.Create(AComponent.Name)); 135 | end); 136 | Result := LCompList.ToArray(); 137 | finally 138 | LCompList.Free(); 139 | end; 140 | end; 141 | 142 | class function TIOTAUtils.FindDelphiProjectEditor( 143 | const AProject: IOTAProject): IOTAEditor; 144 | var 145 | I: Integer; 146 | begin 147 | for I := 0 to AProject.ModuleFileCount -1 do 148 | if AProject.ModuleFileEditors[I].FileName.EndsWith('.dpr') then 149 | Exit(AProject.ModuleFileEditors[I]); 150 | 151 | Result := nil; 152 | end; 153 | 154 | class function TIOTAUtils.FindEvents(const AFormEditor: IOTAFormEditor; const ADesigner: IDesigner): TExportedEvents; 155 | procedure ExtractPropertyEvents(const ARttiContext: TRttiContext; 156 | const AComponent: TComponent; const AEvents: TExportedEventList); 157 | var 158 | LRttiType: TRttiType; 159 | LRttiProp: TRttiProperty; 160 | LMethod: TValue; 161 | LMethodName: string; 162 | LRttiMethod: TRttiMethodType; 163 | LParamList: TList; 164 | LParam: TRttiParameter; 165 | LEvt: TExportedEvent; 166 | begin 167 | LRttiType := ARttiContext.GetType(AComponent.ClassInfo); 168 | for LRttiProp in LRttiType.GetProperties() do begin 169 | if not (LRttiProp.Visibility = TMemberVisibility.mvPublished) then 170 | Continue; 171 | if not (LRttiProp.PropertyType is TRttiMethodType) then 172 | Continue; 173 | LMethod := LRttiProp.GetValue(AComponent); 174 | if LMethod.IsEmpty then 175 | Continue; 176 | 177 | LMethodName := ADesigner.GetMethodName(PMethod(LMethod.GetReferenceToRawData)^); 178 | if not ADesigner.MethodExists(LMethodName) then 179 | Continue; 180 | 181 | LRttiMethod := LRttiProp.PropertyType as TRttiMethodType; 182 | LParamList := TList.Create(); 183 | try 184 | for LParam in LRttiMethod.GetParameters() do begin 185 | LParamList.Add(LParam.Name); 186 | end; 187 | LEvt := TExportedEvent.Create(LMethodName, LParamList.ToArray()); 188 | if not AEvents.Contains(LEvt) then 189 | AEvents.Add(LEvt); 190 | finally 191 | LParamList.Free(); 192 | end; 193 | end; 194 | end; 195 | function FindComponentRefs(): TArray; 196 | var 197 | LCompList: TList; 198 | begin 199 | LCompList := TList.Create(); 200 | try 201 | EnumComps(AFormEditor, procedure(AComponent: TComponent) begin 202 | LCompList.Add(AComponent); 203 | end); 204 | 205 | Result := LCompList.ToArray(); 206 | finally 207 | LCompList.Free(); 208 | end; 209 | end; 210 | var 211 | LEvts: TExportedEventList; 212 | LRttiCtx: TRttiContext; 213 | LComponent: TComponent; 214 | begin 215 | LEvts := TExportedEventList.Create( 216 | TDelegatedComparer.Create( 217 | function(const Left, Right: TExportedEvent): Integer begin 218 | Result := CompareStr(Left.MethodName, Right.MethodName); 219 | end)); 220 | 221 | try 222 | LRttiCtx := TRttiContext.Create(); 223 | try 224 | //Extract the form events 225 | ExtractPropertyEvents(LRttiCtx, ADesigner.Root, LEvts); 226 | //Extract the component events 227 | for LComponent in FindComponentRefs() do 228 | ExtractPropertyEvents(LRttiCtx, LComponent, LEvts); 229 | finally 230 | LRttiCtx.Free(); 231 | end; 232 | Result := LEvts.ToArray(); 233 | finally 234 | LEvts.Free(); 235 | end; 236 | end; 237 | 238 | class function TIOTAUtils.FindForm(const AFormName: string; out AFormInfo: TIOTAFormInfo): boolean; 239 | var 240 | LModuleServices: IOTAModuleServices; 241 | LModule: IOTAModule; 242 | LEditor: IOTAFormEditor; 243 | LDesigner: IDesigner; 244 | begin 245 | LModuleServices := (BorlandIDEServices as IOTAModuleServices); 246 | LModule := LModuleServices.FindFormModule(AFormName); 247 | if not Assigned(LModule) then 248 | Exit(false); 249 | 250 | LEditor := GetFormEditorFromModule(LModule); 251 | if not Assigned(LEditor) then 252 | Exit(false); 253 | 254 | LDesigner := (LEditor as INTAFormEditor).FormDesigner; 255 | if not Assigned(LDesigner) then 256 | Exit(false); 257 | 258 | AFormInfo.FileName := LModule.FileName; 259 | AFormInfo.FormName := LDesigner.Root.Name; 260 | AFormInfo.FrameworkType := GetFrameworkTypeFromDesigner(LDesigner); 261 | AFormInfo.Module := LModule; 262 | AFormInfo.Editor := LEditor; 263 | AFormInfo.Designer := LDesigner; 264 | Result := true; 265 | end; 266 | 267 | class function TIOTAUtils.GetEditorContentFromEditor( 268 | const AEditor: IOTAEditor): IOTAEditorContent; 269 | begin 270 | if not Supports(AEditor, IOTAEditorContent, Result) then 271 | Result := nil; 272 | end; 273 | 274 | class function TIOTAUtils.GetFormCaption(const AComponent: TComponent): string; 275 | begin 276 | if AComponent is Vcl.Forms.TForm then 277 | Result := Vcl.Forms.TForm(AComponent).Caption 278 | else if AComponent is Fmx.Forms.TForm then 279 | Result := Fmx.Forms.TForm(AComponent).Caption 280 | else 281 | Result := String.Empty; 282 | end; 283 | 284 | class function TIOTAUtils.GetFormEditorFromModule(const AModule: IOTAModule): IOTAFormEditor; 285 | var 286 | I: integer; 287 | LEditor: IOTAEditor; 288 | begin 289 | if AModule = nil then 290 | Exit(nil); 291 | 292 | for I := 0 to AModule.GetModuleFileCount - 1 do begin 293 | LEditor := AModule.GetModuleFileEditor(i); 294 | if Supports(LEditor, IOTAFormEditor, Result) then 295 | Break; 296 | end; 297 | end; 298 | 299 | class function TIOTAUtils.GetFrameworkTypeFromDesigner( 300 | const ADesigner: IDesigner): string; 301 | begin 302 | if CompareText(ADesigner.DesignerExtention, 'dfm') = 0 then 303 | Result := 'VCL' 304 | else if CompareText(ADesigner.DesignerExtention, 'fmx') = 0 then 305 | Result := 'FMX' 306 | else 307 | raise EUnknownFrameworkType.Create('Unknown framework type.'); 308 | end; 309 | 310 | class function TIOTAUtils.GuessMainForm( 311 | const AProject: IOTAProject): IOTAModule; 312 | var 313 | LEntries: TDprEntries; 314 | LModuleServices: IOTAModuleServices; 315 | begin 316 | LEntries := ScanDprEntries(AProject); 317 | if not Assigned(LEntries) then 318 | Exit(nil); 319 | 320 | LModuleServices := (BorlandIDEServices as IOTAModuleServices); 321 | Result := LModuleServices.FindFormModule(LEntries[Low(LEntries)].Value); 322 | end; 323 | 324 | class function TIOTAUtils.HasForms: boolean; 325 | var 326 | LModuleServices: IOTAModuleServices; 327 | I: Integer; 328 | LModule: IOTAModule; 329 | begin 330 | LModuleServices := (BorlandIDEServices as IOTAModuleServices); 331 | for I := 0 to LModuleServices.ModuleCount - 1 do begin 332 | LModule := LModuleServices.Modules[I]; 333 | if ModuleIsExportable(LModule) then 334 | Exit(true); 335 | end; 336 | Result := false; 337 | end; 338 | 339 | class function TIOTAUtils.ModuleIsForm(const AModule: IOTAModule): boolean; 340 | var 341 | LEditor: IOTAFormEditor; 342 | LDesigner: IDesigner; 343 | LRoot: TComponent; 344 | begin 345 | LEditor := GetFormEditorFromModule(AModule); 346 | if not Assigned(LEditor) then 347 | Exit(false); 348 | LDesigner := (LEditor as INTAFormEditor).FormDesigner; 349 | if not Assigned(LDesigner) then 350 | Exit(false); 351 | LRoot := LDesigner.Root; 352 | if not Assigned(LRoot) then 353 | Exit(false); 354 | if not (LRoot.InheritsFrom(Vcl.Forms.TForm) 355 | or LRoot.InheritsFrom(Fmx.Forms.TForm)) then 356 | Exit(false); 357 | Result := true; 358 | end; 359 | 360 | class function TIOTAUtils.ModuleIsPas(const AModule: IOTAModule): boolean; 361 | begin 362 | Result := SameText(ExtractFileExt(AModule.FileName), '.pas'); 363 | end; 364 | 365 | class function TIOTAUtils.ScanDprEntries( 366 | const AProject: IOTAProject): TDprEntries; 367 | var 368 | I: integer; 369 | LEditor: IOTAEditor; 370 | LEditorContent: IOTAEditorContent; 371 | LOleStream: TStream; 372 | LStream: TStringStream; 373 | LMatches: TMatchCollection; 374 | LValues: string; 375 | LPair: TArray; 376 | begin 377 | LEditor := FindDelphiProjectEditor(AProject); 378 | if not Assigned(LEditor) then 379 | Exit(nil); 380 | 381 | LEditorContent := GetEditorContentFromEditor(LEditor); 382 | if not Assigned(LEditorContent) then 383 | Exit(nil); 384 | 385 | LOleStream := TOleStream.Create(LEditorContent.Content); 386 | try 387 | LStream := TStringStream.Create(''); 388 | try 389 | LStream.CopyFrom(LOleStream); 390 | 391 | LMatches := TRegEx.Matches( 392 | LStream.DataString, 393 | 'Application.CreateForm\((.*?)\);', 394 | [roIgnoreCase, roMultiLine]); 395 | 396 | finally 397 | LStream.Free(); 398 | end; 399 | finally 400 | LOleStream.Free(); 401 | end; 402 | 403 | if (LMatches.Count = 0) then 404 | Exit(nil); 405 | 406 | LValues := String.Empty; 407 | for I := 0 to LMatches.Count - 1 do 408 | LValues := LValues + LMatches.Item[I].Value + sLineBreak; 409 | 410 | LMatches := TRegEx.Matches( 411 | LValues, 412 | '\((.*?)\)', 413 | [roIgnoreCase, roMultiLine]); 414 | 415 | for I := 0 to LMatches.Count - 1 do begin 416 | LPair := LMatches.Item[I].Value 417 | .Replace('(', '', []) 418 | .Replace(')', '', []) 419 | .Replace(' ', '', [rfReplaceAll]) 420 | .Split([',']); 421 | 422 | if Length(LPair) <> 2 then 423 | Continue; 424 | 425 | Result := Result + [ 426 | TDprEntry.Create( 427 | LPair[Low(LPair)], 428 | LPair[Low(LPair) + 1]) 429 | ]; 430 | end; 431 | end; 432 | 433 | class function TIOTAUtils.ModuleIsCpp(const AModule: IOTAModule): boolean; 434 | begin 435 | Result := SameText(ExtractFileExt(AModule.FileName), '.cpp'); 436 | end; 437 | 438 | class function TIOTAUtils.ModuleIsExportable( 439 | const AModule: IOTAModule): boolean; 440 | begin 441 | Result := (ModuleIsPas(AModule) or ModuleIsCpp(AModule)) 442 | and ModuleIsForm(AModule); 443 | end; 444 | 445 | class procedure TIOTAUtils.EnumComps(const AFormEditor: IOTAFormEditor; 446 | const ACallback: TProc); 447 | var 448 | LRoot: IOTAComponent; 449 | I: integer; 450 | LComp: TComponent; 451 | begin 452 | if not Assigned(ACallback) then 453 | Exit; 454 | LRoot := AFormEditor.GetRootComponent(); 455 | if not Assigned(LRoot) then 456 | Exit; 457 | 458 | for I := 0 to LRoot.GetComponentCount() - 1 do begin 459 | LComp := TComponent(LRoot.GetComponent(I).GetComponentHandle()); 460 | if not Assigned(LComp) then 461 | Continue; 462 | 463 | ACallback(LComp); 464 | end; 465 | end; 466 | 467 | end. 468 | -------------------------------------------------------------------------------- /Source/PythonTools.Registration.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Registration; 2 | 3 | interface 4 | 5 | uses 6 | PythonTools.SplashScreen, PythonTools.Menu; 7 | 8 | procedure Register(); 9 | 10 | implementation 11 | 12 | procedure RegisterPythonToolsMenuServices(); 13 | begin 14 | with TPythonToolsMenu.Instance do 15 | HookMenu(); 16 | end; 17 | 18 | procedure Register(); 19 | begin 20 | RegisterPythonToolsMenuServices; 21 | end; 22 | 23 | initialization 24 | AddSplashScreen(); 25 | 26 | finalization 27 | 28 | end. 29 | -------------------------------------------------------------------------------- /Source/PythonTools.Registry.pas: -------------------------------------------------------------------------------- 1 | unit PythonTools.Registry; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Win.Registry, 7 | Winapi.Windows, 8 | PythonTools.Model.Design.Project, 9 | PythonTools.Model.Design.Forms; 10 | 11 | type 12 | TExporterRegistry = class 13 | private 14 | class function GetBaseRegistryKey(): string; 15 | class procedure UseActionKey(const AKey: string; const AProc: TProc); 16 | public 17 | class procedure SaveProjectModel(const AModel: TExportProjectDesignModel); 18 | class procedure LoadProjectModel(const AModel: TExportProjectDesignModel); 19 | 20 | class procedure SaveFormsModel(const AModel: TExportFormsDesignModel); 21 | class procedure LoadFormsModel(const AModel: TExportFormsDesignModel); 22 | end; 23 | 24 | implementation 25 | 26 | uses 27 | ToolsAPI, 28 | PythonTools.Common; 29 | 30 | const 31 | PROGRAM_KEY = 'Delphi4PythonExporter'; 32 | //Actions 33 | PROJECT_ACTION_KEY = 'ProjectAction'; 34 | FORMS_ACTION_KEY = 'FormsAction'; 35 | //Values 36 | DEFAULT_DIRECTORY_KEY = 'DefaultDirectory'; 37 | DEFAULT_SHOW_IN_EXPLORER = 'DefaultShowInExplorer'; 38 | DEFAULT_FORM_FILE_KIND = 'DefaultFormFileKind'; 39 | //Project values 40 | PROJECT_TITLE_KEY = 'ProjectTile'; 41 | PROJECT_MAIN_FORM = 'ProjectMainForm'; 42 | 43 | 44 | { TExporterRegistry } 45 | 46 | class function TExporterRegistry.GetBaseRegistryKey: string; 47 | begin 48 | with (BorlandIDEServices as IOTAServices) do 49 | Result := GetBaseRegistryKey(); 50 | end; 51 | 52 | class procedure TExporterRegistry.UseActionKey(const AKey: string; 53 | const AProc: TProc); 54 | var 55 | LRegistry: TRegistry; 56 | begin 57 | LRegistry := TRegistry.Create(); 58 | try 59 | LRegistry.RootKey := HKEY_CURRENT_USER; 60 | try 61 | if LRegistry.OpenKey(GetBaseRegistryKey(), false) then 62 | try 63 | if LRegistry.OpenKey(PROGRAM_KEY, true) then 64 | try 65 | if LRegistry.OpenKey(AKey, true) then 66 | try 67 | AProc(LRegistry); 68 | finally 69 | LRegistry.CloseKey(); 70 | end; 71 | finally 72 | LRegistry.CloseKey(); 73 | end; 74 | finally 75 | LRegistry.CloseKey(); 76 | end; 77 | finally 78 | LRegistry.CloseKey(); 79 | end; 80 | finally 81 | LRegistry.Free(); 82 | end; 83 | end; 84 | 85 | class procedure TExporterRegistry.LoadProjectModel( 86 | const AModel: TExportProjectDesignModel); 87 | begin 88 | UseActionKey(PROJECT_ACTION_KEY, procedure(ARegistry: TRegistry) begin 89 | AModel.ApplicationDirectory := ARegistry.ReadString(DEFAULT_DIRECTORY_KEY); 90 | if ARegistry.ValueExists(DEFAULT_SHOW_IN_EXPLORER) then 91 | AModel.ShowInExplorer := ARegistry.ReadBool(DEFAULT_SHOW_IN_EXPLORER); 92 | if ARegistry.ValueExists(DEFAULT_FORM_FILE_KIND) then 93 | AModel.FormFileKind := TFormFileKind(ARegistry.ReadInteger(DEFAULT_FORM_FILE_KIND)); 94 | if ARegistry.OpenKey(GuidToString(AModel.ApplicationId), false) then 95 | try 96 | AModel.ApplicationTitle := ARegistry.ReadString(PROJECT_TITLE_KEY); 97 | AModel.ApplicationMainForm := TFormNameAndFile.Create( 98 | Copy(ARegistry.ReadString(PROJECT_MAIN_FORM), 99 | Pos('.', ARegistry.ReadString(PROJECT_MAIN_FORM)) + 1, 100 | Length(ARegistry.ReadString(PROJECT_MAIN_FORM)) 101 | - Pos('.', ARegistry.ReadString(PROJECT_MAIN_FORM))), 102 | Copy(ARegistry.ReadString(PROJECT_MAIN_FORM), 103 | 1, 104 | Pos('.', ARegistry.ReadString(PROJECT_MAIN_FORM)) - 1)); 105 | finally 106 | ARegistry.CloseKey(); 107 | end; 108 | end); 109 | end; 110 | 111 | class procedure TExporterRegistry.SaveProjectModel( 112 | const AModel: TExportProjectDesignModel); 113 | begin 114 | UseActionKey(PROJECT_ACTION_KEY, procedure(ARegistry: TRegistry) begin 115 | ARegistry.WriteString(DEFAULT_DIRECTORY_KEY, AModel.ApplicationDirectory); 116 | ARegistry.WriteBool(DEFAULT_SHOW_IN_EXPLORER, AModel.ShowInExplorer); 117 | ARegistry.WriteInteger(DEFAULT_FORM_FILE_KIND, Integer(AModel.FormFileKind)); 118 | if ARegistry.OpenKey(GuidToString(AModel.ApplicationId), true) then begin 119 | try 120 | ARegistry.WriteString(PROJECT_TITLE_KEY, AModel.ApplicationTitle); 121 | ARegistry.WriteString(PROJECT_MAIN_FORM, 122 | AModel.ApplicationMainForm.CombineFileAndFormName()); 123 | finally 124 | ARegistry.CloseKey(); 125 | end; 126 | end; 127 | 128 | end); 129 | end; 130 | 131 | class procedure TExporterRegistry.LoadFormsModel( 132 | const AModel: TExportFormsDesignModel); 133 | begin 134 | UseActionKey(FORMS_ACTION_KEY, procedure(ARegistry: TRegistry) begin 135 | AModel.Directory := ARegistry.ReadString(DEFAULT_DIRECTORY_KEY); 136 | if ARegistry.ValueExists(DEFAULT_SHOW_IN_EXPLORER) then 137 | AModel.ShowInExplorer := ARegistry.ReadBool(DEFAULT_SHOW_IN_EXPLORER); 138 | end); 139 | end; 140 | 141 | class procedure TExporterRegistry.SaveFormsModel( 142 | const AModel: TExportFormsDesignModel); 143 | begin 144 | UseActionKey(FORMS_ACTION_KEY, procedure(ARegistry: TRegistry) begin 145 | ARegistry.WriteString(DEFAULT_DIRECTORY_KEY, AModel.Directory); 146 | ARegistry.WriteBool(DEFAULT_SHOW_IN_EXPLORER, AModel.ShowInExplorer); 147 | end); 148 | end; 149 | 150 | end. 151 | -------------------------------------------------------------------------------- /Source/PythonTools.SplashScreen.pas: -------------------------------------------------------------------------------- 1 | {$I PythonTools.inc} 2 | 3 | unit PythonTools.SplashScreen; 4 | 5 | interface 6 | 7 | procedure AddSplashScreen(); 8 | 9 | implementation 10 | 11 | uses 12 | ToolsAPI, Vcl.Graphics, Vcl.Imaging.pngimage; 13 | 14 | procedure AddSplashScreen(); 15 | const 16 | EMB_PY_IMG = 'embarcaderopython_24px'; 17 | var 18 | LImg: {$IFDEF DELPHI11_UP}TPngImage{$ELSE}TBitmap{$ENDIF DELPHI11_UP}; 19 | begin 20 | LImg := {$IFDEF DELPHI11_UP}TPngImage{$ELSE}TBitmap{$ENDIF DELPHI11_UP}.Create(); 21 | try 22 | LImg.LoadFromResourceName(HInstance, EMB_PY_IMG); 23 | {$IFDEF DELPHI11_UP} 24 | SplashScreenServices.AddPluginBitmap('Delphi4Python - Export forms for Python', [LImg], false, 'Registered', ''); 25 | {$ELSE} 26 | SplashScreenServices.AddPluginBitmap('Delphi4Python - Export forms for Python', LImg.Handle, false, 'Registered', ''); 27 | {$ENDIF DELPHI11_UP} 28 | finally 29 | LImg.Free(); 30 | end; 31 | end; 32 | 33 | end. 34 | -------------------------------------------------------------------------------- /Source/PythonTools.inc: -------------------------------------------------------------------------------- 1 | {$IFDEF VER300} 2 | {$DEFINE DELPHI10_UP} 3 | {$ENDIF VER300} 4 | 5 | {$IFDEF VER310} 6 | {$DEFINE DELPHI10_UP} 7 | {$DEFINE DELPHI10_1_UP} 8 | {$ENDIF VER310} 9 | 10 | {$IFDEF VER320} 11 | {$DEFINE DELPHI10_UP} 12 | {$DEFINE DELPHI10_1_UP} 13 | {$DEFINE DELPHI10_2_UP} 14 | {$ENDIF VER320} 15 | 16 | {$IFDEF VER330} 17 | {$DEFINE DELPHI10_UP} 18 | {$DEFINE DELPHI10_1_UP} 19 | {$DEFINE DELPHI10_2_UP} 20 | {$DEFINE DELPHI10_3_UP} 21 | {$ENDIF VER330} 22 | 23 | {$IFDEF VER340} 24 | {$DEFINE DELPHI10_UP} 25 | {$DEFINE DELPHI10_1_UP} 26 | {$DEFINE DELPHI10_2_UP} 27 | {$DEFINE DELPHI10_3_UP} 28 | {$DEFINE DELPHI10_4_UP} 29 | {$ENDIF VER340} 30 | 31 | {$IFDEF VER350} 32 | {$DEFINE DELPHI10_UP} 33 | {$DEFINE DELPHI10_1_UP} 34 | {$DEFINE DELPHI10_2_UP} 35 | {$DEFINE DELPHI10_3_UP} 36 | {$DEFINE DELPHI10_4_UP} 37 | {$DEFINE DELPHI11_UP} 38 | {$ENDIF VER350} 39 | 40 | {$IFDEF VER360} 41 | {$DEFINE DELPHI10_UP} 42 | {$DEFINE DELPHI10_1_UP} 43 | {$DEFINE DELPHI10_2_UP} 44 | {$DEFINE DELPHI10_3_UP} 45 | {$DEFINE DELPHI10_4_UP} 46 | {$DEFINE DELPHI11_UP} 47 | {$DEFINE DELPHI12_UP} 48 | {$ENDIF VER360} 49 | 50 | {$IFNDEF DELPHI10_UP} 51 | {$MESSAGE ERROR 'This framework requires Delphi 10 or higher.'} 52 | {$ENDIF DELPHI10_UP} 53 | -------------------------------------------------------------------------------- /Tests/FMX.Producer.Test.pas: -------------------------------------------------------------------------------- 1 | unit FMX.Producer.Test; 2 | 3 | interface 4 | 5 | uses 6 | DUnitX.TestFramework, 7 | PythonTools.Common, 8 | PythonTools.Producer, 9 | PythonTools.Producer.SimpleFactory, 10 | PythonTools.Model.Producer.Application, 11 | PythonTools.Model.Producer.Form, 12 | PythonTools.Model.Producer.FormFile; 13 | 14 | type 15 | [TestFixture] 16 | TFMXProducerTest = class 17 | private 18 | FProducer: IPythonCodeProducer; 19 | FApplicationModel: TApplicationProducerModel; 20 | FFormModel: TFormProducerModel; 21 | FFormFileModel: TFormFileProducerModel; 22 | 23 | function GetFilesDir(): string; 24 | function GetDataDir(): string; 25 | 26 | function BuildApplicationModel(): TApplicationProducerModel; 27 | function BuildFormModel(): TFormProducerModel; 28 | function BuildFormFileModel(): TFormFileProducerModel; 29 | public 30 | [Setup] 31 | procedure Setup; 32 | [TearDown] 33 | procedure TearDown; 34 | 35 | [Test] 36 | procedure CheckFormInheritance(); 37 | [Test] 38 | procedure GenerateApplication(); 39 | [Test] 40 | procedure GenerateForm(); 41 | [Test] 42 | procedure GenerateFormFileBin(); 43 | [Test] 44 | procedure GenerateFormFileTxt(); 45 | end; 46 | 47 | implementation 48 | 49 | uses 50 | System.SysUtils, System.IOUtils, System.Classes, FMX.Forms, Data.FMXForm; 51 | 52 | procedure TFMXProducerTest.Setup; 53 | begin 54 | FProducer := TProducerSimpleFactory.CreateProducer('FMX'); 55 | FApplicationModel := BuildApplicationModel(); 56 | FFormModel := BuildFormModel(); 57 | FFormFileModel := BuildFormFileModel(); 58 | end; 59 | 60 | procedure TFMXProducerTest.TearDown; 61 | begin 62 | FFormFileModel.Free(); 63 | FFormModel.Free(); 64 | FApplicationModel.Free(); 65 | FProducer := nil; 66 | TDirectory.Delete(GetFilesDir(), true); 67 | end; 68 | 69 | function TFMXProducerTest.GetDataDir: string; 70 | begin 71 | Result := TDirectory.GetParent(TDirectory.GetParent(ExtractFileDir(ParamStr(0)))); 72 | Result := TPath.Combine(Result, 'data'); 73 | end; 74 | 75 | function TFMXProducerTest.GetFilesDir: string; 76 | begin 77 | Result := TPath.Combine(ExtractFileDir(ParamStr(0)), 'testfiles'); 78 | if not TDirectory.Exists(Result) then 79 | TDirectory.CreateDirectory(Result); 80 | end; 81 | 82 | function TFMXProducerTest.BuildApplicationModel: TApplicationProducerModel; 83 | const 84 | UNIT_NAME = 'UnitProjectTest'; 85 | FORM_NAME = 'FormTest'; 86 | begin 87 | Result := TApplicationProducerModel.Create(); 88 | try 89 | Result.Directory := GetFilesDir(); 90 | Result.FileName := UNIT_NAME; 91 | 92 | Result.Title := 'Test'; 93 | Result.MainForm := FORM_NAME; 94 | 95 | var LForms := TFormNameAndFileList.Create(); 96 | try 97 | LForms.Add(TFormNameAndFile.Create(FORM_NAME, UNIT_NAME)); 98 | Result.ImportedForms := LForms.ToArray(); 99 | finally 100 | LForms.Free(); 101 | end; 102 | except 103 | on E: Exception do begin 104 | FreeAndNil(Result); 105 | raise; 106 | end; 107 | end; 108 | end; 109 | 110 | function TFMXProducerTest.BuildFormFileModel: TFormFileProducerModel; 111 | begin 112 | Result := TFormFileProducerModel.Create(); 113 | try 114 | Result.Directory := GetFilesDir(); 115 | Result.FileName := 'Data.FMXForm'; 116 | var LStream := TFileStream.Create(TPath.Combine(GetDataDir(), 'Data.FMXForm.fmx'), fmOpenRead); 117 | try 118 | Result.FormResource := LStream; 119 | Result.FormResource.Position := 0; 120 | finally 121 | LStream.Free(); 122 | end; 123 | Result.Form := FmxForm; 124 | Result.Mode := TFormFileMode.ffmPython; 125 | Result.FrameworkType := 'FMX'; 126 | except 127 | on E: Exception do begin 128 | FreeAndNil(Result); 129 | raise; 130 | end; 131 | end; 132 | end; 133 | 134 | function TFMXProducerTest.BuildFormModel: TFormProducerModel; 135 | const 136 | UNIT_NAME = 'UnitFormTest'; 137 | FORM_NAME = 'FormTest'; 138 | begin 139 | Result := TFormProducerModel.Create(); 140 | try 141 | Result.Directory := GetFilesDir(); 142 | Result.FileName := UNIT_NAME; 143 | 144 | Result.FormName := FORM_NAME; 145 | Result.FormParentName := TForm.ClassName.Replace('T', ''); 146 | 147 | var LExportCompList := TExportedComponentList.Create(); 148 | try 149 | LExportCompList.Add(TExportedComponent.Create('Comp1')); 150 | Result.ExportedComponents := LExportCompList.ToArray(); 151 | finally 152 | LExportCompList.Free(); 153 | end; 154 | 155 | var LExporEvtList := TExportedEventList.Create(); 156 | try 157 | LExporEvtList.Add(TExportedEvent.Create('Event1', 158 | TArray.Create('Param1', 'Param2'))); 159 | Result.ExportedEvents := LExporEvtList.ToArray(); 160 | finally 161 | LExporEvtList.Free(); 162 | end; 163 | except 164 | on E: Exception do begin 165 | FreeAndNil(Result); 166 | raise; 167 | end; 168 | end; 169 | end; 170 | 171 | procedure TFMXProducerTest.CheckFormInheritance; 172 | begin 173 | Assert.IsTrue(FProducer.IsValidFormInheritance(TForm)); 174 | end; 175 | 176 | procedure TFMXProducerTest.GenerateApplication; 177 | begin 178 | //Save the project file 179 | FProducer.SavePyApplicationFile(FApplicationModel, FApplicationModel.Stream); 180 | FApplicationModel.Stream.Position := 0; 181 | 182 | //Check for the generated file 183 | var LFilePath := TPath.Combine(FApplicationModel.Directory, FApplicationModel.FileName.AsPython()); 184 | Assert.IsTrue(TFile.Exists(LFilePath)); 185 | 186 | var LStrings := TStringList.Create(); 187 | try 188 | LStrings.LoadFromStream(FApplicationModel.Stream); 189 | 190 | {** this is what we excpect **} 191 | // from delphivcl import * 192 | // from UnitFormTest import FormTest 193 | // 194 | // def main(): 195 | // Application.Initialize() 196 | // Application.Title = 'Test' 197 | // MainForm = FormTest(Application) 198 | // MainForm.Show() 199 | // FreeConsole() 200 | // Application.Run() 201 | // 202 | // if __name__ == '__main__': 203 | // main() 204 | 205 | Assert.IsTrue(LStrings.Count = 13); 206 | Assert.IsTrue(LStrings[0] = 'from delphifmx import *'); 207 | Assert.IsTrue(LStrings[1] = Format('from %s import %s', [ 208 | FApplicationModel.ImportedForms[0].FileName, 209 | FApplicationModel.ImportedForms[0].FormName])); 210 | Assert.IsTrue(LStrings[2] = String.Empty); 211 | Assert.IsTrue(LStrings[3] = 'def main():'); 212 | Assert.IsTrue(LStrings[4] = sIdentation1 + 'Application.Initialize()'); 213 | Assert.IsTrue(LStrings[5] = sIdentation1 + Format('Application.Title = %s', [ 214 | FApplicationModel.Title.QuotedString()])); 215 | Assert.IsTrue(LStrings[6] = sIdentation1 + Format('Application.MainForm = %s(Application)', [ 216 | FApplicationModel.MainForm])); 217 | Assert.IsTrue(LStrings[7] = sIdentation1 + 'Application.MainForm.Show()'); 218 | Assert.IsTrue(LStrings[8] = sIdentation1 + 'Application.Run()'); 219 | Assert.IsTrue(LStrings[9] = sIdentation1 + 'Application.MainForm.Destroy()'); 220 | Assert.IsTrue(LStrings[10] = String.Empty); 221 | Assert.IsTrue(LStrings[11] = 'if __name__ == ''__main__'':'); 222 | Assert.IsTrue(LStrings[12] = sIdentation1 + 'main()'); 223 | finally 224 | LStrings.Free(); 225 | end; 226 | end; 227 | 228 | procedure TFMXProducerTest.GenerateForm; 229 | begin 230 | //Save the form file 231 | FProducer.SavePyForm(FFormModel, FFormFileModel, FFormModel.Stream); 232 | FFormModel.Stream.Position := 0; 233 | 234 | //Check for the generated file 235 | var LFilePath := TPath.Combine(FFormModel.Directory, FFormModel.FileName.AsPython()); 236 | Assert.IsTrue(TFile.Exists(LFilePath)); 237 | 238 | var LStrings := TStringList.Create(); 239 | try 240 | LStrings.LoadFromStream(FFormModel.Stream); 241 | {** this is what we excpect **} 242 | // import os 243 | // from delphivcl import * 244 | // 245 | // class FormTest(Form): 246 | // 247 | // def __init__(self, owner): 248 | // self.Comp1 = None 249 | // self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "UnitFormTest.pydfm")) 250 | // 251 | // def Event1(self, Param1, Param2): 252 | // pass 253 | 254 | Assert.IsTrue(LStrings.Count = 11); 255 | Assert.IsTrue(LStrings[0] = 'import os'); 256 | Assert.IsTrue(LStrings[1] = 'from delphifmx import *'); 257 | Assert.IsTrue(LStrings[2] = String.Empty); 258 | Assert.IsTrue(LStrings[3] = Format('class %s(Form):', [FFormModel.FormName])); 259 | Assert.IsTrue(LStrings[4] = String.Empty); 260 | Assert.IsTrue(LStrings[5] = sIdentation1 + 'def __init__(self, owner):'); 261 | Assert.IsTrue(LStrings[6] = sIdentation2 + Format('self.%s = None', [ 262 | FFormModel.ExportedComponents[0].ComponentName])); 263 | Assert.IsTrue(LStrings[7] = sIdentation2 264 | + Format('self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "%s%s"))', [ 265 | FFormModel.FileName, TFormFile('').AsPythonFmx()])); 266 | Assert.IsTrue(LStrings[8] = String.Empty); 267 | Assert.IsTrue(LStrings[9] = sIdentation1 + Format('def %s(self, %s, %s):', [ 268 | FFormModel.ExportedEvents[0].MethodName, 269 | FFormModel.ExportedEvents[0].MethodParams[0], 270 | FFormModel.ExportedEvents[0].MethodParams[1]])); 271 | Assert.IsTrue(LStrings[10] = sIdentation2 +'pass'); 272 | finally 273 | LStrings.Free(); 274 | end; 275 | end; 276 | 277 | procedure TFMXProducerTest.GenerateFormFileBin; 278 | begin 279 | //Save the project file 280 | FProducer.SavePyFormFileBin(FFormFileModel, FFormFileModel.Stream); 281 | 282 | //Check for the generated file 283 | var LFilePath := TPath.Combine(FFormFileModel.Directory, FFormFileModel.FormFile.AsPythonFmx()); 284 | Assert.IsTrue(TFile.Exists(LFilePath)); 285 | 286 | var LStream := TFileStream.Create(LFilePath, fmOpenRead or fmShareDenyNone); 287 | try 288 | var LReader := TReader.Create(LStream, 4096); 289 | try 290 | var LForm := TFmxForm.CreateNew(nil); 291 | try 292 | try 293 | LReader.ReadRootComponent(LForm); 294 | except 295 | on E: Exception do 296 | Assert.Fail(E.Message); 297 | end; 298 | finally 299 | LForm.Free(); 300 | end; 301 | finally 302 | LReader.Free(); 303 | end; 304 | finally 305 | LStream.Free(); 306 | end; 307 | end; 308 | 309 | procedure TFMXProducerTest.GenerateFormFileTxt; 310 | begin 311 | //Save the project file 312 | FProducer.SavePyFormFileTxt(FFormFileModel, FFormFileModel.Stream); 313 | 314 | //Check for the generated file 315 | var LFilePath := TPath.Combine(FFormFileModel.Directory, FFormFileModel.FormFile.AsPythonFmx()); 316 | Assert.IsTrue(TFile.Exists(LFilePath)); 317 | 318 | var LInput := TFileStream.Create(LFilePath, fmOpenRead or fmShareDenyNone); 319 | try 320 | var LOutput := TMemoryStream.Create(); 321 | try 322 | ObjectTextToBinary(LInput, LOutput); 323 | var LReader := TReader.Create(LOutput, 4096); 324 | try 325 | var LForm := TFmxForm.CreateNew(nil); 326 | try 327 | try 328 | LOutput.Position := 0; 329 | LReader.ReadRootComponent(LForm); 330 | except 331 | on E: Exception do 332 | Assert.Fail(E.Message); 333 | end; 334 | finally 335 | LForm.Free(); 336 | end; 337 | finally 338 | LReader.Free(); 339 | end; 340 | finally 341 | LOutput.Free(); 342 | end; 343 | finally 344 | LInput.Free(); 345 | end; 346 | end; 347 | 348 | initialization 349 | TDUnitX.RegisterTestFixture(TFMXProducerTest); 350 | 351 | end. 352 | -------------------------------------------------------------------------------- /Tests/PythonExporterTest.dpr: -------------------------------------------------------------------------------- 1 | program PythonExporterTest; 2 | 3 | {$IFNDEF TESTINSIGHT} 4 | {$APPTYPE CONSOLE} 5 | {$ENDIF} 6 | {$STRONGLINKTYPES ON} 7 | uses 8 | System.SysUtils, 9 | {$IFDEF TESTINSIGHT} 10 | TestInsight.DUnitX, 11 | {$ELSE} 12 | DUnitX.Loggers.Console, 13 | DUnitX.Loggers.Xml.NUnit, 14 | {$ENDIF } 15 | DUnitX.TestFramework, 16 | VCL.Producer.Test in 'VCL.Producer.Test.pas', 17 | Data.VCLForm in 'data\Data.VCLForm.pas' {VclForm}, 18 | Data.FMXForm in 'data\Data.FMXForm.pas' {FmxForm}, 19 | FMX.Producer.Test in 'FMX.Producer.Test.pas'; 20 | 21 | { keep comment here to protect the following conditional from being removed by the IDE when adding a unit } 22 | 23 | var 24 | runner : ITestRunner; 25 | results : IRunResults; 26 | logger : ITestLogger; 27 | nunitLogger : ITestLogger; 28 | begin 29 | {$IFDEF GUI} 30 | DUnitX.Loggers.GUI.VCL.Run(); 31 | Exit; 32 | {$ENDIF} 33 | try 34 | //Check command line options, will exit if invalid 35 | TDUnitX.CheckCommandLine; 36 | //Create the runner 37 | runner := TDUnitX.CreateRunner; 38 | runner.UseRTTI := True; 39 | 40 | //Tell the runned how we will log this 41 | if TDUnitX.Options.ConsoleMode <> TDunitXConsoleMode.Off then begin 42 | logger := TDUnitXConsoleLogger.Create(TDUnitX.Options.ConsoleMode = TDunitXConsoleMode.Quiet); 43 | runner.AddLogger(logger); 44 | end; 45 | 46 | nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile); 47 | runner.AddLogger(nunitLogger); 48 | 49 | //We want to see the results 50 | TDUnitX.Options.ExitBehavior := TDUnitXExitBehavior.Pause; 51 | 52 | //Run tests 53 | results := runner.Execute; 54 | if not results.AllPassed then 55 | System.ExitCode := EXIT_ERRORS; 56 | 57 | {$IFNDEF CI} 58 | if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then 59 | begin 60 | System.Write('Done.. press key to quit.'); 61 | System.Readln; 62 | end; 63 | {$ENDIF} 64 | except 65 | on E: Exception do 66 | System.Writeln(E.ClassName, ': ', E.Message); 67 | end; 68 | 69 | end. 70 | -------------------------------------------------------------------------------- /Tests/VCL.Producer.Test.pas: -------------------------------------------------------------------------------- 1 | unit VCL.Producer.Test; 2 | 3 | interface 4 | 5 | uses 6 | DUnitX.TestFramework, 7 | PythonTools.Common, 8 | PythonTools.Producer, 9 | PythonTools.Producer.SimpleFactory, 10 | PythonTools.Model.Producer.Application, 11 | PythonTools.Model.Producer.Form, 12 | PythonTools.Model.Producer.FormFile; 13 | 14 | type 15 | [TestFixture] 16 | TVCLProducerTest = class 17 | private 18 | FProducer: IPythonCodeProducer; 19 | FApplicationModel: TApplicationProducerModel; 20 | FFormModel: TFormProducerModel; 21 | FFormFileModel: TFormFileProducerModel; 22 | 23 | function GetFilesDir(): string; 24 | function GetDataDir(): string; 25 | 26 | function BuildApplicationModel(): TApplicationProducerModel; 27 | function BuildFormModel(): TFormProducerModel; 28 | function BuildFormFileModel(): TFormFileProducerModel; 29 | public 30 | [Setup] 31 | procedure Setup; 32 | [TearDown] 33 | procedure TearDown; 34 | 35 | [Test] 36 | procedure CheckFormInheritance(); 37 | [Test] 38 | procedure GenerateApplication(); 39 | [Test] 40 | procedure GenerateForm(); 41 | [Test] 42 | procedure GenerateFormFileBin(); 43 | [Test] 44 | procedure GenerateFormFileTxt(); 45 | end; 46 | 47 | implementation 48 | 49 | uses 50 | System.SysUtils, System.IOUtils, System.Classes, Vcl.Forms, Data.VCLForm; 51 | 52 | procedure TVCLProducerTest.Setup; 53 | begin 54 | FProducer := TProducerSimpleFactory.CreateProducer('VCL'); 55 | FApplicationModel := BuildApplicationModel(); 56 | FFormModel := BuildFormModel(); 57 | FFormFileModel := BuildFormFileModel(); 58 | end; 59 | 60 | procedure TVCLProducerTest.TearDown; 61 | begin 62 | FFormFileModel.Free(); 63 | FFormModel.Free(); 64 | FApplicationModel.Free(); 65 | FProducer := nil; 66 | TDirectory.Delete(GetFilesDir(), true); 67 | end; 68 | 69 | function TVCLProducerTest.GetDataDir: string; 70 | begin 71 | Result := TDirectory.GetParent(TDirectory.GetParent(ExtractFileDir(ParamStr(0)))); 72 | Result := TPath.Combine(Result, 'data'); 73 | end; 74 | 75 | function TVCLProducerTest.GetFilesDir: string; 76 | begin 77 | Result := TPath.Combine(ExtractFileDir(ParamStr(0)), 'testfiles'); 78 | if not TDirectory.Exists(Result) then 79 | TDirectory.CreateDirectory(Result); 80 | end; 81 | 82 | function TVCLProducerTest.BuildApplicationModel: TApplicationProducerModel; 83 | const 84 | UNIT_NAME = 'UnitProjectTest'; 85 | FORM_NAME = 'FormTest'; 86 | begin 87 | Result := TApplicationProducerModel.Create(); 88 | try 89 | Result.Directory := GetFilesDir(); 90 | Result.FileName := UNIT_NAME; 91 | 92 | Result.Title := 'Test'; 93 | Result.MainForm := FORM_NAME; 94 | 95 | var LForms := TFormNameAndFileList.Create(); 96 | try 97 | LForms.Add(TFormNameAndFile.Create(FORM_NAME, UNIT_NAME)); 98 | Result.ImportedForms := LForms.ToArray(); 99 | finally 100 | LForms.Free(); 101 | end; 102 | except 103 | on E: Exception do begin 104 | FreeAndNil(Result); 105 | raise; 106 | end; 107 | end; 108 | end; 109 | 110 | function TVCLProducerTest.BuildFormFileModel: TFormFileProducerModel; 111 | begin 112 | Result := TFormFileProducerModel.Create(); 113 | try 114 | Result.Directory := GetFilesDir(); 115 | Result.FileName := 'Data.VCLForm'; 116 | var LStream := TFileStream.Create(TPath.Combine(GetDataDir(), 'Data.VCLForm.dfm'), fmOpenRead); 117 | try 118 | Result.FormResource := LStream; 119 | Result.FormResource.Position := 0; 120 | finally 121 | LStream.Free(); 122 | end; 123 | Result.Form := VclForm; 124 | Result.Mode := TFormFileMode.ffmPython; 125 | Result.FrameworkType := 'VCL'; 126 | except 127 | on E: Exception do begin 128 | FreeAndNil(Result); 129 | raise; 130 | end; 131 | end; 132 | end; 133 | 134 | function TVCLProducerTest.BuildFormModel: TFormProducerModel; 135 | const 136 | UNIT_NAME = 'UnitFormTest'; 137 | FORM_NAME = 'FormTest'; 138 | begin 139 | Result := TFormProducerModel.Create(); 140 | try 141 | Result.Directory := GetFilesDir(); 142 | Result.FileName := UNIT_NAME; 143 | 144 | Result.FormName := FORM_NAME; 145 | Result.FormParentName := TForm.ClassName.Replace('T', ''); 146 | 147 | var LExportCompList := TExportedComponentList.Create(); 148 | try 149 | LExportCompList.Add(TExportedComponent.Create('Comp1')); 150 | Result.ExportedComponents := LExportCompList.ToArray(); 151 | finally 152 | LExportCompList.Free(); 153 | end; 154 | 155 | var LExporEvtList := TExportedEventList.Create(); 156 | try 157 | LExporEvtList.Add(TExportedEvent.Create('Event1', 158 | TArray.Create('Param1', 'Param2'))); 159 | Result.ExportedEvents := LExporEvtList.ToArray(); 160 | finally 161 | LExporEvtList.Free(); 162 | end; 163 | except 164 | on E: Exception do begin 165 | FreeAndNil(Result); 166 | raise; 167 | end; 168 | end; 169 | end; 170 | 171 | procedure TVCLProducerTest.CheckFormInheritance; 172 | begin 173 | Assert.IsTrue(FProducer.IsValidFormInheritance(TForm)); 174 | end; 175 | 176 | procedure TVCLProducerTest.GenerateApplication; 177 | begin 178 | //Save the project file 179 | FProducer.SavePyApplicationFile(FApplicationModel, FApplicationModel.Stream); 180 | FApplicationModel.Stream.Position := 0; 181 | 182 | //Check for the generated file 183 | var LFilePath := TPath.Combine(FApplicationModel.Directory, FApplicationModel.FileName.AsPython()); 184 | Assert.IsTrue(TFile.Exists(LFilePath)); 185 | 186 | var LStrings := TStringList.Create(); 187 | try 188 | LStrings.LoadFromStream(FApplicationModel.Stream); 189 | 190 | {** this is what we excpect **} 191 | // from delphivcl import * 192 | // from UnitFormTest import FormTest 193 | // 194 | // def main(): 195 | // Application.Initialize() 196 | // Application.Title = 'Test' 197 | // MainForm = FormTest(Application) 198 | // MainForm.Show() 199 | // FreeConsole() 200 | // Application.Run() 201 | // 202 | // if __name__ == '__main__': 203 | // main() 204 | 205 | Assert.IsTrue(LStrings.Count = 13); 206 | Assert.IsTrue(LStrings[0] = 'from delphivcl import *'); 207 | Assert.IsTrue(LStrings[1] = Format('from %s import %s', [ 208 | FApplicationModel.ImportedForms[0].FileName, 209 | FApplicationModel.ImportedForms[0].FormName])); 210 | Assert.IsTrue(LStrings[2] = String.Empty); 211 | Assert.IsTrue(LStrings[3] = 'def main():'); 212 | Assert.IsTrue(LStrings[4] = sIdentation1 + 'Application.Initialize()'); 213 | Assert.IsTrue(LStrings[5] = sIdentation1 + Format('Application.Title = %s', [ 214 | FApplicationModel.Title.QuotedString()])); 215 | Assert.IsTrue(LStrings[6] = sIdentation1 + Format('MainForm = %s(Application)', [ 216 | FApplicationModel.MainForm])); 217 | Assert.IsTrue(LStrings[7] = sIdentation1 + 'MainForm.Show()'); 218 | Assert.IsTrue(LStrings[8] = sIdentation1 + 'FreeConsole()'); 219 | Assert.IsTrue(LStrings[9] = sIdentation1 + 'Application.Run()'); 220 | Assert.IsTrue(LStrings[10] = String.Empty); 221 | Assert.IsTrue(LStrings[11] = 'if __name__ == ''__main__'':'); 222 | Assert.IsTrue(LStrings[12] = sIdentation1 + 'main()'); 223 | finally 224 | LStrings.Free(); 225 | end; 226 | end; 227 | 228 | procedure TVCLProducerTest.GenerateForm; 229 | begin 230 | //Save the form file 231 | FProducer.SavePyForm(FFormModel, FFormFileModel, FFormModel.Stream); 232 | FFormModel.Stream.Position := 0; 233 | 234 | //Check for the generated file 235 | var LFilePath := TPath.Combine(FFormModel.Directory, FFormModel.FileName.AsPython()); 236 | Assert.IsTrue(TFile.Exists(LFilePath)); 237 | 238 | var LStrings := TStringList.Create(); 239 | try 240 | LStrings.LoadFromStream(FFormModel.Stream); 241 | {** this is what we excpect **} 242 | // import os 243 | // from delphivcl import * 244 | // 245 | // class FormTest(Form): 246 | // 247 | // def __init__(self, owner): 248 | // self.Comp1 = None 249 | // self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "UnitFormTest.pydfm")) 250 | // 251 | // def Event1(self, Param1, Param2): 252 | // pass 253 | 254 | Assert.IsTrue(LStrings.Count = 11); 255 | Assert.IsTrue(LStrings[0] = 'import os'); 256 | Assert.IsTrue(LStrings[1] = 'from delphivcl import *'); 257 | Assert.IsTrue(LStrings[2] = String.Empty); 258 | Assert.IsTrue(LStrings[3] = Format('class %s(Form):', [FFormModel.FormName])); 259 | Assert.IsTrue(LStrings[4] = String.Empty); 260 | Assert.IsTrue(LStrings[5] = sIdentation1 + 'def __init__(self, owner):'); 261 | Assert.IsTrue(LStrings[6] = sIdentation2 + Format('self.%s = None', [ 262 | FFormModel.ExportedComponents[0].ComponentName])); 263 | Assert.IsTrue(LStrings[7] = sIdentation2 264 | + Format('self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "%s%s"))', [ 265 | FFormModel.FileName, TFormFile('').AsPythonDfm()])); 266 | Assert.IsTrue(LStrings[8] = String.Empty); 267 | Assert.IsTrue(LStrings[9] = sIdentation1 + Format('def %s(self, %s, %s):', [ 268 | FFormModel.ExportedEvents[0].MethodName, 269 | FFormModel.ExportedEvents[0].MethodParams[0], 270 | FFormModel.ExportedEvents[0].MethodParams[1]])); 271 | Assert.IsTrue(LStrings[10] = sIdentation2 +'pass'); 272 | finally 273 | LStrings.Free(); 274 | end; 275 | end; 276 | 277 | procedure TVCLProducerTest.GenerateFormFileBin; 278 | begin 279 | //Save the project file 280 | FProducer.SavePyFormFileBin(FFormFileModel, FFormFileModel.Stream); 281 | 282 | //Check for the generated file 283 | var LFilePath := TPath.Combine(FFormFileModel.Directory, FFormFileModel.FormFile.AsPythonDfm()); 284 | Assert.IsTrue(TFile.Exists(LFilePath)); 285 | 286 | var LStream := TFileStream.Create(LFilePath, fmOpenRead or fmShareDenyNone); 287 | try 288 | var LReader := TReader.Create(LStream, 4096); 289 | try 290 | var LForm := TVclForm.CreateNew(nil); 291 | try 292 | try 293 | LReader.ReadRootComponent(LForm); 294 | except 295 | on E: Exception do 296 | Assert.Fail(E.Message); 297 | end; 298 | finally 299 | LForm.Free(); 300 | end; 301 | finally 302 | LReader.Free(); 303 | end; 304 | finally 305 | LStream.Free(); 306 | end; 307 | end; 308 | 309 | procedure TVCLProducerTest.GenerateFormFileTxt; 310 | begin 311 | //Save the project file 312 | FProducer.SavePyFormFileTxt(FFormFileModel, FFormFileModel.Stream); 313 | 314 | //Check for the generated file 315 | var LFilePath := TPath.Combine(FFormFileModel.Directory, FFormFileModel.FormFile.AsPythonDfm()); 316 | Assert.IsTrue(TFile.Exists(LFilePath)); 317 | 318 | var LInput := TFileStream.Create(LFilePath, fmOpenRead or fmShareDenyNone); 319 | try 320 | var LOutput := TMemoryStream.Create(); 321 | try 322 | ObjectTextToBinary(LInput, LOutput); 323 | var LReader := TReader.Create(LOutput, 4096); 324 | try 325 | var LForm := TVclForm.CreateNew(nil); 326 | try 327 | try 328 | LOutput.Position := 0; 329 | LReader.ReadRootComponent(LForm); 330 | except 331 | on E: Exception do 332 | Assert.Fail(E.Message); 333 | end; 334 | finally 335 | LForm.Free(); 336 | end; 337 | finally 338 | LReader.Free(); 339 | end; 340 | finally 341 | LOutput.Free(); 342 | end; 343 | finally 344 | LInput.Free(); 345 | end; 346 | end; 347 | 348 | initialization 349 | TDUnitX.RegisterTestFixture(TVCLProducerTest); 350 | 351 | end. 352 | -------------------------------------------------------------------------------- /Tests/data/Data.FMXForm.fmx: -------------------------------------------------------------------------------- 1 | object FmxForm: TFmxForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form1' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | end 12 | -------------------------------------------------------------------------------- /Tests/data/Data.FMXForm.pas: -------------------------------------------------------------------------------- 1 | unit Data.FMXForm; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs; 8 | 9 | type 10 | TFmxForm = class(TForm) 11 | private 12 | { Private declarations } 13 | public 14 | { Public declarations } 15 | end; 16 | 17 | var 18 | FmxForm: TFmxForm; 19 | 20 | implementation 21 | 22 | {$R *.fmx} 23 | 24 | initialization 25 | FmxForm := TFmxForm.Create(nil); 26 | 27 | finalization 28 | FmxForm.Free(); 29 | 30 | end. 31 | -------------------------------------------------------------------------------- /Tests/data/Data.VCLForm.dfm: -------------------------------------------------------------------------------- 1 | object VclForm: TVclForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'VclForm' 5 | ClientHeight = 441 6 | ClientWidth = 624 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -12 11 | Font.Name = 'Segoe UI' 12 | Font.Style = [] 13 | PixelsPerInch = 96 14 | TextHeight = 15 15 | end 16 | -------------------------------------------------------------------------------- /Tests/data/Data.VCLForm.pas: -------------------------------------------------------------------------------- 1 | unit Data.VCLForm; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs; 8 | 9 | type 10 | TVclForm = class(TForm) 11 | private 12 | { Private declarations } 13 | public 14 | { Public declarations } 15 | end; 16 | 17 | var 18 | VclForm: TVclForm; 19 | 20 | implementation 21 | 22 | {$R *.dfm} 23 | 24 | initialization 25 | VclForm := TVclForm.Create(nil); 26 | 27 | finalization 28 | VclForm.Free(); 29 | 30 | end. 31 | -------------------------------------------------------------------------------- /images/EmbarcaderoPython(154px).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/EmbarcaderoPython(154px).png -------------------------------------------------------------------------------- /images/EmbarcaderoPython(16px).bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/EmbarcaderoPython(16px).bmp -------------------------------------------------------------------------------- /images/EmbarcaderoPython(16px).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/EmbarcaderoPython(16px).png -------------------------------------------------------------------------------- /images/EmbarcaderoPython(24px).bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/EmbarcaderoPython(24px).bmp -------------------------------------------------------------------------------- /images/EmbarcaderoPython(24px).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/EmbarcaderoPython(24px).png -------------------------------------------------------------------------------- /images/Export2Python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/Export2Python.png -------------------------------------------------------------------------------- /images/ExportCurrentProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/ExportCurrentProject.png -------------------------------------------------------------------------------- /images/ExportForms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/Delphi4PythonExporter/e009e337ce844b591cc01430e6790cb9eadf2b2f/images/ExportForms.png -------------------------------------------------------------------------------- /images/readme.md: -------------------------------------------------------------------------------- 1 | 2 | ![Export2Python](https://github.com/Embarcadero/Delphi4PythonExporter/raw/main/images/Export2Python.png) 3 | --------------------------------------------------------------------------------