Page 1 of 2

Falco's QT Programs

Posted: Mon Sep 21, 2009 9:58 am
by Falco Girgis
I'm starting this topic thanks to my Software Design class (CPE353), where we write QT programs. I must admit that I almost never pay attention in there. For folks like us who are used to game development, this shit is cake. But I will also admit that I think QT is by far the most impressive and versatile GUI development kit that I have seen. Sorry WxWidgets, sorry .NET. QT compiles identically on a PC, Mac, Linux, and even smartphones. The KDE desktop environment for Ubuntu/Kubuntu was written in it.

So without further ado, here it is. The assignment was to make a simple GUI-based encryptor that works by simply shifting letters. I have tested it on Kubuntu and Windows XP, and it is definitely identical:

main.cpp

Code: Select all

/*
    Falco Girgis
    CPE353
    QT Project #1
    9/18/09
*/

#include <QApplication>
#include "EncryptDialog.h"

int main(int argc, char *argv[]) {

    QApplication application(argc, argv);
    //Instantiate the EncryptDialog
    EncryptDialog encryptDialog;
    //Show it
    encryptDialog.show();
    return application.exec();
}
encryptdialog.h

Code: Select all

#ifndef ENCRYPTDIALOG_H
#define ENCRYPTDIALOG_H

#include <QDialog>
#include <QLineEdit>
#include <QLabel>
#include <QSpinBox>

#define MAX_LINE_LENGTH 26
enum ENCRYPTION_STATE { STATE_ENCRYPT, STATE_DECRYPT };

class EncryptDialog: public QDialog {
    Q_OBJECT

public:
    EncryptDialog();

private:
    /*
      Member pointers are for parts of the dialog that need to be
      referred to outside of the constructor for signals and slots.
     */
    QSpinBox *encryptionKeyInput;
    QLineEdit *plainTextInput;
    QLineEdit *cipherTextInput;
    QPushButton *switchButton;
    QPushButton *clearButton;
    QPushButton *quitButton;
    QLabel *encryptKeyLabel;

    ENCRYPTION_STATE state;
    int key;

private slots:
    void Clear();
    void SwitchMode();
    void CipherTextChanged(const QString &string);
    void PlainTextChanged(const QString &string);
    void KeyChanged(int p_key);


};

#endif
encryptdialog.cpp

Code: Select all

#include "EncryptDialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QDebug>
#include <QTextCodec>

/*
  Default constructor for our EncryptDialog window
  */
