How Far We’ve Come – Pt. 2

We need to establish a time frame before I start showing any code. Yes, you can go visit Source Forge to pull down what is there if you are well and truly desperate to view it. This portion is more about the journey than the code.

xpnsqt

The xpnsqt program was originally written around the time IBM sunset OS/2 which, according to this article, spanned the time frame between March 12, 2003 and December 31, 2004. Foundations of Qt Development came out in 2007 and C++ GUI Programming with Qt 4 came out in 2006. Both of them discussed QSqlDatabase. Ordinarily I would just hit the help key in QtCreator for QSqlDatabase. It would then take me to a help page which would say something like “feature/class was added in version blah.ha. Funny thing happened when I tried that today.

qtCreator image

Couldn’t find it on that page. Searched on-line in the 4.8 documentation and didn’t find any mention of when QSqlDatabase class was added. I don’t remember it being in Qt3 but I didn’t do that much with Qt3 because the message boards said Qt4 was going to be a night and day difference.

Point and Laugh

At any rate, now that most of you have some idea just how long ago this was and the fact it was my first “real” Qt program, it is time to let everyone point and laugh.

main.cpp

/****************************************************************************
 * Originally created by Roland Hughes at Logikal Solutions.
 * Project is being released under GPL2 license.
 *
 * At some point in the future either Logikal Solutions or Roland Hughes
 * may elect to publish a book with this original source code in it.  If
 * the book is written it will be part of "The Minimum You Need to Know"
 * book series.
 ****************************************************************************/
#include 
#include 
#include 
#include 

#include "XpnsLogonDialog.h"

int main(int argc, char *argv[])
{
    int i_x;
    QString qtDbName;
    QTime theTime = QTime::currentTime();

    QApplication app(argc, argv);

    {
        QString driverName = "QPSQL";

        //
        //  Set up information for driver and see if driver is available
        //
        qtDbName = "xpns" + theTime.toString("hhmmsszzz");
        QSqlDatabase db = QSqlDatabase::addDatabase(driverName, qtDbName);
        if (!QSqlDatabase::isDriverAvailable( driverName)) {
            QMessageBox::critical( 0, "Missing PostgreSQL Driver",
                                   "The Qt driver for PostgreSQL "
                                   + driverName
                                   + " is not installed.  You must install it before running this program",
                                   QMessageBox::Ok);
            db = QSqlDatabase();        //  reset to avoid warning
            return 0;
        }

        XpnsLogonDialog *xpnsLogonDialog = new XpnsLogonDialog( 0, qtDbName);
        xpnsLogonDialog->show();
        i_x = app.exec();

        qDebug() << "About to delete dialog";
        delete xpnsLogonDialog;
        qDebug() << "Dialog deleted, now clearing database";

        db = QSqlDatabase::database();  // clear connection to avoid error
    }  // end scope of logon dialog

    QSqlDatabase::removeDatabase(qtDbName);

    return i_x;
}

Looking at some of the comments in here brought back memories which were a long way from good. I’m sure many of you are freaked seeing the {} block enclosing the bulk of the program and the call to removeDatabase() outside of the block. When I saw the whole “clear connection to avoid error” comment it kind of all came back to me.

One thing I really hate about writing stuff like this for my blog, besides never getting paid for it,  is not being able to highlight code. There is probably some HTML markup tags which would let me set the background color, but the WordPress editor should make it a whole lot easier. Due to the way blog themes change the display of preformatted text I cannot even be sure line numbers will display.

The Logon Dialog

While I’m certainly not going to post all of the code in this series, we need to look at a couple more source files (kind of the worst) before we go too far in the discussion.

XpnsLogonDialog.h

/****************************************************************************
 * Originally created by Roland Hughes at Logikal Solutions.
 * Project is being released under GPL2 license.
 *
 * At some point in the future either Logikal Solutions or Roland Hughes
 * may elect to publish a book with this original source code in it.  If
 * the book is written it will be part of "The Minimum You Need to Know"
 * book series.
 ****************************************************************************/
#ifndef XPNSLOGONDIALOG_H
#define XPNSLOGONDIALOG_H

#include 
#include "ui_XpnsLogonDialog.h"
#include "Xpnsform.h"

class XpnsLogonDialog : public QDialog, public Ui::XpnsLogonDialog
{
    Q_OBJECT

public:
    XpnsLogonDialog( QWidget *parent, const QString &qtDbName);

    bool getConnectionStatus() { return m_connectionStatus;}
    int getTaxYear() { return m_tax_year;}
    bool useCalendarYear() { return m_calendarYear;}
    QString getActualDbName() {return m_actualDbName;}

private slots:
    void attempt_postgresql_logon();
    void on_userNameLineEdit_textChanged();

private:
    bool m_connectionStatus;
    void create_database( bool dbCreated);
    void ask_copy();
    void prompt_prior_year();
    void copy_prior_year( int year);
    bool  test_exists( int year);
    int m_tax_year;
    QString m_qtDbName;
    QString m_actualDbName;
    bool m_calendarYear;
    Xpnsform *xpnsForm;
};

