dev/qt/ PgenPasswordGeneratorVersion1
Start a new default QtWidgets application.
Go to the Ui designer. Create 5 line edit boxes and 5 labels. Select all and arrange in grid. The top box is the secret, so has echo mode
set to Password
. The next input is the main input, leave this as is. The next three line edits are for output, so make them read-only. Set ids to "secretInput"
, "mainInput"
, "mainOutput"
, "testShaOutput"
, and "testMd5Output"
respectively.
Now the test outputs shouldn't be selectable, so set focusPolicy to NoFocus
for these.
MainWindow.h
We need to add two slots
private slots:
void handle_change() const;
void handle_enter() const;
and two functions to handle updating the contents of the output boxes and copying to the clipboard. (The copy could be put directly in the slot handler, but in general you would duplicate code if two or more functions wanted to copy the output to the clipboard, similarly for the process function, which is also called from the constructor.)
private:
void process() const;
void copy_output() const;
MainWindow.cpp
Headers
#include <QCryptographicHash>
#include <QClipboard>
Constructor
ui->setupUi(this);
// handle change
QObject::connect(ui->secretInput,&QLineEdit::textChanged,this,&MainWindow::handle_change);
QObject::connect(ui->mainInput,&QLineEdit::textChanged,this,&MainWindow::handle_change);
// handle enter
QObject::connect(ui->secretInput,&QLineEdit::returnPressed,this,&MainWindow::handle_enter);
QObject::connect(ui->mainInput,&QLineEdit::returnPressed,this,&MainWindow::handle_enter);
QObject::connect(ui->mainOutput,&QLineEdit::returnPressed,this,&MainWindow::handle_enter);
ui->secretInput->setText("boing");
ui->mainInput->setText("snarf");
process();
Slots
void MainWindow::handle_change() const
{
process();
}
void MainWindow::handle_enter() const
{
copy_output();
}
Hash helper functions
static QString sha(QString x) {
QCryptographicHash sha_hash(QCryptographicHash::Sha256);
sha_hash.addData(x.toUtf8());
QByteArray result = sha_hash.result();
QByteArray b64 = result.toBase64();
QString b64_str(b64);
QString final = b64_str.replace("/","#").replace("+","@").left(16);
return final;
}
static QString md5(QString x) {
QCryptographicHash md5_hash(QCryptographicHash::Md5);
md5_hash.addData(x.toUtf8());
QByteArray result = md5_hash.result();
QByteArray hex = result.toHex();
QByteArray b64 = hex.toBase64();
QString b64_str(b64);
QString final = b64_str.replace("/","#").replace("+","@").left(16);
return final;
}
Now from back when these were command line scripts, I've always used the shorthands j
for the md5 version and jj
for the later sha version. (j for John's password generator, I think.) This is where you could add code to handle non-default schemas, but these days I don't bother changing it. It was just some extra flexibility that seemed to make sense when I wrote the original scripts.
// md5 version
static QString jj(QString input, QString secret) {
return sha(input+secret);
}
// sha version
static QString j(QString input, QString secret) {
return md5(input+secret+"\n");
}
And finally the process and copy methods
void MainWindow::process() const
{
// get text from secret and input
// form input strings
QString secret(ui->secretInput->text());
QString main_input(ui->mainInput->text());
// hash data (note we reuse the sha)
QString sha_output = jj(main_input,secret);
QString sha_test_output = jj(QString("MrFlibble"),secret);
QString md5_test_output = j(QString("MrFlibble"),secret);
ui->mainOutput->setText(sha_output);
ui->testShaOutput->setText(sha_test_output);
ui->testMd5Output->setText(md5_test_output);
}
void MainWindow::copy_output() const
{
QString output = ui->mainOutput->text();
QGuiApplication::clipboard()->setText(output);
}
and that's it.
For reference, here is the Xml for the mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>21</x>
<y>16</y>
<width>186</width>
<height>126</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Secret</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="secretInput">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Input</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mainInput"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Output</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="mainOutput">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Test SHA</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="testShaOutput">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Test MD5</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="testMd5Output">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<tabstops>
<tabstop>secretInput</tabstop>
<tabstop>mainInput</tabstop>
<tabstop>mainOutput</tabstop>
<tabstop>testShaOutput</tabstop>
<tabstop>testMd5Output</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>