1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2009 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Module implementing the SQL Browser main window.
8"""
9
10from PyQt5.QtCore import QTimer, QUrl
11from PyQt5.QtGui import QKeySequence
12from PyQt5.QtSql import QSqlError, QSqlDatabase
13
14from E5Gui.E5Action import E5Action
15from E5Gui import E5MessageBox
16from E5Gui.E5MainWindow import E5MainWindow
17from E5Gui.E5Application import e5App
18
19import UI.PixmapCache
20import UI.Config
21
22import Preferences
23
24
25class SqlBrowser(E5MainWindow):
26    """
27    Class implementing the SQL Browser main window.
28    """
29    def __init__(self, connections=None, parent=None):
30        """
31        Constructor
32
33        @param connections list of database connections to add
34            (list of strings)
35        @param parent reference to the parent widget (QWidget)
36        """
37        super().__init__(parent)
38        self.setObjectName("SqlBrowser")
39
40        if connections is None:
41            connections = []
42
43        self.setWindowTitle(self.tr("SQL Browser"))
44        self.setWindowIcon(UI.PixmapCache.getIcon("eric"))
45
46        self.setStyle(Preferences.getUI("Style"),
47                      Preferences.getUI("StyleSheet"))
48
49        from .SqlBrowserWidget import SqlBrowserWidget
50        self.__browser = SqlBrowserWidget(self)
51        self.setCentralWidget(self.__browser)
52
53        self.__browser.statusMessage.connect(self.statusBar().showMessage)
54
55        self.__initActions()
56        self.__initMenus()
57        self.__initToolbars()
58
59        self.resize(self.__browser.size())
60
61        self.__warnings = []
62
63        for connection in connections:
64            url = QUrl(connection, QUrl.ParsingMode.TolerantMode)
65            if not url.isValid():
66                self.__warnings.append(
67                    self.tr("Invalid URL: {0}").format(connection))
68                continue
69
70            err = self.__browser.addConnection(url.scheme(), url.path(),
71                                               url.userName(), url.password(),
72                                               url.host(), url.port(-1))
73            if err.type() != QSqlError.ErrorType.NoError:
74                self.__warnings.append(
75                    self.tr("Unable to open connection: {0}".format(
76                        err.text())))
77
78        QTimer.singleShot(0, self.__uiStartUp)
79
80    def __uiStartUp(self):
81        """
82        Private slot to do some actions after the UI has started and the main
83        loop is up.
84        """
85        for warning in self.__warnings:
86            E5MessageBox.warning(
87                self,
88                self.tr("SQL Browser startup problem"),
89                warning)
90
91        if len(QSqlDatabase.connectionNames()) == 0:
92            self.__browser.addConnectionByDialog()
93
94    def __initActions(self):
95        """
96        Private method to define the user interface actions.
97        """
98        # list of all actions
99        self.__actions = []
100
101        self.addConnectionAct = E5Action(
102            self.tr('Add Connection'),
103            UI.PixmapCache.getIcon("databaseConnection"),
104            self.tr('Add &Connection...'),
105            0, 0, self, 'sql_file_add_connection')
106        self.addConnectionAct.setStatusTip(self.tr(
107            'Open a dialog to add a new database connection'))
108        self.addConnectionAct.setWhatsThis(self.tr(
109            """<b>Add Connection</b>"""
110            """<p>This opens a dialog to add a new database"""
111            """ connection.</p>"""
112        ))
113        self.addConnectionAct.triggered.connect(
114            self.__browser.addConnectionByDialog)
115        self.__actions.append(self.addConnectionAct)
116
117        self.exitAct = E5Action(
118            self.tr('Quit'),
119            UI.PixmapCache.getIcon("exit"),
120            self.tr('&Quit'),
121            QKeySequence(self.tr("Ctrl+Q", "File|Quit")),
122            0, self, 'sql_file_quit')
123        self.exitAct.setStatusTip(self.tr('Quit the SQL browser'))
124        self.exitAct.setWhatsThis(self.tr(
125            """<b>Quit</b>"""
126            """<p>Quit the SQL browser.</p>"""
127        ))
128        self.exitAct.triggered.connect(e5App().closeAllWindows)
129
130        self.aboutAct = E5Action(
131            self.tr('About'),
132            self.tr('&About'),
133            0, 0, self, 'sql_help_about')
134        self.aboutAct.setStatusTip(self.tr(
135            'Display information about this software'))
136        self.aboutAct.setWhatsThis(self.tr(
137            """<b>About</b>"""
138            """<p>Display some information about this software.</p>"""
139        ))
140        self.aboutAct.triggered.connect(self.__about)
141        self.__actions.append(self.aboutAct)
142
143        self.aboutQtAct = E5Action(
144            self.tr('About Qt'),
145            self.tr('About &Qt'),
146            0, 0, self, 'sql_help_about_qt')
147        self.aboutQtAct.setStatusTip(
148            self.tr('Display information about the Qt toolkit'))
149        self.aboutQtAct.setWhatsThis(self.tr(
150            """<b>About Qt</b>"""
151            """<p>Display some information about the Qt toolkit.</p>"""
152        ))
153        self.aboutQtAct.triggered.connect(self.__aboutQt)
154        self.__actions.append(self.aboutQtAct)
155
156    def __initMenus(self):
157        """
158        Private method to create the menus.
159        """
160        mb = self.menuBar()
161
162        menu = mb.addMenu(self.tr('&File'))
163        menu.setTearOffEnabled(True)
164        menu.addAction(self.addConnectionAct)
165        menu.addSeparator()
166        menu.addAction(self.exitAct)
167
168        mb.addSeparator()
169
170        menu = mb.addMenu(self.tr('&Help'))
171        menu.setTearOffEnabled(True)
172        menu.addAction(self.aboutAct)
173        menu.addAction(self.aboutQtAct)
174
175    def __initToolbars(self):
176        """
177        Private method to create the toolbars.
178        """
179        filetb = self.addToolBar(self.tr("File"))
180        filetb.setObjectName("FileToolBar")
181        filetb.setIconSize(UI.Config.ToolBarIconSize)
182        filetb.addAction(self.addConnectionAct)
183        filetb.addSeparator()
184        filetb.addAction(self.exitAct)
185
186    def __about(self):
187        """
188        Private slot to show the about information.
189        """
190        E5MessageBox.about(
191            self,
192            self.tr("SQL Browser"),
193            self.tr(
194                """<h3>About SQL Browser</h3>"""
195                """<p>The SQL browser window is a little tool to examine """
196                """the data and the schema of a database and to execute """
197                """queries on a database.</p>"""
198            )
199        )
200
201    def __aboutQt(self):
202        """
203        Private slot to show info about Qt.
204        """
205        E5MessageBox.aboutQt(self, self.tr("SQL Browser"))
206