#endif

Multiple Inheritance

Take a good look at that class definition. How many of you remember every class based on Qt and a UI file having to perform multiple inheritance? Come on, be honest! That all changed when the infamous “they” tried to make Qt usable by Java developers so they could finally abandon Swing. I and most others railed against that, but we lost. No, I won’t empty my colon on it again. You can buy a copy of this book if you want to read that rant. Let’s just say Java banned multiple inheritance and then had to bring it back with “interfaces.” They also banned the goto statement but the labeled break statement and a few other such things. The really bad parts in C and C++ existed for reasons. You can’t successfully remove the bad parts until you remove the reason for them.

Yes, if I don’t run out of time with this series I will rewrite the application from scratch using the more current approach to all things Qt. I believe you need to know where we came from because at some point you are going to encounter heritage code someone wants you to change without rewriting. If you don’t believe that you are either too young or haven’t been coding long enough. Every 1-2 years I get phone calls for a contract at a medical device company where they are looking for Qt 3 only. They have some device they want to make one small change in. If you rewrite they have to go through a very lengthy FDA approval process if the consultant just tweaks they can go through a much shorter and cheaper approval process. A rewrite means it is a “new device” while a change means it is an “updated/changed device.” No those aren’t the correct terms. I don’t remember the correct terms, but those work for the general audience.

Design due to QSqlDatabase “feature”

The convoluted design came about due to a “feature” with that version of Qt and Postgresql. In order to run like a mainframe/midrange application a database login dialog needed to pop up. Since I was going to release this as OpenSource I needed to have the information splash dialog pop up first so people too lazy to read a README.TXT would actually know something. First time users would be somewhat screwed. There was no way around having to manually enter categories. I didn’t want to ship with a predetermined set of categories. N year users would have it great because the login dialog would create the database for the tax year and offer to copy category information forward.

Our first “feature” reared its head during the first cut where I called the dialog exec() method. Even though QSqlDatabase was supposed to globally keep track of connections, when the dialog which created the database went away, so did the connection. In order to keep an entry you had to keep one reference alive. This left me with some really unenviable design choices.

  1. Pass a pointer to the db variable into the constructor of the dialog
  2. Pass string references for username and password and database year duplicating the connection code
  3. Derive from QApplication splitting all of the login functionality into methods within that class which would be executed when the event loop started.
  4. Doing something similar with a QObject class.

Our second and third “feature” reared its head when I didn’t have {} around the life of the db variable.  If one didn’t clear the database connection a runtime error would spit up in the terminal/debug window about object destroyed with active connection or something like that. Simply clearing the connection wasn’t enough, or at least it wasn’t instant enough. Calling removeDatabase() immediately after the clear with the db variable still in scope would cause more errors to be thrown about removing a database with an active connection.

Growing Pains Leave Warts

Yes, they were growing pains. Yes, most of these oddities have long since been cleaned up. Yes, this code still compiles and runs, I use it every time tax season approaches. Yes, you are going to encounter decade plus old code because it serves its purpose and rewriting isn’t free.

Many years ago I worked on a trading floor system for a stock exchange. The original “temporary” system was written in BASIC on a PDP 11 computer. Years later it was “temporarily” ported to the VAX hardware, then the Alpha, all the while the “permanent” trading floor system was being designed and a platform being chosen. This temporary system got pretty much rewritten when the U.S. stock market switched from trading in fractions to dollars and cents. That stock exchange got rid of its trading floor a few years ago. I’m told that “temporary” system went away with the trading floor but I would not be surprised to learn the automated portions of that system are what is running the exchange today.

Short Term “solutions” = Long Term Problems

Keep in mind that Y2K happened because “short term” solutions which made sense in the 1970s and early 1980s which were supposed to be replaced once storage and software became cheap enough were still in use near the year 2000. Read this page to learn what other Y2K like events are in your future.

Cast no stone at decade plus old code. We can always insult the ability of the developer but sometimes it is the ability of others which forced an ugly choice.

<Previous-part Next-Part>

Related posts:

Where Did My QDebug Output Go?

MOC Parse Error at “std”

KDE Neon – Distcc and Qt

CopperSpice Experiments

QtCreator – No qmlScene installed

So You Can’t Get Your Models to Work with QML?

QT Database book

How Far We’ve Come – Pt. 1

Occasionally life gives you a chance to look back at your past and to allow others to resoundingly embarrass you for it. This weekend is such an occasion. Yes, I have a party for my nephew to attend and I will visit my dad at least once if not twice, but, the weather isn’t going to cooperate enough that I can help my brother continue planting season. In an ordinary year we would be long since done, but this is no ordinary year. For the states of Illinois and Missouri it is going to be an extremely short corn crop. Yes, the cold wet weather is bad around here, but, at least this isn’t my field.