EncryptDialog::EncryptDialog(): encryptionKeyInput(NULL), plainTextInput(NULL), cipherTextInput(NULL),
switchButton(NULL), clearButton(NULL), quitButton(NULL),state(STATE_ENCRYPT), key(0)  {
    //allocating layouts on the heap
    //Ties mainLayout and everything tied to it to "this" (which in our case would be on the stack.
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    QHBoxLayout *encryptionLayout = new QHBoxLayout();
    QGridLayout *plainCipherTextLayout = new QGridLayout();
    QHBoxLayout *buttonLayout = new QHBoxLayout();

    setWindowTitle(tr("Dialog"));

    //Set up mainLayout
    mainLayout->addLayout(encryptionLayout);
    mainLayout->addStretch();
    mainLayout->addLayout(plainCipherTextLayout);
    mainLayout->addStretch();
    mainLayout->addLayout(buttonLayout);

    //Set up encryptionLayout
    encryptKeyLabel = new QLabel(tr("Encryption Key"));
    encryptionKeyInput = new QSpinBox();
    encryptionKeyInput->setMaximum(25);
    encryptionLayout->addWidget(encryptKeyLabel);
    encryptionLayout->addWidget(encryptionKeyInput);

    //Set up Encrypt/Decrypt layout using a grid
    QLabel *plainTextLabel = new QLabel(tr("Plaintext"));
    plainTextInput = new QLineEdit();
    plainTextInput->setValidator( new QRegExpValidator( QRegExp( "[a-z]+"), this));
    plainTextInput->setMaxLength(MAX_LINE_LENGTH);
    QLabel *cipherTextLabel = new QLabel(tr("Ciphertext"));
    cipherTextInput = new QLineEdit();
    cipherTextInput->setValidator( new QRegExpValidator( QRegExp( "[a-z]+"), this));
    cipherTextInput->setMaxLength(MAX_LINE_LENGTH);
    cipherTextInput->setFrame(false);
    cipherTextInput->setReadOnly(true);
    plainCipherTextLayout->addWidget(plainTextLabel, 0, 0);
    plainCipherTextLayout->addWidget(plainTextInput, 0, 1);
    plainCipherTextLayout->addWidget(cipherTextLabel, 1, 0);
    plainCipherTextLayout->addWidget(cipherTextInput, 1, 1);

    //Set up layout for buttons
    switchButton = new QPushButton(tr("Switch to Decryption Mode"));
    switchButton->setDefault(true);
    clearButton = new QPushButton(tr("Clear"));
    quitButton = new QPushButton(tr("Quit"));
    buttonLayout->addWidget(switchButton);
    buttonLayout->addStretch();
    buttonLayout->addWidget(clearButton);
    buttonLayout->addStretch();
    buttonLayout->addWidget(quitButton);

    //Connect our signals and slots
    connect(quitButton, SIGNAL(clicked()), this, SLOT(accept()));
    connect(clearButton, SIGNAL(clicked()), this, SLOT(Clear()));
    connect(switchButton, SIGNAL(clicked()), this, SLOT(SwitchMode()));
    connect(plainTextInput, SIGNAL(textChanged(const QString&)), this, SLOT(PlainTextChanged(const QString&)));
    connect(cipherTextInput, SIGNAL(textChanged(const QString&)), this, SLOT(CipherTextChanged(const QString&)));
    connect(encryptionKeyInput, SIGNAL(valueChanged(int)), this, SLOT(KeyChanged(int)));
}

/*
  Slot called when the clear button is pressed
  */
void EncryptDialog::Clear() {
    plainTextInput->clear();
    cipherTextInput->clear();
}

/*
  Slot called when the Switch to Encryption/Decryption mode button has been pressed
  */
void EncryptDialog::SwitchMode() {
    switch(state) {
    case STATE_ENCRYPT:
        state = STATE_DECRYPT;
        plainTextInput->setReadOnly(true);
        plainTextInput->setFrame(false);
        cipherTextInput->setReadOnly(false);
        cipherTextInput->setFrame(true);
        cipherTextInput->setFocus();
        switchButton->setText(tr("Switch to Encryption Mode"));
        encryptKeyLabel->setText(tr("Decryption Key"));
        break;
    case STATE_DECRYPT:
        state = STATE_ENCRYPT;
        plainTextInput->setReadOnly(false);
        plainTextInput->setFrame(true);
        plainTextInput->setFocus();
        cipherTextInput->setReadOnly(true);
        cipherTextInput->setFrame(false);
        switchButton->setText(tr("Switch to Decryption Mode"));
        encryptKeyLabel->setText(tr("Encryption Key"));
        break;
    default:
        break;
    }
}

/*
  Slot called when the key spinButton's value has been changed
  */
void EncryptDialog::KeyChanged(int p_key) {
    key = p_key;

    switch(state) {
    case STATE_ENCRYPT:
        PlainTextChanged(plainTextInput->text());
        break;
    case STATE_DECRYPT:
        CipherTextChanged(cipherTextInput->text());
        break;
    }
}

/*
  Slot called when the cipherTextEdit string has changed

  Note about shifting:
  I probably could have been more efficient about this and used
  unicode rather than changing from QString to std::string to char array.
  I learned a lot about string conversions from ascii to unicode this way,
  though.
  */
