(resent per Matthew's request)

Matthew Fairclough wrote:

I would like to thank Ed and Paul for their responses and updates.  I
just downloaded the latest tarball and everything works perfectly
(though I must admit still having difficulty with ReportDesigner)

ReportDesigner isn't usable yet, but under heavy development.


Dabo seems perfect.  The SimpleApps showed exactly what I need in terms
of entry, edit, and search.  Also, ReportDesigner will allow me to
create the reports I need (once I can figure out how to use it:)

No, ReportDesigner can't do that yet, and it will probably be on the order of
months until it can.


However, I'm having a little difficulty determining whether Dabo is
sufficiently developed for someone like myself.  I have a feeling that I
might be a few years too early. One of the main reasons for this is the
documentation.  I understand that it is the last part of the agenda, but
I am lost without it

You are indeed a bit early if you want a fully-developed toolkit with full
instructions on how to use it. However, if you can afford to get your hands a
bit dirty, from what you've said about your project with a little elbow grease
I'm certain you could get a Dabo app up and running for your purposes.


If someone can point me in the right direction, perhaps I can get a
better grip on this.  Using the OneToManyApp as an example

I'm really kind of embarrassed that you are using the OneToManyApp, as it was
never followed through with and doesn't completely work.


1.  Instead of opening a new app for every table (which would confuse my
users no end), I have been trying to open each table as a separate tab
(much like FieldSpecEditor).

First off, it isn't a new app for every table, but a new form for each entity.
It could be that an entity comprises a number of underlying tables, but the
users only care about the entity, not the composition of the underlying 
database.


Each tab would be identical to the current
forms.  In this way there is only one window, and if a user wanted to do
other things (such as a report), they would just open another tab.  I
haven't had any success with this.  How can this be done

First off, for testing purposes only, and just so you can get started, please
temporarily set the OneToManyApp aside, and try out my new AppWizard, which is
in the daboide/wizards directory and is called "AppWizardX". Pick one main table
in your database, and only generate the app for that one table and follow the
wizard through.

AppWizardX will generate a directory structure that will make more sense than
the files the current AppWizard generates. Unfortunately I haven't gotten around
to adding comments to the generated source files yet to offer direction on how
to override behaviors and such, but at this point please just generate this
first test app and verify that it works at a basic level.

I don't think you should add more tabs if the tabs don't relate directly with
the entity for that form, although that can certainly be done but you've got to
write code in the overridden method.

For instance, this line at the end of my FrmClients.afterInit() adds a page that
I've defined to list the client's activity and report their current balance:

                self.PageFrame.appendPage(PagClientBalance, "Balance")


2.  I need to customise the search page to search on foreign keys with
drop down menus.  The options in FieldSpecEditor seem limited.  How can
I add custom fields to configure the search form (and also the entry
form) to a greater degree

I'm working on giving user code a hook into the search options, so stay tuned on
that. As far as the edit page goes, you can override that by changing your form
code (located in ui/Frm*.py, where * is the name of the table) to something like
(my example is with FrmClients):

class FrmClients(FrmBase):

        def initProperties(self):
                FrmClients.doDefault()
                self.NameBase = "frmClients"
                self.Caption = "Clients"


        def addEditPage(self, dataSource, title, pageClass=None):
                # If you have an overrided edit page, stick it in here:
                pageClass = self.Application.ui.PagEditClient
                FrmClients.doDefault(dataSource, title, pageClass)

I've just told Dabo to load my custom edit page, and I'm now required to create
that edit page. This requires you getting your hands dirty and actually writing
some code. Here is my PagEditClient class, located in ui/PagEditClient.py:


import dabo
from PagBase import PagBase
import baseControls


class PagEditClient(PagBase):

        def afterInit(self):
                lProps = {"Width": 150, "Alignment": "Right"}
                fProps = {"DataSource": "clients"}

                p = self.addObject(dabo.ui.dPanel, Name="panAddress", 
Sizer=dabo.ui.dSizer("v"))
                p.Sizer.appendSpacer(10)
                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="Attention (f, 
m, l):",
                                      **lProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="cfirst", 
Width=100,
                                      **fProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="cmiddle", Width=100,
                                      **fProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="clast", 
Width=130,
                                      **fProps))
                p.Sizer.append(hs)
                
                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="Company:", 
**lProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="ccompany",
                          Width=330, **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="Address:", 
**lProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="caddress1",
                          Width=330, **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="", 
**lProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="caddress2",
                          Width=330, **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="", 
**lProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="caddress3",
                          Width=330, **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="City, State, 
Zip:",
                          **lProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="ccity", 
Width=150,
                          **fProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="cstate", 
Width=55,
                          **fProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="czip", 
Width=125,
                          **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="Phone1, Phone2, 
