commit
5c6e609962
|
|
@ -0,0 +1,73 @@
|
||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
QT += core gui
|
||||||
|
QT += sql
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
# any Qt feature that has been marked deprecated (the exact warnings
|
||||||
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
# deprecated API in order to know how to port your code away from it.
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
|
# You can also make your code fail to compile if it uses deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
dbunit.cpp \
|
||||||
|
main.cpp \
|
||||||
|
mainwindow.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
dbunit.h \
|
||||||
|
mainwindow.h
|
||||||
|
|
||||||
|
# Default rules for deployment.
|
||||||
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
resource.qrc
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
#include "dbunit.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QSqlError>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
|
||||||
|
DBUnit::DBUnit()
|
||||||
|
{
|
||||||
|
db_ins = QSqlDatabase::addDatabase("QSQLITE", "datas");
|
||||||
|
db_ins.setDatabaseName("./core.db");
|
||||||
|
if (!db_ins.open())
|
||||||
|
qDebug() << db_ins.lastError();
|
||||||
|
|
||||||
|
init_basic_tables(db_ins);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery
|
||||||
|
DBUnit::getQuery() const
|
||||||
|
{
|
||||||
|
return QSqlQuery(db_ins);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DBUnit::init_basic_tables(QSqlDatabase& db_ins)
|
||||||
|
{
|
||||||
|
QSqlQuery q(db_ins);
|
||||||
|
|
||||||
|
q.prepare("create table if not exists country_information( "
|
||||||
|
"cid integer auto_increment primary key, "
|
||||||
|
"name text not null, describe text)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists publishing_information( "
|
||||||
|
"pid integer auto_increment primary key, name text not null, "
|
||||||
|
"country integer not null, describe text, "
|
||||||
|
"constraint fk_pi foreign key (country) references country_information(cid) "
|
||||||
|
"on update cascade on delete cascade)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists authors_information( "
|
||||||
|
"author_id integer auto_increment primary key, name text not null, "
|
||||||
|
"country integer not null, describe text, "
|
||||||
|
"constraint fk_ai foreign key (country) references country_information(cid) "
|
||||||
|
"on delete cascade on update cascade)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists books_information("
|
||||||
|
"book_id integer auto_increment primary key,isbn text not null,"
|
||||||
|
"name text not null,publishing integer not null,author integer not null,"
|
||||||
|
"author2 integer not null,language text,time text,abstract text,image blob,"
|
||||||
|
"constraint fk_bi0 foreign key (publishing) references publishing_information on delete cascade on update cascade,"
|
||||||
|
"constraint fk_bi1 foreign key (author) references authors_information on delete cascade on update cascade,"
|
||||||
|
"constraint fk_bi1 foreign key (author2) references authors_information on delete cascade on update cascade)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists groups_records("
|
||||||
|
"record_id integer auto_increment primary key,"
|
||||||
|
"name text not null)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists labels_records( "
|
||||||
|
"record_id integer auto_increment primary key, "
|
||||||
|
"name text not null, describe text)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists books_manage("
|
||||||
|
"record_id integer auto_increment primary key,"
|
||||||
|
"book integer not null,`group` integer not null,"
|
||||||
|
"constraint fk_bm0 foreign key (book) references books_information(record_id) on delete cascade on update cascade,"
|
||||||
|
"constraint fk_bm1 foreign key (`group`) references groups_records(record_id) on delete cascade on update cascade)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare("create table if not exists book_labels_manage( "
|
||||||
|
"record_id integer auto_increment primary key, "
|
||||||
|
"book integer not null,label integer not null, "
|
||||||
|
"constraint fk_blm0 foreign key (book) references books_information(book_id) on delete cascade on update cascade,"
|
||||||
|
"constraint fk_blm1 foreign key (label) references labels_records(record_id) on delete cascade on update cascade)");
|
||||||
|
if (!q.exec()) {
|
||||||
|
qDebug() << q.lastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef DBUNIT_H
|
||||||
|
#define DBUNIT_H
|
||||||
|
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
|
||||||
|
class DBUnit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DBUnit();
|
||||||
|
|
||||||
|
QSqlQuery getQuery() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSqlDatabase db_ins;
|
||||||
|
|
||||||
|
void init_basic_tables(QSqlDatabase& db_ins);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DBUNIT_H
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "dbunit.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
// MainWindow w;
|
||||||
|
// w.show();
|
||||||
|
|
||||||
|
// DBUnit t;
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#define GROUP_ITEMSCOUNT Qt::UserRole + 1
|
||||||
|
#define GROUP_TITLE Qt::DisplayRole
|
||||||
|
#define GROUP_COVER0 Qt::DecorationRole
|
||||||
|
#define GROUP_COVER1 Qt::UserRole + 3
|
||||||
|
#define GROUP_COVER2 Qt::UserRole + 4
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget* parent)
|
||||||
|
: QMainWindow(parent), groups_view(new QListView(this)),
|
||||||
|
groups_list(new QStandardItemModel(this)), items_view(new QListView(this)),
|
||||||
|
items_list(new QStandardItemModel(this))
|
||||||
|
{
|
||||||
|
groups_view->setModel(groups_list);
|
||||||
|
items_view->setModel(items_list);
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
auto splitter = new QSplitter(this);
|
||||||
|
setCentralWidget(splitter);
|
||||||
|
|
||||||
|
splitter->addWidget(groups_view);
|
||||||
|
splitter->addWidget(items_view);
|
||||||
|
|
||||||
|
groups_list->setHorizontalHeaderLabels(QStringList() << "数量"
|
||||||
|
<< "名称");
|
||||||
|
groups_view->setItemDelegate(new GroupDisplayDelegate);
|
||||||
|
groups_view->setMovement(QListView::Free);
|
||||||
|
init_groups_list(groups_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MainWindow::init_groups_list(QStandardItemModel* model)
|
||||||
|
{
|
||||||
|
model->removeRows(0, model->rowCount());
|
||||||
|
|
||||||
|
QRandomGenerator gen;
|
||||||
|
for (int idx = 0; idx < 200; ++idx) {
|
||||||
|
QList<QStandardItem*> row;
|
||||||
|
row << new QStandardItem("无名集合0");
|
||||||
|
row.last()->setData(gen.generate() % 100, GROUP_ITEMSCOUNT);
|
||||||
|
|
||||||
|
model->appendRow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupDisplayDelegate::GroupDisplayDelegate()
|
||||||
|
: default_cover(new QIcon(":/imgs/default/cover.jpg"))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupDisplayDelegate::~GroupDisplayDelegate()
|
||||||
|
{
|
||||||
|
delete default_cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget*
|
||||||
|
GroupDisplayDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
auto font = option.font;
|
||||||
|
font.setPointSize(26);
|
||||||
|
auto ins = new QLineEdit(parent);
|
||||||
|
ins->setFont(font);
|
||||||
|
return ins;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupDisplayDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
static_cast<QLineEdit*>(editor)->setText(index.data().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupDisplayDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
model->setData(index, static_cast<QLineEdit*>(editor)->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto text_rect = [](const QRect& whole_rect, double font_height) -> QRectF {
|
||||||
|
return QRectF(whole_rect.left() + 145, whole_rect.top() + 20, whole_rect.width() - 165, font_height);
|
||||||
|
};
|
||||||
|
void
|
||||||
|
GroupDisplayDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItem new_ = option;
|
||||||
|
new_.font.setPointSize(26);
|
||||||
|
new_.fontMetrics = QFontMetrics(new_.font);
|
||||||
|
editor->setGeometry(text_rect(option.rect, new_.fontMetrics.height()).toRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupDisplayDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
drawBackground(painter, option, index);
|
||||||
|
|
||||||
|
auto cover0 = index.data(GROUP_COVER0);
|
||||||
|
if (cover0.isNull())
|
||||||
|
cover0 = default_cover->pixmap(QSize(100, 150));
|
||||||
|
|
||||||
|
auto cover1 = index.data(GROUP_COVER1);
|
||||||
|
if (cover1.isNull())
|
||||||
|
cover1 = default_cover->pixmap(QSize(100, 150));
|
||||||
|
|
||||||
|
auto cover2 = index.data(GROUP_COVER2);
|
||||||
|
if (cover2.isNull())
|
||||||
|
cover2 = default_cover->pixmap(QSize(100, 150));
|
||||||
|
|
||||||
|
auto valid_rect = option.rect - QMargins(15, 15, 15, 15);
|
||||||
|
|
||||||
|
auto pixmap1 = cover1.value<QPixmap>();
|
||||||
|
QRectF rect1(valid_rect.left() + 60, valid_rect.top() + 20, 54, 80);
|
||||||
|
painter->drawPixmap(rect1, pixmap1, QRectF(0, 0, 100, 150));
|
||||||
|
|
||||||
|
auto pixmap2 = cover2.value<QPixmap>();
|
||||||
|
QRectF rect2(valid_rect.left() + 34, valid_rect.top() + 10, 66, 100);
|
||||||
|
painter->drawPixmap(rect2, pixmap2, QRectF(0, 0, 100, 150));
|
||||||
|
|
||||||
|
auto pixmap0 = cover0.value<QPixmap>();
|
||||||
|
QRectF rect0(valid_rect.left(), valid_rect.top(), 80, 120);
|
||||||
|
painter->drawPixmap(rect0, pixmap0, QRectF(0, 0, 100, 150));
|
||||||
|
|
||||||
|
QStyleOptionViewItem new_copy = option;
|
||||||
|
new_copy.font.setPointSize(26);
|
||||||
|
new_copy.fontMetrics = QFontMetrics(new_copy.font);
|
||||||
|
drawDisplay(painter, new_copy, text_rect(option.rect, new_copy.fontMetrics.height()).toRect(), index.data().toString());
|
||||||
|
|
||||||
|
new_copy.font.setPointSize(18);
|
||||||
|
new_copy.fontMetrics = QFontMetrics(new_copy.font);
|
||||||
|
drawDisplay(painter, new_copy, new_copy.rect - QMargins(160, 60, 0, 0), QString("总藏书:%1").arg(index.data(GROUP_ITEMSCOUNT).toUInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize
|
||||||
|
GroupDisplayDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
return QSize(400, 145);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QItemDelegate>
|
||||||
|
#include <QListView>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
class GroupDisplayDelegate : public QItemDelegate {
|
||||||
|
public:
|
||||||
|
GroupDisplayDelegate();
|
||||||
|
virtual ~GroupDisplayDelegate() override;
|
||||||
|
|
||||||
|
// QAbstractItemDelegate interface
|
||||||
|
public:
|
||||||
|
virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
virtual void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||||
|
virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
|
||||||
|
virtual void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QIcon* const default_cover;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWindow(QWidget* parent = nullptr);
|
||||||
|
virtual ~MainWindow() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QListView* const groups_view;
|
||||||
|
QStandardItemModel* const groups_list;
|
||||||
|
QListView* const items_view;
|
||||||
|
QStandardItemModel* const items_list;
|
||||||
|
|
||||||
|
void init_groups_list(QStandardItemModel* model);
|
||||||
|
};
|
||||||
|
#endif // MAINWINDOW_H
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/imgs/default">
|
||||||
|
<file>cover.jpg</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
Loading…
Reference in New Issue