Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #44

Merged
merged 5 commits into from
Aug 7, 2024
Merged

Dev #44

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 7 additions & 25 deletions COS3711-03-01/COS3711-03-01.drawio
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<mxfile host="Electron" modified="2024-08-03T22:19:03.055Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.6.4 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="wzqjLYlRrMz9Hwo7XFZM" version="24.6.4" type="device">
<mxfile host="Electron" modified="2024-08-06T13:08:42.070Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.6.4 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="2MUYOWNRhgzR3xg8WMUV" version="24.6.4" type="device">
<diagram id="6iuWq0UelAJ61aAoiBDy" name="Book Shelf">
<mxGraphModel dx="2265" dy="2298" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<mxGraphModel dx="1288" dy="1299" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
Expand Down Expand Up @@ -97,42 +97,24 @@
<mxCell id="gvHln3FCuM-_E14BoruI-77" value="+ BookProxyModel(parent: QObject)&lt;div&gt;+ setFilterText(filterText: QString)&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="gvHln3FCuM-_E14BoruI-74" vertex="1">
<mxGeometry y="34" width="500" height="56" as="geometry" />
</mxCell>
<mxCell id="gvHln3FCuM-_E14BoruI-78" value="&lt;div&gt;BookView&lt;/div&gt;" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="1050" y="-610" width="400" height="98" as="geometry" />
</mxCell>
<mxCell id="gvHln3FCuM-_E14BoruI-79" value="- tableView: QTableView&lt;div&gt;- model: BookTableModel&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="gvHln3FCuM-_E14BoruI-78" vertex="1">
<mxGeometry y="26" width="400" height="34" as="geometry" />
</mxCell>
<mxCell id="gvHln3FCuM-_E14BoruI-80" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;labelBackgroundColor=none;" parent="gvHln3FCuM-_E14BoruI-78" vertex="1">
<mxGeometry y="60" width="400" height="8" as="geometry" />
</mxCell>
<mxCell id="gvHln3FCuM-_E14BoruI-81" value="&lt;div&gt;+ addBook(title: QString, authors: QString, isbn: QString, date: QString)&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;labelBackgroundColor=none;" parent="gvHln3FCuM-_E14BoruI-78" vertex="1">
<mxGeometry y="68" width="400" height="30" as="geometry" />
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-5" value="&lt;div&gt;MainWindow&lt;/div&gt;" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;labelBackgroundColor=none;" vertex="1" parent="1">
<mxGeometry x="1670" y="-375" width="500" height="360" as="geometry" />
<mxGeometry x="1670" y="-410" width="500" height="310" as="geometry" />
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-6" value="&lt;div&gt;- bookView: BookView&lt;/div&gt;&lt;div&gt;- bookModel: BookModel&lt;/div&gt;&lt;div&gt;- menuBar: QMenuBar&lt;/div&gt;&lt;div&gt;- statusBar: QStatusBar&lt;/div&gt;&lt;div&gt;- toolBar: QToolBar&lt;/div&gt;&lt;div&gt;- actionAddBook: QAction&lt;/div&gt;&lt;div&gt;- actionExportBooks: QAction&lt;/div&gt;&lt;div&gt;- actionSearchBook: QAction&lt;/div&gt;&lt;div&gt;- actionCloseApplicationWindow(): QAction&lt;/div&gt;&lt;div&gt;- lineEditSearch: QLineEdit&lt;/div&gt;&lt;div&gt;- pushButtonClear: QPushButton&lt;/div&gt;&lt;div&gt;- proxyModel: BookFilterProxyModel&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;labelBackgroundColor=none;" vertex="1" parent="we9DT2KBn4o6eFFRd77e-5">
<mxGeometry y="26" width="500" height="184" as="geometry" />
<mxCell id="we9DT2KBn4o6eFFRd77e-6" value="&lt;div&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;- bookModel: BookModel&lt;/span&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;- proxyModel: BookFilterProxyModel&lt;/div&gt;&lt;div&gt;- bookTableView: QTableView&lt;br&gt;&lt;/div&gt;&lt;div&gt;- actionAddBook: QAction&lt;/div&gt;&lt;div&gt;- actionExportBooks: QAction&lt;/div&gt;&lt;div&gt;- actionClose: QAction&lt;/div&gt;&lt;div&gt;- lineEditSearch: QLineEdit&lt;/div&gt;&lt;div&gt;- pushButtonClear: QPushButton&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;labelBackgroundColor=none;" vertex="1" parent="we9DT2KBn4o6eFFRd77e-5">
<mxGeometry y="26" width="500" height="134" as="geometry" />
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-7" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;labelBackgroundColor=none;" vertex="1" parent="we9DT2KBn4o6eFFRd77e-5">
<mxGeometry y="210" width="500" height="8" as="geometry" />
<mxGeometry y="160" width="500" height="8" as="geometry" />
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-8" value="&lt;div&gt;&lt;div&gt;+ MainWindow(parent: QWidget)&lt;/div&gt;&lt;/div&gt;&lt;div&gt;+ ~MainWindow()&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;+ setupUI()&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;- addBook()&lt;/div&gt;&lt;div&gt;- exportBooks()&lt;/div&gt;&lt;div&gt;- clearFilter()&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;labelBackgroundColor=none;" vertex="1" parent="we9DT2KBn4o6eFFRd77e-5">
<mxGeometry y="218" width="500" height="142" as="geometry" />
<mxGeometry y="168" width="500" height="142" as="geometry" />
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-9" value="" style="endArrow=diamondThin;endFill=1;endSize=24;html=1;rounded=0;" edge="1" parent="1" source="gvHln3FCuM-_E14BoruI-74" target="we9DT2KBn4o6eFFRd77e-5">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="660" y="-470" as="sourcePoint" />
<mxPoint x="820" y="-470" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-10" value="" style="endArrow=diamondThin;endFill=1;endSize=24;html=1;rounded=0;" edge="1" parent="1" source="gvHln3FCuM-_E14BoruI-78" target="we9DT2KBn4o6eFFRd77e-5">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1340" y="-680" as="sourcePoint" />
<mxPoint x="1500" y="-680" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="we9DT2KBn4o6eFFRd77e-11" value="" style="endArrow=diamondThin;endFill=0;endSize=24;html=1;rounded=0;" edge="1" parent="1" source="gvHln3FCuM-_E14BoruI-51" target="gvHln3FCuM-_E14BoruI-74">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="780" y="490" as="sourcePoint" />
Expand Down
3 changes: 2 additions & 1 deletion COS3711-03-01/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ set(PROJECT_SOURCES
)