Fax:",
                          **lProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="cphone1", Width=110,
                          **fProps))
                hs.append(p.addObject(baseControls.TxtBase, 
DataField="cphone2", Width=110,
                          **fProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="cfax", 
Width=110,
                          **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="email:", 
**lProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="cemail", 
Width=330,
                          **fProps))
                p.Sizer.append(hs)

                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="URL:", 
**lProps))
                hs.append1x(p.addObject(baseControls.TxtBase, DataField="curl", 
Width=330,
                            **fProps))
                p.Sizer.append(hs)

                self.Sizer.append(p)

                del(lProps["Width"])

                p = self.addObject(dabo.ui.dPanel, Name="panMiddle",
                                   Sizer=dabo.ui.dSizer("v"))
                p.Sizer.appendSpacer(10)
                hs = dabo.ui.dSizer("h")
                hs.appendSpacer(50)
                hs.append(p.addObject(baseControls.LblBase, Caption="Code:", 
Width=50,
                          **lProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="ccode", 
Width=50,
                          **fProps))
                hs.append(p.addObject(baseControls.LblBase,
                          Caption="Default Billing Rate:", Width=150, **lProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="nrate", 
Width=50,
                          **fProps))
                hs.append(p.addObject(baseControls.LblBase, Caption="Terms:", 
Width=50,
                          **lProps))
                hs.append(p.addObject(baseControls.TxtBase, DataField="cterms", 
Width=75,
                          **fProps))
                p.Sizer.append(hs)

                self.Sizer.append(p)

                p = self.addObject(dabo.ui.dPanel, Name="panBottom",
                                   Sizer=dabo.ui.dSizer("v"))
                p.Sizer.appendSpacer(10)
                hs = dabo.ui.dSizer("h")
                hs.append(p.addObject(baseControls.LblBase, Caption="Notes:", 
Width=100,
                          **lProps))
                hs.append(p.addObject(baseControls.EdtBase, Width=375, 
DataField="mnotes",
                          **fProps), "expand")
                p.Sizer.append1x(hs)

                self.Sizer.append1x(p)
                self.Sizer.appendSpacer(10)


Yuck! Some of the lines wrapped, so watch out for that. Basically, 95% of this
code is boilerplate sizer-related stuff. It took about an hour for me to
edit/test/repeat until I got the layout right. The layout the wizard outputs is
acceptable for small tables and as a default, but for anything else you are
going to have to do something like my above code to get a good layout. The
basecontrols are just thin wrappers over the dabo base controls. Ignore them and
just replace in your mind eg baseControls.LblBase -> dabo.ui.dLabel.

I don't mean to overwhelm you, but this is the level at which you currently must
work in order to get effective with Dabo. This won't always be the case, but it
is the case right now. Dabo as a framework and library is really 95% capable
right now given wxPython and the databases we support. But as a RAD tool it has
only begun to scratch the surface.


3.  Many of the reports I will need to produce involve joins from
several tables.  For example, a report of each orditem with the total
number of orders.  Where would such code go

Multi-table joins aren't a problem, that is a common need. What the runtime
ReportWriter needs is a single dataset (denormalize your multiple tables into
one dataset with repeated values in the proper order for consumption by the
report writer), and a report format xml file (rfxml). The rfxml has sections for
different report bands (pageHeader, pageFooter, detail, groupHeader,
groupFooter...), report grouping definitions (what expression to group on),
report variable definitions (running totals by group, for example), the page
margins and orientation, etc. Each band can have any number of objects such as
rectangles, lines, strings, and long strings. Each object has properties such as
font, font size, rotation, background/foreground color.

For my invoices, I have a getInvoicesDataSet() function in my db layer that puts
everything I need into the invoices dataset. Then, in my reports directory I
have invoice.rfxml which specifies the layout of the invoice report. I coded
both of these by hand, an investment of perhaps 8-12 tedious hours, mostly spent
on edit/test/repeat of the invoice report format. The report actually gets run
from a menu item Reports|Invoices, which pulls up a modal dialog with some
selection criteria and a "Run Report" button.

The tedium of manually constructing the rfxml file will go away as soon as the
ReportDesigner is working (a few months at least). The tedium of constructing
the UI forms, pages, etc. will go away as soon as the UI Designer is working
(probably a few months as well).

We really appreciate your thoughts and feedback, and hope Dabo can work for you.


I really would like to use Dabo.  The benefits to Dabo would be an
international (non-IT) company using Dabo as it's primary recording
system.  I'm sure that would make for good press

I'll just come out and ask: would there be any opportunity for a contract with
Ed and/or myself to get this implemented for you? You'd walk away with source
code you could look at and tweak to your needs, and we'd walk away with needed
financial support as well as a better Dabo.


--
Paul McNett
http://paulmcnett.com
http://dabodev.com


_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-users


_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-users

Reply via email to