void EncryptDialog::CipherTextChanged(const QString &string) {
    if(state != STATE_DECRYPT) return;

    QString newString;
    std::string midString;
    midString = string.toStdString();
    char *midderString = (char *)midString.c_str();

    for(unsigned int i = 0; i < midString.length(); ++i) {
        midderString[i] = (midderString[i] - 'a' - key)%26+'a';
        if(midderString[i] < 'a') midderString[i] = 'z'+1-('a'-midderString[i]);
    }

    midString = midderString;
    newString = QString::fromStdString(midString);


    plainTextInput->setText(newString);
}

/*
  Slot called when the plainTextEdit string has changed
  */
void EncryptDialog::PlainTextChanged(const QString &string) {
    if(state != STATE_ENCRYPT) return;
    QString newString;
    std::string midString;
    midString = string.toStdString();
    char *midderString = (char *)midString.c_str();

    for(unsigned int i = 0; i < midString.length(); ++i) {
        midderString[i] = (midderString[i] - 'a' + key)%26+'a';
    }

    midString = midderString;
    newString = QString::fromStdString(midString);

    cipherTextInput->setText(newString);

}
Attached is a screenshot of it running on Windows

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 11:46 am
by captjack
Has trolltech relaxed their sphincter around their license model? I seem to recall a battle whereby the license was commercial and prevented its inclusion in software covered under the GPL. I haven't touched it since. (Well, that's primarily because I was never interested in what it offered. I may have to re-examine it, now.)


-capt jack

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 12:49 pm
by hurstshifter
I'm really glad you posted this as I've recently begun researching a good toolkit for building gui apps. Has any ever used GTK+ as well as Qt? Any pros or cons for either? I've heard great things about both.

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 1:08 pm
by K-Bal
captjack wrote:Has trolltech relaxed their sphincter around their license model? I seem to recall a battle whereby the license was commercial and prevented its inclusion in software covered under the GPL. I haven't touched it since. (Well, that's primarily because I was never interested in what it offered. I may have to re-examine it, now.)
I think its LGPL since v4.5.

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 1:53 pm
by M_D_K
oh sweet, it's the Caesar cipher aka Caesar shift :)

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 1:56 pm
by Falco Girgis
captjack wrote:Has trolltech relaxed their sphincter around their license model? I seem to recall a battle whereby the license was commercial and prevented its inclusion in software covered under the GPL. I haven't touched it since. (Well, that's primarily because I was never interested in what it offered. I may have to re-examine it, now.)


-capt jack
Yeah, they chilled out. It's LGPL now.

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 2:00 pm
by captjack
GyroVorbis wrote:
captjack wrote:Has trolltech relaxed their sphincter around their license model? I seem to recall a battle whereby the license was commercial and prevented its inclusion in software covered under the GPL. I haven't touched it since. (Well, that's primarily because I was never interested in what it offered. I may have to re-examine it, now.)


-capt jack
Yeah, they chilled out. It's LGPL now.

Nice! I think I might take a stroll through some tutorials.

Re: Falco's QT Programs

Posted: Mon Sep 21, 2009 2:23 pm
by Falco Girgis
I'm not a big fan of GPL myself, I wouldn't be so enthusiastic had they not.

Re: Falco's QT Programs

Posted: Mon Oct 19, 2009 3:45 pm
by imran.hoshimi
Can we use the Qt toolkit with VC6 to build the app? I went to their website and found that they also provide their own IDE and designer.

Re: Falco's QT Programs

Posted: Mon Oct 19, 2009 4:23 pm
by avansc
QT does not even install on OSX Snow Leopard

Re: Falco's QT Programs

Posted: Mon Oct 19, 2009 4:36 pm
by Falco Girgis
avansc wrote:QT does not even install on OSX Snow Leopard
You've got to be shitting me. Are you serious?
Can we use the Qt toolkit with VC6 to build the app? I went to their website and found that they also provide their own IDE and designer.
Not sure about VC6, but it has project templates for Visual Studio 2008 and Eclipse.

Re: Falco's QT Programs