# Create library
add_library(MyProjectLib ${PROJECT_SOURCES})
add_library(MyProjectLib ${PROJECT_SOURCES}
bookfactory.h bookfactory.cpp)

# Include directories for the library
target_include_directories(MyProjectLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Expand Down
20 changes: 20 additions & 0 deletions COS3711-03-01/src/bookfactory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "bookfactory.h"
#include "book.h"


BookFactory::BookFactory() {}

BookFactory &BookFactory::getInstance()
{
static BookFactory bookFactoryInstance;
return bookFactoryInstance;
}

Book *BookFactory::createBook(const QString &title, const QStringList &authors, const QString &isbn, const QDate &publicationDate)
{
if (title.isEmpty() || authors.isEmpty() || isbn.isEmpty() || !publicationDate.isValid())
{
return nullptr;
}
return new Book(title, authors, isbn, publicationDate);
}
23 changes: 23 additions & 0 deletions COS3711-03-01/src/bookfactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef BOOKFACTORY_H
#define BOOKFACTORY_H

class Book;
class QDate;
class QString;

#include <QStringList>


class BookFactory
{
public:
static BookFactory &getInstance();
Book *createBook(const QString &title, const QStringList &authors, const QString &isbn, const QDate &publicationDate);

private:
BookFactory();
BookFactory(const BookFactory&) = delete;
BookFactory &operator=(const BookFactory&) = delete;
};

#endif // BOOKFACTORY_H
50 changes: 43 additions & 7 deletions COS3711-03-01/src/bookinput.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "book.h"
#include "bookinput.h"
#include "booktablemodel.h"
#include "bookfactory.h"

#include <QDateEdit>
#include <QGridLayout>
Expand All @@ -12,8 +15,9 @@
#include <QRegularExpressionMatch>


BookInput::BookInput(QWidget *parent)
BookInput::BookInput(BookTableModel *model, QWidget *parent)
: QDialog{parent},
bookTableModel(model),
mainLayout(new QGridLayout(this)),
gridLayoutBook(new QGridLayout()),
gridLayoutAuthor(new QGridLayout()),
Expand Down Expand Up @@ -78,7 +82,30 @@ void BookInput::saveBook()
return;
}

// TODO: add book and author to model
// Add book and author to model
QString title = lineEditTitle->text();
QStringList authors;
for (int i = 0; i < listWidgetAuthors->count(); i++)
{
QListWidgetItem *item = listWidgetAuthors->item(i);
if (item)
{
authors.append(item->text());
}
}
QString isbn = lineEditIsbn->text();
QDate publicationDate = dateEditPublicationDate->date();

