I have an application that can interact with its database by adding, deleting or updating its entries. What I xant to do is that whenever there is a new entry or an operation is performed on the database, I want to emit a general signal that tells the mainwindow to redraw the ClipBoardWidget widgets as now there could be more, less, or a widget might be updated with new information... As of now, this works only when you perform an operation in the application and the you have to close it and reopen the application for it change, its not dynamic...
Here is the MainWindow class:
from PySide6.QtWidgets import (QMainWindow,
QToolBar,
QWidget,
QToolButton,
QVBoxLayout,
QScrollArea
)
from PySide6.QtGui import (QAction, QIcon)
from PySide6.QtCore import (Qt, QCoreApplication, QSize, Slot)
from controller.database import Database
from gui.add import AddClipboard
from gui.search import SearchClipboard
from gui.remove import RemoveClipboard
from gui.clipboardwidget import ClipBoardWidget
class GUI(QMainWindow):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Clipboard Manager")
self.tool_bar = QToolBar(self)
self.tool_bar.setObjectName(u"toolBar")
self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
self.tool_bar.setMovable(False)
self.add_cb_btn = QToolButton()
self.add_cb_btn.setIcon(QIcon("gui/assets/add.svg"))
self.add_cb_btn.clicked.connect(self.addcbshow)
self.remove_cb_btn = QToolButton()
self.remove_cb_btn.setIcon(QIcon("gui/assets/trash.svg"))
self.remove_cb_btn.clicked.connect(self.removecbshow)
self.search_cb_btn = QToolButton()
self.search_cb_btn.setIcon(QIcon("gui/assets/search.svg"))
self.search_cb_btn.clicked.connect(self.searchcbshow)
self.tool_bar.addWidget(self.add_cb_btn)
self.tool_bar.addWidget(self.remove_cb_btn)
self.tool_bar.addWidget(self.search_cb_btn)
self.slate_layout = QVBoxLayout()
self.scroll_cb = QScrollArea()
self.slate = QWidget()
self.db = Database()
for u in self.db.GetClipboards():
obj = ClipBoardWidget(u[0], u[2], u[1], u[3])
self.slate_layout.addWidget(obj)
self.slate_layout.setStretch(0,0)
self.slate.setLayout(self.slate_layout)
self.scroll_cb.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll_cb.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll_cb.setWidgetResizable(True)
self.scroll_cb.setWidget(self.slate)
self.setCentralWidget(self.scroll_cb)
@Slot()
def addcbshow(self):
global g1
g1 = AddClipboard()
g1.show()
@Slot()
def removecbshow(self):
global g2
g2 = RemoveClipboard()
g2.show()
@Slot()
def searchcbshow(self):
global g3
g3 = SearchClipboard()
g3.show()
The ClipBoardWidget class:
class ClipBoardWidget(QWidget):
def __init__(self, title, date, categories, data) -> None:
super().__init__()
self.title = title
self.db = Database()
self.data = data
self.cbwidget_layout = QHBoxLayout()
self.title_label = QLabel(title)
self.date_label = QLabel(date)
self.categories_label = QLabel(categories)
self.data_label = QLabel(self.data)
self.edit_button = QPushButton(QIcon("gui/assets/edit.svg"), "")
self.edit_button.clicked.connect(self.edit_cb)
self.remove_button = QPushButton(QIcon("gui/assets/trash.svg"), "")
self.remove_button.clicked.connect(self.remove_cb)
self.copy_to_cb_button = QPushButton(QIcon("gui/assets/copy.svg"), "")
self.copy_to_cb_button.clicked.connect(self.copy_cb)
self.cbwidget_layout.addWidget(self.title_label)
self.cbwidget_layout.addWidget(self.date_label)
self.cbwidget_layout.addWidget(self.categories_label)
self.cbwidget_layout.addWidget(self.data_label)
self.cbwidget_layout.addWidget(self.edit_button)
self.cbwidget_layout.addWidget(self.remove_button)
self.cbwidget_layout.addWidget(self.copy_to_cb_button)
self.setLayout(self.cbwidget_layout)
@Slot()
def edit_cb(self):
global g1
g1 = EditClipboard()
g1.show()
@Slot()
def remove_cb(self):
self.db.RemoveClipboard(self.title)
@Slot()
def copy_cb(self):
pyperclip.copy(self.data)
the add edit remove and search dialogs:
class SearchClipboard(QDialog):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Search Clipboard")
class RemoveClipboard(QDialog):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Remove Clipboard")
self.db = Database()
self.setWindowTitle("Add Clipboard")
self.lay = QGridLayout()
self.remove_by_name = QLabel("Remove clipboard by name")
self.remove_by_name_lineedit = QLineEdit()
self.remove_cb_button = QPushButton(QIcon("gui/assets/trash.svg"), "Remove")
self.remove_cb_button.clicked.connect(self.remove_cb_from_db)
self.lay.addWidget(self.remove_by_name, 0, 0)
self.lay.addWidget(self.remove_by_name_lineedit, 0, 1)
self.lay.addWidget(self.remove_cb_button, 1,0 ,1, 2)
self.setLayout(self.lay)
@Slot()
def remove_cb_from_db(self):
self.db.RemoveClipboard(self.remove_by_name_lineedit.text())
self.deleteLater()
class EditClipboard(QDialog):
def __init__(self) -> None:
super().__init__()
self.db = Database()
self.setWindowTitle("Add Clipboard")
self.lay = QGridLayout()
self.cb_name = QLabel("Name")
self.cb_name_lineedit = QLineEdit()
self.cb_data = QLabel("Data")
self.cb_data_lineedit = QLineEdit()
self.cb_categories = QLabel("Categories")
self.cb_categories_lineedit = QLineEdit()
self.seperator_info = QLabel("<i>Seperate categoris with ';'</i>")
self.add_btn = QPushButton(QIcon("gui/assets/add.svg"), "Add")
self.add_btn.clicked.connect(self.add_cb_to_db)
self.lay.addWidget(self.cb_name, 0, 0)
self.lay.addWidget(self.cb_name_lineedit, 0, 1)
self.lay.addWidget(self.cb_data, 1, 0)
self.lay.addWidget(self.cb_data_lineedit, 1, 1)
self.lay.addWidget(self.cb_categories, 2, 0)
self.lay.addWidget(self.cb_categories_lineedit, 2, 1)
self.lay.addWidget(self.seperator_info, 3, 0 )
self.lay.addWidget(self.add_btn,4,0,1,2)
self.setLayout(self.lay)
@Slot()
def add_cb_to_db(self):
title = self.cb_name_lineedit.text()
categories = self.cb_categories_lineedit.text()
date = datetime.datetime.now()
data = self.cb_data.text()
self.db.AddClipboard(title, categories, date, data)
self.deleteLater()
class AddClipboard(QDialog):
def __init__(self) -> None:
super().__init__()
self.db = Database()
self.setWindowTitle("Add Clipboard")
self.lay = QGridLayout()
self.cb_name = QLabel("Name")
self.cb_name_lineedit = QLineEdit()
self.cb_data = QLabel("Data")
self.cb_data_lineedit = QLineEdit()
self.cb_categories = QLabel("Categories")
self.cb_categories_lineedit = QLineEdit()
self.seperator_info = QLabel("<i>Seperate categoris with ';'</i>")
self.add_btn = QPushButton(QIcon("gui/assets/add.svg"), "Add")
self.add_btn.clicked.connect(self.add_cb_to_db)
self.lay.addWidget(self.cb_name, 0, 0)
self.lay.addWidget(self.cb_name_lineedit, 0, 1)
self.lay.addWidget(self.cb_data, 1, 0)
self.lay.addWidget(self.cb_data_lineedit, 1, 1)
self.lay.addWidget(self.cb_categories, 2, 0)
self.lay.addWidget(self.cb_categories_lineedit, 2, 1)
self.lay.addWidget(self.seperator_info, 3, 0 )
self.lay.addWidget(self.add_btn,4,0,1,2)
self.setLayout(self.lay)
@Slot()
def add_cb_to_db(self):
title = self.cb_name_lineedit.text()
categories = self.cb_categories_lineedit.text()
date = datetime.datetime.now()
data = self.cb_data.text()
self.db.AddClipboard(title, categories, date, data)
self.deleteLater()
and finally, this is the database manager:
class UpdateEnum(IntEnum):
TITLE = 1
CATEGORIES = 2
DATA = 3
class Database():
def __init__(self) -> None:
self.con = sqlite3.connect("clipboardmanager.db")
self.cur = self.con.cursor()
with open("controller/tags.txt", "r") as f:
self.data = f.readlines()
def CreateTables(self):
self.cur.execute("CREATE TABLE clipboard(title, category, date, data)")
def AddClipboard(self, title: str, category: str, date: datetime, data: str):
self.cur.execute("""
INSERT INTO clipboard VALUES(?,?,?,?)
""", (title, category, date, data))
self.con.commit()
def RemoveClipboard(self, title: str):
self.cur.execute("DELETE from clipboard where title = ?", (title,))
self.con.commit()
def GetClipboards(self):
self.cur.execute("SELECT * FROM clipboard")
return self.cur.fetchall()
def EditClipoard(self, what_to_edit: UpdateEnum, edit: str, title: str):
if what_to_edit == UpdateEnum.TITLE:
self.cur.execute("UPDATE clipboard SET title = ? WHERE title = ?", (edit,title))
self.con.commit()
elif what_to_edit == UpdateEnum.DATA:
self.cur.execute("UPDATE clipboard SET data = ? WHERE title = ?", (edit,title))
self.con.commit()
elif what_to_edit == UpdateEnum.CATEGORIES:
self.cur.execute("UPDATE clipboard SET category = ? WHERE title = ?", (edit,title))
self.con.commit()
def Close(self):
self.cur.close()
self.con.close()
main.py where in a config.json file, "setup" is true or false
class CBManager():
def __init__(self) -> None:
pass
def _is_setup(self) -> bool:
self._file = open("config.json")
self._data = json.load(self._file)
return self._data["setup"]
def _setup(self) -> None:
self.db = Database()
self.db.CreateTables()
self.db.Close()
with open("config.json", "r") as json_file:
data = json.load(json_file)
data["setup"] = True
with open("config.json", "w") as json_file:
json.dump(data, json_file, indent=4)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle('Fusion')
if CBManager()._is_setup():
gui = GUI()
gui.setFixedWidth(600)
gui.setFixedHeight(400)
gui.show()
else:
CBManager()._setup()
gui = GUI()
gui.setFixedWidth(600)
gui.setFixedHeight(400)
gui.show()
sys.exit(app.exec())
the general gist is that the application loads all the entries from the db, show the entries in to clipboardwidgets in the mainwindow scroll area. when you perform add, edit, remove operations, the clipboardwidgets are not updated until you close the entire application and reopen it. How could I fix that?