Search code examples
pythonpyside2qtwidgets

How to refresh in tray menu after add new


I need to refresh list on tray menu after add new item.

what I need to do

class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtWidgets.QMenu(parent)

        c.execute('SELECT * FROM projects')
        for row in c.fetchall():
                path = row[0]
                open_app = menu.addAction(path.split('/')[-1])
                open_app.triggered.connect( lambda: self.vscode(path))           

    def add(self):
        Tkinter.Tk().withdraw() # Close the root window
        in_path = tkFileDialog.askdirectory()
        c.execute("INSERT INTO projects VALUES ('"+str(in_path)+"')")


Solution

  • One possible solution is to eliminate the QActions that depend on the database and create new ones by inserting them with the new information:

    from PySide2 import QtCore, QtGui, QtWidgets, QtSql
    
    
    def create_connection():
        db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName("tray.db")
    
        if not db.open():
            QtWidgets.QMessageBox.critical(
                None,
                QtWidgets.qApp.tr("Cannot open database"),
                QtWidgets.qApp.tr(
                    "Unable to establish a database connection.\n"
                    "This example needs SQLite support. Please read "
                    "the Qt SQL driver documentation for information "
                    "how to build it.\n\n"
                    "Click Cancel to exit."
                ),
                QtWidgets.QMessageBox.Cancel,
            )
            return False
    
        query = QtSql.QSqlQuery(
            "CREATE TABLE IF NOT EXISTS projects(PATH text NOT NULL UNIQUE)"
        )
        if not query.exec_():
            print(query.lastError().text())
            return False
        return True
    
    
    class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
        def __init__(self, icon, parent=None):
            super().__init__(icon, parent)
            self._path_actions = []
    
            self._menu = QtWidgets.QMenu(parent)
            self.setContextMenu(self._menu)
    
            self._separator = self._menu.addSeparator()
            add_action = QtWidgets.QAction(
                "Adicionar", self, icon=QtGui.QIcon("img/plus.png"), triggered=self.add
            )
            quit_action = QtWidgets.QAction(
                "Exit",
                self,
                icon=QtGui.QIcon("img/logout.png"),
                triggered=QtWidgets.QApplication.quit,
            )
            self._menu.addAction(add_action)
            self._menu.addAction(quit_action)
    
            self.refresh_menu()
    
            self.activated.connect(self.onTrayIconActivated)
    
        @QtCore.Slot(QtWidgets.QSystemTrayIcon.ActivationReason)
        def onTrayIconActivated(self, reason):
            if reason in (
                QtWidgets.QSystemTrayIcon.Trigger,
                QtWidgets.QSystemTrayIcon.DoubleClick,
            ):
                QtWidgets.QApplication.quit()
    
        def refresh_menu(self):
            menu = self.contextMenu()
    
            for action in self._path_actions:
                action.deleteLater()
    
            query = QtSql.QSqlQuery("SELECT * FROM projects")
            self._path_actions = []
            while query.next():
                directory = query.value(0)
                info = QtCore.QFileInfo(directory)
                action = QtWidgets.QAction(info.fileName(), self, triggered=self.vscode)
                action.setData(directory)
                self._path_actions.append(action)
            menu.insertActions(self._separator, self._path_actions)
    
        @QtCore.Slot()
        def add(self):
            directory = QtWidgets.QFileDialog.getExistingDirectory(
                None, self.tr("Open getExistingDirectory")
            )
            query = QtSql.QSqlQuery()
            query.prepare("INSERT INTO projects VALUES (?)")
            query.addBindValue(directory)
            if not query.exec_():
                print(query.lastError().text())
                return
            self.refresh_menu()
    
        @QtCore.Slot()
        def vscode(self):
            action = self.sender()
            directory = action.data()
            print(directory)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        if not create_connection():
            sys.exit(-1)
    
        if not QtWidgets.QSystemTrayIcon.isSystemTrayAvailable():
            QtWidgets.QMessageBox.critical(
                None, "Systray", "I couldn't detect any system tray on this system."
            )
            sys.exit(1)
    
        QtWidgets.QApplication.setQuitOnLastWindowClosed(False)
        tray_icon = SystemTrayIcon(QtGui.QIcon("img/icon.png"))
        tray_icon.show()
        tray_icon.showMessage("TrayCode", 'Hi "bitter"')
        sys.exit(app.exec_())