// Create the new book using the book factory
BookFactory &bookFactory = BookFactory::getInstance();
Book *newBook = bookFactory.createBook(title, authors, isbn, publicationDate);

// Add the new book to the model
bookTableModel->addBook(newBook);

// Close the dialog
accept();

}

void BookInput::cancel()
Expand Down Expand Up @@ -108,6 +135,8 @@ void BookInput::setupBookGroup()

// ISBN
QLabel *labelIsbn = new QLabel("ISBN", this);
lineEditIsbn->setInputMask("999-9-99-999999-9;_");
lineEditIsbn->setPlaceholderText("978-3-16-148410-0");
gridLayoutBook->addWidget(labelIsbn, 1, 0);
gridLayoutBook->addWidget(lineEditIsbn, 1, 1, 1, 3);

Expand Down Expand Up @@ -174,12 +203,19 @@ bool BookInput::isValidInput()
return false;
}

// Check if ISBN is empty or invalid
static QRegularExpression isbnRegex("\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}");
QRegularExpressionMatch isbnMatch = isbnRegex.match(lineEditIsbn->text());
if (lineEditIsbn->text().isEmpty() || !isbnMatch.hasMatch())
// // Check if ISBN is empty or invalid
// static QRegularExpression isbnRegex("\\d{3}-\\d{1,5}-\\d{1,7}-\\d{1,7}-\\d{1}");
// QRegularExpressionMatch isbnMatch = isbnRegex.match(lineEditIsbn->text());
// if (lineEditIsbn->text().isEmpty() || !isbnMatch.hasMatch())
// {
// QMessageBox::warning(this, "Input Error", "Please enter a valid ISBN (format: 978-3-16-148410-0).");
// lineEditIsbn->setFocus();
// return false;
// }
// Check if ISBN is empty
if (lineEditIsbn->text().isEmpty())
{
QMessageBox::warning(this, "Input Error", "Please enter a valid ISBN (format: 978-3-16-148410-0).");
QMessageBox::warning(this, "Input Error", "Please enter an ISBN.");
lineEditIsbn->setFocus();
return false;
}
Expand Down
6 changes: 3 additions & 3 deletions COS3711-03-01/src/bookinput.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ class QGroupBox;
class QLineEdit;
class QListWidget;
class QPushButton;
class BookTableModel;


class BookInput : public QDialog
{
Q_OBJECT
public:
explicit BookInput(QWidget *parent = nullptr);
// TODO: inject model into constructor

explicit BookInput(BookTableModel *model, QWidget *parent = nullptr);
~BookInput();

private slots:
Expand All @@ -33,6 +32,7 @@ private slots:
void setupButtons();
bool isValidInput();

BookTableModel *bookTableModel;
QLineEdit *lineEditTitle;
QLineEdit *lineEditIsbn;
QDateEdit *dateEditPublicationDate;
Expand Down
44 changes: 25 additions & 19 deletions COS3711-03-01/src/booktablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ BookTableModel::BookTableModel(QObject *parent)

BookTableModel::~BookTableModel()
{
qDeleteAll(books);
qDeleteAll(bookList);
}

int BookTableModel::rowCount(const QModelIndex &parent) const
Expand All @@ -17,7 +17,7 @@ int BookTableModel::rowCount(const QModelIndex &parent) const
{
return 0;
}
return books.size();
return bookList.size();
}

int BookTableModel::columnCount(const QModelIndex &parent) const
Expand All @@ -27,7 +27,7 @@ int BookTableModel::columnCount(const QModelIndex &parent) const
{
return 0;
}
return 4; // title, author, publication date, isbn
return 4; // title, authors, publication date, isbn
}

QVariant BookTableModel::data(const QModelIndex &index, int role) const
Expand All @@ -42,10 +42,20 @@ QVariant BookTableModel::data(const QModelIndex &index, int role) const
int col = index.column();
int row = index.row();

if (col == 0) { return books.at(row)->getTitle(); }
if (col == 1) { return books.at(row)->getAuthors(); }
if (col == 2) { return books.at(row)->getPublicationDate(); }
if (col == 3) { return books.at(row)->getIsbn(); }
if (col == 0) { return bookList.at(row)->getTitle(); }
if (col == 1)
{
if (bookList.at(row)->getAuthors().count() == 1)
{
return bookList.at(row)->getAuthors();
}
else if (bookList.at(row)->getAuthors().count() > 1)
{
return bookList.at(row)->getAuthors().join("; ");
}
}
if (col == 2) { return bookList.at(row)->getPublicationDate(); }
if (col == 3) { return bookList.at(row)->getIsbn(); }
}
return QVariant();
}
Expand Down Expand Up @@ -75,10 +85,6 @@ QVariant BookTableModel::headerData(int section, Qt::Orientation orientation, in
break;
}
}
else if (orientation == Qt::Vertical)
{
return section + 1; // row numbers
}
return QVariant();
}