Posted: Mon Oct 19, 2009 4:41 pm
by avansc
GyroVorbis wrote:
avansc wrote:QT does not even install on OSX Snow Leopard
You've got to be shitting me. Are you serious?
Can we use the Qt toolkit with VC6 to build the app? I went to their website and found that they also provide their own IDE and designer.
Not sure about VC6, but it has project templates for Visual Studio 2008 and Eclipse.

yeppers. i tried to get it installed. keeps failing at validating packages. its a documented problem.

Re: Falco's QT Programs

Posted: Mon Oct 19, 2009 4:59 pm
by M_D_K
It's cause Apple wants you to use Cocoa directly, those assholes.

Re: Falco's QT Programs

Posted: Mon Nov 23, 2009 8:50 pm
by Falco Girgis
Just finished my final project in QT (Software Engineering) in CPE353. We were assigned to create a front-end GUI that interacts with a SQL database via QT's SQLite extensions. The database is supposed to be some sort of bank account emulator. Here's the source and a screenshot. Tested on my PC with Windows XP, Kendall's with Windows 7, my Kubuntu box, and the Solaris boxes at the university. Platform independent as hell.

main:

Code: Select all

/*
  Falco Girgis
  CPE353
  Project 05
   11/23/09
 */
#include <QtGui/QApplication>
#include <QtSql>
#include <QTableView>
#include <QDebug>
#include "mainwindow.h"

int main(int argc, char *argv[]) {

    //Load database file
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("bank.db");
    db.setHostName("localhost");

    if(!db.open()) {
        qDebug() << db.lastError();
        qDebug() << "Error: Unable to connect";
    }

    QApplication a(argc, argv);

    BankDialog w;
    w.show();
    return a.exec();
}
maindialog.h

Code: Select all

/*
  Falco Girgis
  CPE353
  Project 05
   11/23/09
 */

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QDialog>
#include <QLabel>
#include <QSpinBox>
#include <QRadioButton>
#include <QLineEdit>
#include <QDateEdit>
#include <QtSql>
#include <QTableView>

class BankDialog: public QDialog {
    Q_OBJECT
public:
    BankDialog();

private:
    QPushButton *submitButton;
    QPushButton *quitButton;
    QLabel      *currentBalance;
    QDateEdit    *dateEdit;
    QRadioButton *depositRadioButton;
    QRadioButton *withdrawRadioButton;
    QLineEdit    *descriptionLineEdit;
    QLineEdit    *amountLineEdit;
    QSqlQueryModel *model;


private slots:
    bool AddTuple();

};

#endif // MAINWINDOW_H
maindialog.cpp

Code: Select all

/*
  Falco Girgis
  CPE353
  Project 05
   11/23/09
 */


#include "mainwindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QGroupBox>
#include <QSpinBox>
#include <QDateEdit>
#include <QtSql>
#include <QTableView>
#include <QDebug>