Pity yourself all you want just don’t do it out loud. There is always some poor bastard worse off than you and you had best remember that each and every day, not just Memorial Day weekend.

In that vein I’ve been doing some poking and experimenting. Obligations on my time will only be a few hours per day and so I’m just killing time until my new contract starts next week some time.

xpnsqt

Yes, I have heard some of you want me to get back to my Raspberry Pi series and we will eventually. We were basically at the stage I rarely have to do, configure for cross compile. If I’m going to jump through that hoop I might as well do something others want me to do, configure cross compile for Andriod. This way all of the pain is gotten out of the way at once. We should also have 2 test applications. The SerialKeypad application from the Raspberry Pi series and xpnsqt which is now actually called xpnsqt2 on my computers after I had to tweak it for Qt 5 compilation some time back.

Xpnsqt is something I actually use each year while getting ready for taxes. I was looking to learn Qt and had written a few “Hello World!” type applications, but nothing really substantial. I got onto this “How Far We’ve Come” topic because I can’t quite determine when I first wrote it. Honestly, I compile this thing and restore my expense database each time I switch distros or upgrade to different Qt version. For me it “just works” and other than the Qt 5 header file changes, I no touchy.

DOS Days

Had a nice little version of this expense tracker written with Lotus Approach. Years prior to that I had some DOS based program I wrote in C/C++ using the Greenleaf Database (GDB) Library and Greenleaf DataWindows (GDW) Library. Sorry I could not find a link for GDB but I did find a link for Patrick who lists it at the bottom of this page currently. DataWindows still has some mentions on-line with some more detailed than others.

Most of you will never have heard of these products because you are not older than dirt. DataWindows came out well before Microsoft shipped Windows 1.0 and, if memory serves, before OS/2 even had a hint of a presentation manager. Then the Clintons interfered with Janet Reno’s criminal investigation of Microsoft and Microsoft got the trademark right to “Windows” in all things software while the human species got royally screwed. Every week or so the little bitty company called Greenleaf had the 8000lb gorilla’s lawyers dropping nastygrams of intent to blah blah blah until all their cash was consumed by other lawyers and, eventually, DataWindows got dropped. Definitely “Medal of Honor” stuff there.

The Star Printer

Star NX-2420 printer imageAll the expense tracker did was group each expense under a category in a simple database. I would manually enter each expense in the nice little screen then I could run one of two reports: all expenses or tax deductible expenses. Each created an ASCII text file set up to print to a continuous form printer complete with page breaks, category totals and a grand total. I would send the file to my printer, it would grind away and I would take it to my tax professional.

Yes, I still have that Star NX-2420 printer. It still works as far as I know. I printed something with it a few months ago but the ink ribbon was getting dry and my box of continuous form paper is about as old as the printer. Somewhere in this office I still should have at least one if not two brand new sealed up ribbons for this printer.

I probably should have saved the 9-pin serial printer I sent to electronic recycling instead of this one during my last office purge. I’ve had this printer forever and it’s a tank, but I could print continuous form mailing labels on the other. It didn’t have a big rubber platen. Tractors on the serial printer could slide all the way together. The spool of continuous form labels used to friction feed via the rubber platen but it has gotten quite dry and the labels are a long way from fresh.

Preprinted Continuous Form Mailing Labels

Preprinted continuous form mailing labels imageI’m guessing I told myself nobody sold preprinted continuous form mailing labels anymore. Yes, I knew it was a lie when I said it, but I forced myself to believe it. Sigh. I still have a few hundred more of these which require hand writing now. Used to have a little C/C++ program I wrote under DOS and ported to OS/2 which would let me either manually enter addresses or open a text file in another portion of the screen to cut and past addresses in. I could click on the print button and it would automatically put the address in the right spot for this label. Yes, I know, most of you don’t find that useful, but you also do not write and ship books. I’ve been doing that and using these labels for decades.

Where We Were

Why all of this talk about things most of you are too young to have ever seen? Because you have to understand where we were in order to both appreciate and beat upon where we are. In the world of business printing we have went downhill exponentially. That simple thing of being able to feed a raw ASCII file to a printer with formfeed characters in it and have it do the right thing has been repeatedly lost. We will stumble on that while discussing xpnsqt.

Generic parallel port card imageSadly I haven’t been able to find my USB->Parallel cable in a number of years and I never think about replacing it because I know it is in one of my boxes of cables or drawers of “spare stuff.” If I was really into going down this rabbit hole I could pull the bracket off the generic parallel port card you see and stuff it in my current desktop hoping against all hope Linux still had the drivers for it.

Hopefully I won’t take too many memory lane diversions so the kids who are still wet behind the ears don’t lose interest. They are the ones who need to read things like this the most.

Next-part>

Related posts:

Where Did My QDebug Output Go?

MOC Parse Error at “std”

KDE Neon – Distcc and Qt

CopperSpice Experiments

QtCreator – No qmlScene installed

So You Can’t Get Your Models to Work with QML?

QT Database book

AGILE book