Expand All @@ -92,16 +98,16 @@ bool BookTableModel::setData(const QModelIndex &index, const QVariant &value, in
switch (col)
{
case 0:
books.at(row)->setTitle(value.toString());
bookList.at(row)->setTitle(value.toString());
break;
case 1:
books.at(row)->setAuthors(value.toStringList());
bookList.at(row)->setAuthors(value.toStringList());
break;
case 2:
books.at(row)->setPublicationDate(value.toDate());
bookList.at(row)->setPublicationDate(value.toDate());
break;
case 3:
books.at(row)->setIsbn(value.toString());
bookList.at(row)->setIsbn(value.toString());
break;
}
emit dataChanged(index, index, { role });
Expand All @@ -114,7 +120,7 @@ Qt::ItemFlags BookTableModel::flags(const QModelIndex &index) const
{
if (index.isValid())
{
return (Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
return (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
else
{
Expand All @@ -124,8 +130,8 @@ Qt::ItemFlags BookTableModel::flags(const QModelIndex &index) const

void BookTableModel::addBook(Book *book)
{
int row = books.size();
beginInsertRows(QModelIndex(), row + 1, row + 1);
books.append(book);
int row = bookList.size();
beginInsertRows(QModelIndex(), row, row);
bookList.append(book);
endInsertRows();
}
2 changes: 1 addition & 1 deletion COS3711-03-01/src/booktablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class BookTableModel : public QAbstractTableModel
void addBook(Book *book);

private:
QList<Book*> books;
QList<Book*> bookList;

};

Expand Down
6 changes: 3 additions & 3 deletions COS3711-03-01/src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ MainWindow::MainWindow(QWidget *parent)
actionExportBooks(new QAction(QIcon(":/icons/export"), tr("Export Books"), this)),
actionClose(new QAction(QIcon(":/icons/exit"), tr("Exit Application"), this)),
lineEditSearch(new QLineEdit(this)),
pushButtonClear(new QPushButton("Clear", this))
pushButtonClear(new QPushButton("Clear Filter", this))
{
// Proxy Model
bookProxyModel->setSourceModel(bookTableModel);
Expand All @@ -43,7 +43,7 @@ MainWindow::MainWindow(QWidget *parent)
// Signals and Slots connections
connect(actionAddBook, &QAction::triggered, this, &MainWindow::addBook);
connect(actionExportBooks, &QAction::triggered, this, &MainWindow::exportBooks);
// connect(lineEditSearch, &QLineEdit::textEdited, bookProxyModel, &BookProxyModel::setFilterText);
connect(lineEditSearch, &QLineEdit::textEdited, bookProxyModel, &BookProxyModel::setFilter);
connect(pushButtonClear, &QPushButton::clicked, this, &MainWindow::clearFilter);
connect(actionClose, &QAction::triggered, this, &MainWindow::close);

Expand Down Expand Up @@ -106,7 +106,7 @@ void MainWindow::setupUI()

void MainWindow::addBook()
{
BookInput *bookInputDialog = new BookInput(this);
BookInput *bookInputDialog = new BookInput(bookTableModel, this);
bookInputDialog->show();
}

Expand Down
1 change: 1 addition & 0 deletions COS3711-03-01/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(UNIT_TEST_SOURCES
testbook.h testbook.cpp
testbooktablemodel.h testbooktablemodel.cpp
testbookproxymodel.h testbookproxymodel.cpp
testbookfactory.h testbookfactory.cpp
)

add_executable(UnitTests ${UNIT_TEST_SOURCES}
Expand Down
5 changes: 5 additions & 0 deletions COS3711-03-01/tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "testbook.h"
#include "testbooktablemodel.h"
#include "testbookproxymodel.h"
#include "testbookfactory.h"


int main(int argc, char *argv[])
Expand All @@ -23,6 +24,10 @@ int main(int argc, char *argv[])
TestBookProxyModel tc;
status |= QTest::qExec(&tc, argc, argv);
}
{
TestBookFactory tc;
status |= QTest::qExec(&tc, argc, argv);
}

return status;
}
Loading
Loading