BankDialog::BankDialog() {
    QVBoxLayout *mainLayout;
    QHBoxLayout *controlLayout;
    QHBoxLayout *buttonLayout;
    QTableView *view;
    QSqlQuery *y;

    view = new QTableView();
    buttonLayout = new QHBoxLayout();
    controlLayout = new QHBoxLayout();
    mainLayout = new QVBoxLayout(this);

    setWindowTitle(tr("p05"));

    model = new QSqlQueryModel();
    model->setQuery("SELECT * from accounts");
    view->setModel(model);

    QString balance;
    balance.append("Current Balance is $");
    y = new QSqlQuery("select SUM(amount) FROM accounts");
    if(y->next()) {
        balance.append(y->value(0).toString());
    }
    currentBalance = new QLabel(balance);
    currentBalance->setAlignment(Qt::AlignHCenter);
    //set up mainLayout
    mainLayout->addWidget(view);
    mainLayout->addStretch();
    mainLayout->addWidget(currentBalance);
    mainLayout->addStretch();
    mainLayout->addLayout(controlLayout);
    mainLayout->addStretch();
    mainLayout->addLayout(buttonLayout);

    //set up control layout
    dateEdit = new QDateEdit();
    QHBoxLayout *transactionDateLayout = new QHBoxLayout();
    transactionDateLayout->addWidget(dateEdit);
    QGroupBox *transactionDateGroup = new QGroupBox(tr("Transaction Date"));
    transactionDateGroup->setLayout(transactionDateLayout);
    controlLayout->addWidget(transactionDateGroup);
    controlLayout->addStretch();

    depositRadioButton = new QRadioButton(tr("Deposit"));
    depositRadioButton->setChecked(true);
    withdrawRadioButton = new QRadioButton(tr("Withdrawal"));
    QVBoxLayout *transactionTypeLayout = new QVBoxLayout();
    transactionTypeLayout->addWidget(depositRadioButton);
    transactionTypeLayout->addWidget(withdrawRadioButton);
    QGroupBox *transactionTypeGroup = new QGroupBox(tr("Transaction Type"));
    transactionTypeGroup->setLayout(transactionTypeLayout);
    controlLayout->addWidget(transactionTypeGroup);
    controlLayout->addStretch();

    descriptionLineEdit = new QLineEdit();
    QHBoxLayout *descriptionLayout = new QHBoxLayout();
    descriptionLayout->addWidget(descriptionLineEdit);
    QGroupBox *descriptionGroupBox = new QGroupBox(tr("Description"));
    descriptionGroupBox->setLayout(descriptionLayout);
    controlLayout->addWidget(descriptionGroupBox);
    controlLayout->addStretch();

    amountLineEdit = new QLineEdit();
    amountLineEdit->setValidator(new QRegExpValidator(QRegExp("[1-9]+"), this));
    QHBoxLayout *amountLayout = new QHBoxLayout();
    amountLayout->addWidget(amountLineEdit);
    QGroupBox *amountGroupBox = new QGroupBox(tr("Amount"));
    amountGroupBox->setLayout(amountLayout);
    controlLayout->addWidget(amountGroupBox);

    //set up buttonLayout
    submitButton = new QPushButton(tr("Submit"));
    buttonLayout->addWidget(submitButton);
    buttonLayout->addStretch();
    quitButton = new QPushButton(tr("Quit"));
    buttonLayout->addWidget(quitButton);

    //set up signals and slots
    connect(quitButton, SIGNAL(clicked()), this, SLOT(accept()));
    connect(submitButton, SIGNAL(clicked()), this, SLOT(AddTuple()));

}

/*
  Constructs a query from the given user input and adds an entry to the database.
  The modelview and current balance are both updated.
  Returns 0 if no input has been entered in the description/amount fields.
*/
bool BankDialog::AddTuple() {
   if(descriptionLineEdit->text().length() <= 0) return 0;
   if(amountLineEdit->text().length() <= 0) return 0;

   QString query;
   QSqlQuery q, y;
   query.append("INSERT INTO accounts VALUES('");
   query.append(dateEdit->text());
   query.append("','");
   if(depositRadioButton->isChecked())
   query.append("deposit");
   else query.append("withdrawal");
   query.append("','");
   query.append(descriptionLineEdit->text());
   query.append("',");
   if(withdrawRadioButton->isChecked())
   query.append("-");
   query.append(amountLineEdit->text());
   query.append(")");
   q.exec(query);
   model->setQuery("SELECT * from accounts");

   QString balance;
    balance.append("Current Balance is $");
    y.exec("select SUM(amount) FROM accounts");
    if(y.next()) {
        balance.append(y.value(0).toString());
    }
    currentBalance->setText(balance);


   return 1;
}
and now the rest of the semester (other than studying for finals), I am officially freeeeee!!

Re: Falco's QT Programs

Posted: Mon Nov 23, 2009 10:02 pm
by Innerscope
avansc wrote:QT does not even install on OSX Snow Leopard
I installed it on my machine. (10.6.2)
Although, I do get the warning from "qglobal.h" when I build:

Code: Select all

#  if (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_6)
#    warning "Support for this version of Mac OS X is still preliminary"
#  endif