main.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. ########################################################################
  2. # Searx-qt - Lightweight desktop application for SearX.
  3. # Copyright (C) 2020 CYBERDEViL
  4. #
  5. # This file is part of Searx-qt.
  6. #
  7. # Searx-qt is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # Searx-qt is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ########################################################################
  21. from PyQt5.QtWidgets import (
  22. QApplication,
  23. QAction,
  24. QSplitter,
  25. QMenuBar,
  26. QMenu,
  27. QMainWindow,
  28. QVBoxLayout,
  29. QWidget,
  30. QStatusBar,
  31. QLabel
  32. )
  33. from PyQt5.QtCore import Qt, QSettings, QByteArray, QSize
  34. from searxqt.models.instances import (
  35. InstancesModel,
  36. InstanceModelFilter,
  37. InstanceSelecterModel
  38. )
  39. from searxqt.models.settings import SettingsModel
  40. from searxqt.models.search import SearchModel
  41. from searxqt.views.instances import InstancesView
  42. from searxqt.views.settings import SettingsWindow
  43. from searxqt.views.search import SearchContainer
  44. from searxqt.views import about
  45. class MainWindow(QMainWindow):
  46. def __init__(self, *args, **kwargs):
  47. QMainWindow.__init__(self, *args, **kwargs)
  48. self.setWindowTitle("SearX-Qt")
  49. self.settings = QSettings('CYBERDEViL', 'searx-qt', self)
  50. self._settingsModel = SettingsModel(self)
  51. self._instancesModel = InstancesModel(
  52. requestSettings=self._settingsModel.requests, parent=self)
  53. self.instanceFilter = InstanceModelFilter(
  54. self._instancesModel, self)
  55. self.instanceSelecter = InstanceSelecterModel(self.instanceFilter)
  56. self._settingsWindow = None
  57. self._searchModel = SearchModel(self._settingsModel.requests, self)
  58. # -- Menu bar
  59. menubar = QMenuBar(self)
  60. # Menu file
  61. menuFile = QMenu(menubar)
  62. menuFile.setTitle("File")
  63. saveAction = QAction("Save", menuFile)
  64. menuFile.addAction(saveAction)
  65. saveAction.setShortcut('Ctrl+S')
  66. saveAction.triggered.connect(self.saveSettings)
  67. actionExit = QAction("Exit", menuFile)
  68. menuFile.addAction(actionExit)
  69. actionExit.setShortcut('Ctrl+Q')
  70. actionExit.triggered.connect(self.__quit)
  71. menubar.addAction(menuFile.menuAction())
  72. # Menu settings
  73. settingsAction = QAction("Settings", menubar)
  74. menubar.addAction(settingsAction)
  75. settingsAction.triggered.connect(self._openSettingsWindow)
  76. # Menu about dialog
  77. aboutAction = QAction("About", menubar)
  78. menubar.addAction(aboutAction)
  79. aboutAction.triggered.connect(self._openAboutDialog)
  80. self.setMenuBar(menubar)
  81. # -- End menu bar
  82. # -- Status bar
  83. self.statusBar = QStatusBar(self)
  84. self._statusInstanceLabel = QLabel(self)
  85. self.statusBar.addPermanentWidget(self._statusInstanceLabel)
  86. self.setStatusBar(self.statusBar)
  87. # -- End status bar
  88. centralWidget = QWidget(self)
  89. layout = QVBoxLayout(centralWidget)
  90. self.setCentralWidget(centralWidget)
  91. self.splitter = QSplitter(centralWidget)
  92. self.splitter.setOrientation(Qt.Horizontal)
  93. layout.addWidget(self.splitter)
  94. self.searchContainer = SearchContainer(
  95. self._searchModel, self.instanceFilter,
  96. self.instanceSelecter, self.splitter)
  97. self.instancesWidget = InstancesView(
  98. self.instanceFilter, self.instanceSelecter, self.splitter)
  99. self.instanceSelecter.instanceChanged.connect(self.__instanceChanged)
  100. self.resize(800, 600)
  101. self.loadSettings()
  102. def __quit(self):
  103. QApplication.quit()
  104. def __instanceChanged(self, url):
  105. self._statusInstanceLabel.setText("Instance: {0}".format(url))
  106. def closeEvent(self, event):
  107. self.saveSettings()
  108. QApplication.closeAllWindows()
  109. def _openAboutDialog(self):
  110. about.show(self)
  111. def _openSettingsWindow(self):
  112. if not self._settingsWindow:
  113. self._settingsWindow = SettingsWindow(self._settingsModel)
  114. self._settingsWindow.show()
  115. def loadSettings(self):
  116. self.resize(
  117. self.settings.value('windowSize', QSize(), QSize)
  118. )
  119. self.splitter.restoreState(
  120. self.settings.value('splitterState', QByteArray(), QByteArray)
  121. )
  122. self._instancesModel.loadSettings(
  123. self.settings.value('instancesData', dict(), dict)
  124. )
  125. self._settingsModel.loadSettings(
  126. self.settings.value('settingsRequests', dict(), dict)
  127. )
  128. self.instanceFilter.loadSettings(
  129. self.settings.value('instanceFilter', dict(), dict)
  130. )
  131. self.instancesWidget.loadSettings(
  132. self.settings.value('instancesView', dict(), dict)
  133. )
  134. # Load the instanceSelecter after the instancesView and
  135. # instanceFilter, they depend on it. (Connections are wired that
  136. # way)
  137. self.instanceSelecter.loadSettings(
  138. self.settings.value('instanceSelecter', dict(), dict)
  139. )
  140. self.searchContainer.loadSettings(
  141. self.settings.value('searchView', dict(), dict)
  142. )
  143. self._searchModel.loadSettings(
  144. self.settings.value('searchModel', dict(), dict)
  145. )
  146. def saveSettings(self):
  147. self.settings.setValue('windowSize', self.size())
  148. self.settings.setValue('splitterState', self.splitter.saveState())
  149. self.settings.setValue('instancesData', self._instancesModel.data())
  150. self.settings.setValue(
  151. 'settingsRequests',
  152. self._settingsModel.saveSettings()
  153. )
  154. self.settings.setValue(
  155. 'instanceFilter',
  156. self.instanceFilter.saveSettings()
  157. )
  158. self.settings.setValue(
  159. 'instanceSelecter',
  160. self.instanceSelecter.saveSettings()
  161. )
  162. self.settings.setValue(
  163. 'instancesView',
  164. self.instancesWidget.saveSettings()
  165. )
  166. self.settings.setValue(
  167. 'searchView',
  168. self.searchContainer.saveSettings()
  169. )
  170. self.settings.setValue(
  171. 'searchModel',
  172. self._searchModel.saveSettings()
  173. )