Skip to content

Commit ef84882

Browse files
committed
✨ COntact Book
1 parent 5190a9e commit ef84882

File tree

7 files changed

+261
-0
lines changed

7 files changed

+261
-0
lines changed

contact-book/main.py

Whitespace-only changes.

contact-book/rpcontacts.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
# rpcontacts_project/rpcontacts.py
4+
5+
"""This module provides RP Contacts entry point script."""
6+
7+
from rpcontacts.main import main
8+
9+
if __name__ == "__main__":
10+
main()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""This module provides the rpcontacts package."""
4+
5+
__version__ = "0.1.0"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# -*- coding: utf-8 -*-
2+
# rpcontacts/database.py
3+
4+
# Snip...
5+
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
6+
7+
8+
def _createContactsTable():
9+
"""Create the contacts table in the database."""
10+
createTableQuery = QSqlQuery()
11+
return createTableQuery.exec(
12+
"""
13+
CREATE TABLE IF NOT EXISTS contacts (
14+
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
15+
name VARCHAR(40) NOT NULL,
16+
job VARCHAR(50),
17+
email VARCHAR(40) NOT NULL
18+
)
19+
"""
20+
)
21+
22+
23+
def createConnection(databaseName):
24+
# Snip...
25+
_createContactsTable()
26+
return True

contact-book/rpcontacts/main.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
# rpcontacts/main.py
3+
4+
"""This module provides RP Contacts application."""
5+
6+
import sys
7+
8+
from PyQt5.QtWidgets import QApplication
9+
10+
from .database import createConnection
11+
from .views import Window
12+
13+
14+
def main():
15+
"""RP Contacts main function."""
16+
# Create the application
17+
app = QApplication(sys.argv)
18+
# Connect to the database before creating any window
19+
if not createConnection("contacts.sqlite"):
20+
sys.exit(1)
21+
# Create the main window if the connection succeeded
22+
win = Window()
23+
win.show()
24+
# Run the event loop
25+
sys.exit(app.exec_())

contact-book/rpcontacts/model.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# -*- coding: utf-8 -*-
2+
# rpcontacts/model.py
3+
4+
"""This module provides a model to manage the contacts table."""
5+
6+
from PyQt5.QtCore import Qt
7+
from PyQt5.QtSql import QSqlTableModel
8+
9+
10+
class ContactsModel:
11+
def __init__(self):
12+
self.model = self._createModel()
13+
14+
@staticmethod
15+
def _createModel():
16+
"""Create and set up the model."""
17+
tableModel = QSqlTableModel()
18+
tableModel.setTable("contacts")
19+
tableModel.setEditStrategy(QSqlTableModel.OnFieldChange)
20+
tableModel.select()
21+
headers = ("ID", "Name", "Job", "Email")
22+
for columnIndex, header in enumerate(headers):
23+
tableModel.setHeaderData(columnIndex, Qt.Horizontal, header)
24+
return tableModel
25+
26+
def addContact(self, data):
27+
"""Add a contact to the database."""
28+
rows = self.model.rowCount()
29+
self.model.insertRows(rows, 1)
30+
for column, field in enumerate(data):
31+
self.model.setData(self.model.index(rows, column + 1), field)
32+
self.model.submitAll()
33+
self.model.select()
34+
35+
def deleteContact(self, row):
36+
"""Remove a contact from the database."""
37+
self.model.removeRow(row)
38+
self.model.submitAll()
39+
self.model.select()
40+
41+
def clearContacts(self):
42+
"""Remove all contacts in the database."""
43+
self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
44+
self.model.removeRows(0, self.model.rowCount())
45+
self.model.submitAll()
46+
self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
47+
self.model.select()

contact-book/rpcontacts/views.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""This module provides views to manage the contacts table."""
4+
5+
from PyQt5.QtCore import Qt
6+
from PyQt5.QtWidgets import (
7+
QAbstractItemView,
8+
QHBoxLayout,
9+
QDialog,
10+
QDialogButtonBox,
11+
QFormLayout,
12+
QLineEdit,
13+
QMessageBox,
14+
QMainWindow,
15+
QPushButton,
16+
QTableView,
17+
QVBoxLayout,
18+
QWidget,
19+
)
20+
21+
from .model import ContactsModel
22+
23+
24+
class Window(QMainWindow):
25+
"""Main Window."""
26+
27+
def __init__(self, parent=None):
28+
"""Initializer."""
29+
# Snip...
30+
self.contactsModel = ContactsModel()
31+
self.setupUI()
32+
33+
def setupUI(self):
34+
"""Setup the main window's GUI."""
35+
# Create the table view widget
36+
self.table = QTableView()
37+
self.table.setModel(self.contactsModel.model)
38+
self.deleteButton.clicked.connect(self.deleteContact)
39+
self.clearAllButton.clicked.connect(self.clearContacts)
40+
self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
41+
self.table.resizeColumnsToContents()
42+
# Create buttons
43+
self.addButton = QPushButton("Add...")
44+
self.deleteButton = QPushButton("Delete")
45+
self.clearAllButton = QPushButton("Clear All")
46+
# Lay out the GUI
47+
layout = QVBoxLayout()
48+
layout.addWidget(self.addButton)
49+
layout.addWidget(self.deleteButton)
50+
layout.addStretch()
51+
layout.addWidget(self.clearAllButton)
52+
self.layout.addWidget(self.table)
53+
self.layout.addLayout(layout)
54+
55+
56+
class AddDialog(QDialog):
57+
"""Add Contact dialog."""
58+
59+
def __init__(self, parent=None):
60+
"""Initializer."""
61+
super().__init__(parent=parent)
62+
self.setWindowTitle("Add Contact")
63+
self.layout = QVBoxLayout()
64+
self.setLayout(self.layout)
65+
self.data = None
66+
67+
self.setupUI()
68+
69+
def setupUI(self):
70+
"""Setup the Add Contact dialog's GUI."""
71+
# Create line edits for data fields
72+
self.nameField = QLineEdit()
73+
self.nameField.setObjectName("Name")
74+
self.addButton.clicked.connect(self.openAddDialog)
75+
self.jobField = QLineEdit()
76+
self.jobField.setObjectName("Job")
77+
self.emailField = QLineEdit()
78+
self.emailField.setObjectName("Email")
79+
# Lay out the data fields
80+
layout = QFormLayout()
81+
layout.addRow("Name:", self.nameField)
82+
layout.addRow("Job:", self.jobField)
83+
layout.addRow("Email:", self.emailField)
84+
self.layout.addLayout(layout)
85+
# Add standard buttons to the dialog and connect them
86+
self.buttonsBox = QDialogButtonBox(self)
87+
self.buttonsBox.setOrientation(Qt.Horizontal)
88+
self.buttonsBox.setStandardButtons(
89+
QDialogButtonBox.Ok | QDialogButtonBox.Cancel
90+
)
91+
self.buttonsBox.accepted.connect(self.accept)
92+
self.buttonsBox.rejected.connect(self.reject)
93+
self.layout.addWidget(self.buttonsBox)
94+
95+
def accept(self):
96+
"""Accept the data provided through the dialog."""
97+
self.data = []
98+
for field in (self.nameField, self.jobField, self.emailField):
99+
if not field.text():
100+
QMessageBox.critical(
101+
self,
102+
"Error!",
103+
f"You must provide a contact's {field.objectName()}",
104+
)
105+
self.data = None # Reset .data
106+
return
107+
108+
self.data.append(field.text())
109+
110+
if not self.data:
111+
return
112+
113+
super().accept()
114+
115+
def openAddDialog(self):
116+
"""Open the Add Contact dialog."""
117+
dialog = AddDialog(self)
118+
if dialog.exec() == QDialog.Accepted:
119+
self.contactsModel.addContact(dialog.data)
120+
self.table.resizeColumnsToContents()
121+
122+
def deleteContact(self):
123+
"""Delete the selected contact from the database."""
124+
row = self.table.currentIndex().row()
125+
if row < 0:
126+
return
127+
128+
messageBox = QMessageBox.warning(
129+
self,
130+
"Warning!",
131+
"Do you want to remove the selected contact?",
132+
QMessageBox.Ok | QMessageBox.Cancel,
133+
)
134+
135+
if messageBox == QMessageBox.Ok:
136+
self.contactsModel.deleteContact(row)
137+
138+
def clearContacts(self):
139+
"""Remove all contacts from the database."""
140+
messageBox = QMessageBox.warning(
141+
self,
142+
"Warning!",
143+
"Do you want to remove all your contacts?",
144+
QMessageBox.Ok | QMessageBox.Cancel,
145+
)
146+
147+
if messageBox == QMessageBox.Ok:
148+
self.contactsModel.clearContacts()

0 commit comments

Comments
 (0)