-
-
Save snow45/61cea39423b79c61e10f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------------------------------------------------- | |
# FailinSqliteDb.pro | |
#------------------------------------------------- | |
QT += core gui sql | |
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets | |
TARGET = FailingSQLiteDb | |
TEMPLATE = app | |
SOURCES += main.cpp\ | |
MainWindow.cpp \ | |
MyDatabase.cpp | |
HEADERS += MainWindow.h \ | |
MyDatabase.h | |
FORMS += MainWindow.ui | |
QMAKE_CXXFLAGS += -Werror -Wno-error=unused-local-typedefs -Wno-init-self -fno-exceptions -std=c++11 | |
/* | |
* main.cpp | |
*/ | |
#include "MainWindow.h" | |
#include <QApplication> | |
#include <QDebug> | |
int main(int argc, char *argv[]) | |
{ | |
QApplication a(argc, argv); | |
MainWindow w; | |
bool runApp2 = false; | |
for (int i = 1; i < argc; i++) | |
{ | |
if (strcmp(argv[i], "--help") == 0) | |
{ | |
qDebug() << "Command line options:"; | |
qDebug() << "--app2 Run in app2 mode"; | |
} | |
else if (strcmp(argv[i], "--app2") == 0) | |
runApp2 = true; | |
} | |
w.setRunMode(runApp2); | |
w.show(); | |
return a.exec(); | |
} | |
/* | |
* MainWindow.h | |
*/ | |
#ifndef MAINWINDOW_H | |
#define MAINWINDOW_H | |
#include <QMainWindow> | |
#include <MyDatabase.h> | |
namespace Ui { | |
class MainWindow; | |
} | |
class MainWindow : public QMainWindow | |
{ | |
Q_OBJECT | |
public: | |
explicit MainWindow(QWidget *parent = 0); | |
~MainWindow(); | |
void setRunMode(bool runApp2); | |
private slots: | |
void on_saveStuff_BTN_clicked(); | |
private: | |
Ui::MainWindow *ui; | |
MyDatabase * mDatabase1 = NULL; | |
MyDatabase * mDatabase2 = NULL; | |
bool mRunApp2 = false; | |
void openDatabase(); | |
}; | |
#endif // MAINWINDOW_H | |
/* | |
* MainWindow.cpp | |
*/ | |
#include "MainWindow.h" | |
#include "ui_MainWindow.h" | |
#include <QDir> | |
#include <QDebug> | |
#include <QImage> | |
static const QString FOLDER_1 = "MyApp1_DB"; | |
static const QString FOLDER_2 = "MyApp2_DB"; | |
MainWindow::MainWindow(QWidget *parent) : | |
QMainWindow(parent), | |
ui(new Ui::MainWindow) | |
{ | |
ui->setupUi(this); | |
QDir().mkpath(FOLDER_1); | |
QDir().mkpath(FOLDER_2); | |
openDatabase(); | |
} | |
MainWindow::~MainWindow() | |
{ | |
delete ui; | |
if(!mRunApp2) | |
delete mDatabase1; | |
delete mDatabase2; | |
} | |
void MainWindow::setRunMode(bool runApp2) | |
{ | |
mRunApp2 = runApp2; | |
} | |
void MainWindow::on_saveStuff_BTN_clicked() | |
{ | |
MyStuff mystuff; | |
mystuff.width = rand() % 20; | |
mystuff.height = rand() % 20; | |
mystuff.id = mDatabase2->getNextId("myid"); | |
mystuff.image = QImage(mystuff.width, mystuff.height, QImage::Format_RGB32); // Create random image | |
if(!mRunApp2) | |
{ | |
mDatabase1->addMyStuff(mystuff); | |
} | |
mDatabase2->addMyStuff(mystuff); | |
} | |
void MainWindow::openDatabase() | |
{ | |
mDatabase1 = new MyDatabase(); | |
mDatabase1->open(QDir().absolutePath() + '/' + FOLDER_1); | |
mDatabase2 = new MyDatabase(); | |
mDatabase2->open(QDir().absolutePath() + '/' + FOLDER_2); | |
} | |
/* | |
* MyDatabase.h | |
*/ | |
#ifndef MYDATABASE_H | |
#define MYDATABASE_H | |
#include <QObject> | |
#include <QImage> | |
#include <QSqlDatabase> | |
#include <QSqlQuery> | |
#include <QSqlTableModel> | |
struct MyStuff | |
{ | |
QString id; | |
QImage image; | |
int width; | |
int height; | |
}; | |
class MyDatabase : public QObject | |
{ | |
Q_OBJECT | |
public: | |
MyDatabase(); | |
~MyDatabase(); | |
void close(); | |
QString getNextId(const QString &id); | |
MyStuff *getMyStuff(const QString &id); | |
bool open(const QString &path); | |
signals: | |
public slots: | |
bool addMyStuff(const MyStuff &myStuff); | |
private: | |
QString getPathToImage(const QString &imageDir, const QString &id); | |
MyStuff *myStuffFromRecord(const QSqlRecord &record, const QString &imageDir); | |
QString mConnectionName = QString::number((ulong)this); | |
QString mPath; | |
QSqlDatabase mDb; | |
QSqlQuery* mQuery = NULL; | |
}; | |
#endif // MYDATABASE_H | |
/* | |
* MyDatabase.cpp | |
*/ | |
#include "MyDatabase.h" | |
#include <QApplication> | |
#include <QDebug> | |
#include <QSqlDriver> | |
#include <QSqlError> | |
#include <QSqlField> | |
#include <QSqlQuery> | |
#include <QSqlRecord> | |
#include <QSqlTableModel> | |
#include <sys/stat.h> | |
static const QString DB_NAME = "mystuff.db"; | |
static const QString SELECT_COMMAND = "SELECT * FROM stuffTable"; | |
MyDatabase::MyDatabase() : | |
mPath("") | |
{ | |
} | |
MyDatabase::~MyDatabase() | |
{ | |
close(); | |
} | |
void MyDatabase::close() | |
{ | |
delete mQuery; | |
mQuery = NULL; | |
//if the application is closing down, the connection is already gone and a segfault will occur | |
if (!QApplication::closingDown()) | |
{ | |
QSqlDatabase::removeDatabase(mConnectionName); | |
} | |
} | |
QString MyDatabase::getNextId(const QString& id) | |
{ | |
int sequenceNumber; | |
if (!mQuery->exec("SELECT max(substr(id,5,3)) FROM stuffTable")) | |
{ | |
qCritical() << Q_FUNC_INFO << "mQuery->exec" << mQuery->lastError(); | |
mQuery->finish(); | |
return QString(); | |
} | |
if (!mQuery->first()) | |
{ | |
qCritical() << Q_FUNC_INFO << "mQuery->first" << mQuery->lastError(); | |
mQuery->finish(); | |
return QString(); | |
} | |
if (mQuery->value(0).isNull()) | |
sequenceNumber = 1; | |
else | |
sequenceNumber = mQuery->value(0).toInt() + 1; | |
mQuery->finish(); | |
return id + QString::number(sequenceNumber).rightJustified(3, '0'); | |
} | |
MyStuff* MyDatabase::getMyStuff(const QString& id) | |
{ | |
if (!mQuery->exec(SELECT_COMMAND + " WHERE id='" + QString(id)) + "'") | |
{ | |
qCritical() << Q_FUNC_INFO << "mQuery->exec: " << mQuery->lastError(); | |
mQuery->finish(); | |
return NULL; | |
} | |
if (!mQuery->first()) | |
{ | |
qCritical() << Q_FUNC_INFO << "mQuery->first:" << mQuery->lastError(); | |
mQuery->finish(); | |
return NULL; | |
} | |
MyStuff* mystuff = myStuffFromRecord(mQuery->record(), mPath); | |
mQuery->finish(); | |
return mystuff; | |
} | |
bool MyDatabase::open(const QString& path) | |
{ | |
mPath = path; | |
//create connection to database | |
mDb = QSqlDatabase::addDatabase( "QSQLITE", mConnectionName ); | |
mDb.setDatabaseName( path + '/' + DB_NAME ); | |
// mDb.setConnectOptions("QSQLITE_ENABLE_SHARED_CACHE"); | |
if( !mDb.open() ) | |
{ | |
qCritical() << Q_FUNC_INFO << "mDb->open:" << mDb.lastError(); | |
return false; | |
} | |
//for some reason the umask doesn't seem to work with QSqlDatabase | |
chmod( mDb.databaseName().toLocal8Bit().constData(), 0666 ); | |
mQuery = new QSqlQuery( mDb ); | |
bool result = mQuery->exec( "CREATE TABLE IF NOT EXISTS stuffTable (" | |
"id TEXT PRIMARY KEY," | |
"width INTEGER," | |
"height INTEGER" | |
")" ); | |
if( !result ) | |
{ | |
qCritical() << Q_FUNC_INFO << "mQuery->exec:" << mQuery->lastError(); | |
return false; | |
} | |
mQuery->finish(); | |
return true; | |
} | |
bool MyDatabase::addMyStuff(const MyStuff& myStuff) | |
{ | |
QSqlTableModel table(NULL, mDb); | |
table.setTable("stuffTable"); | |
QSqlRecord record = mDb.record("stuffTable"); | |
record.setValue("id", myStuff.id); | |
record.setValue("width", myStuff.width); | |
record.setValue("height", myStuff.height); | |
if (!table.insertRecord(-1, record)) | |
{ | |
qCritical() << Q_FUNC_INFO << "table.insertRecord:" << table.lastError(); | |
return false; | |
} | |
myStuff.image.save(getPathToImage(mPath, myStuff.id), "PNG"); | |
return true; | |
} | |
QString MyDatabase::getPathToImage(const QString& imageDir, const QString& id) | |
{ | |
return imageDir + '/' + id + ".png"; | |
} | |
MyStuff* MyDatabase::myStuffFromRecord(const QSqlRecord& record, const QString& imageDir) | |
{ | |
MyStuff* myStuff = new MyStuff; | |
myStuff->id = record.value("id").toString(); | |
myStuff->width = record.value("width").toInt(); | |
myStuff->height = record.value("height").toInt(); | |
myStuff->image = QImage(getPathToImage(imageDir, myStuff->id)); | |
return myStuff; | |
} | |
/* | |
* 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>400</width> | |
<height>300</height> | |
</rect> | |
</property> | |
<property name="windowTitle"> | |
<string>MainWindow</string> | |
</property> | |
<widget class="QWidget" name="centralWidget"> | |
<widget class="QPushButton" name="saveStuff_BTN"> | |
<property name="geometry"> | |
<rect> | |
<x>130</x> | |
<y>130</y> | |
<width>85</width> | |
<height>27</height> | |
</rect> | |
</property> | |
<property name="text"> | |
<string>Save Stuff</string> | |
</property> | |
</widget> | |
</widget> | |
<widget class="QMenuBar" name="menuBar"> | |
<property name="geometry"> | |
<rect> | |
<x>0</x> | |
<y>0</y> | |
<width>400</width> | |
<height>27</height> | |
</rect> | |
</property> | |
</widget> | |
<widget class="QToolBar" name="mainToolBar"> | |
<attribute name="toolBarArea"> | |
<enum>TopToolBarArea</enum> | |
</attribute> | |
<attribute name="toolBarBreak"> | |
<bool>false</bool> | |
</attribute> | |
</widget> | |
<widget class="QStatusBar" name="statusBar"/> | |
</widget> | |
<layoutdefault spacing="6" margin="11"/> | |
<resources/> | |
<connections/> | |
</ui> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment