Browse Source

Settings now stored in QtSettings. Added settings window. Re-starts on config changes. Allow running with empty config. Fixed windows not being centered and having the wrong size after opening.

Thomas Buck 3 years ago
parent
commit
3c2b46da95
2 changed files with 171 additions and 41 deletions
  1. 0
    1
      README.md
  2. 171
    40
      octotray

+ 0
- 1
README.md View File

12
 	sudo cp de.xythobuz.octotray.desktop /usr/share/applications/de.xythobuz.octotray.desktop
12
 	sudo cp de.xythobuz.octotray.desktop /usr/share/applications/de.xythobuz.octotray.desktop
13
 
13
 
14
 Then run it from your desktop environment menu or even add it to the autostart there.
14
 Then run it from your desktop environment menu or even add it to the autostart there.
15
-

+ 171
- 40
octotray View File

16
 import urllib.parse
16
 import urllib.parse
17
 import urllib.request
17
 import urllib.request
18
 from PyQt5 import QtWidgets, QtGui, QtCore, QtNetwork
18
 from PyQt5 import QtWidgets, QtGui, QtCore, QtNetwork
19
-from PyQt5.QtWidgets import QSystemTrayIcon, QAction, QMenu, QMessageBox, QWidget, QLabel, QVBoxLayout, QHBoxLayout, QDesktopWidget, QSizePolicy, QSlider, QLayout
19
+from PyQt5.QtWidgets import QSystemTrayIcon, QAction, QMenu, QMessageBox, QWidget, QLabel, QVBoxLayout, QHBoxLayout, QDesktopWidget, QSizePolicy, QSlider, QLayout, QTableWidget, QTableWidgetItem, QPushButton
20
 from PyQt5.QtGui import QIcon, QPixmap, QImageReader, QDesktopServices
20
 from PyQt5.QtGui import QIcon, QPixmap, QImageReader, QDesktopServices
21
-from PyQt5.QtCore import QCoreApplication, QSettings, QUrl, QTimer, QSize, Qt
21
+from PyQt5.QtCore import QCoreApplication, QSettings, QUrl, QTimer, QSize, Qt, QSettings
22
+
23
+class SettingsWindow(QWidget):
24
+    def __init__(self, parent, *args, **kwargs):
25
+        super(SettingsWindow, self).__init__(*args, **kwargs)
26
+        self.parent = parent
27
+
28
+        self.setWindowTitle(parent.name + " Settings")
29
+        self.setWindowIcon(parent.icon)
30
+
31
+        box = QVBoxLayout()
32
+        self.setLayout(box)
33
+
34
+        buttons = QHBoxLayout()
35
+        box.addLayout(buttons, 0)
36
+
37
+        self.add = QPushButton("&Add Printer")
38
+        self.add.clicked.connect(self.addPrinter)
39
+        buttons.addWidget(self.add)
40
+
41
+        self.remove = QPushButton("&Remove Printer")
42
+        self.remove.clicked.connect(self.removePrinter)
43
+        buttons.addWidget(self.remove)
44
+
45
+        printers = self.parent.readSettings()
46
+        self.rows = len(printers)
47
+        self.table = QTableWidget(self.rows, 2)
48
+        box.addWidget(self.table, 1)
49
+
50
+        for i in range(0, self.rows):
51
+            p = printers[i]
52
+            for j in range(0, 2):
53
+                item = QTableWidgetItem(p[j])
54
+                self.table.setItem(i, j, item)
55
+
56
+        self.table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
57
+        self.table.resizeColumnsToContents()
58
+
59
+    def tableToList(self):
60
+        printers = []
61
+        for i in range(0, self.rows):
62
+            p = [self.table.item(i, 0).text(), self.table.item(i, 1).text()]
63
+            printers.append(p)
64
+        return printers
65
+
66
+    def closeEvent(self, event):
67
+        oldPrinters = [item[0:2] for item in self.parent.printers]
68
+        newPrinters = self.tableToList()
69
+        if oldPrinters != newPrinters:
70
+            r = self.parent.showDialog(self.parent.name + " Settings Changed", "Do you want to save the new list of printers?", "This will restart the application!", True, False, False)
71
+            if r == True:
72
+                self.parent.writeSettings(newPrinters)
73
+                QCoreApplication.exit(42)
74
+        self.parent.removeSettingsWindow()
75
+
76
+    def addPrinter(self):
77
+        self.rows += 1
78
+        self.table.setRowCount(self.rows)
79
+        self.table.setItem(self.rows - 1, 0, QTableWidgetItem("HOSTNAME"))
80
+        self.table.setItem(self.rows - 1, 1, QTableWidgetItem("API_KEY"))
81
+
82
+    def removePrinter(self):
83
+        r = self.table.currentRow()
84
+        if (r >= 0) and (r < self.rows):
85
+            self.rows -= 1
86
+            self.table.removeRow(r)
22
 
87
 
23
 class AspectRatioPixmapLabel(QLabel):
88
 class AspectRatioPixmapLabel(QLabel):
24
     def __init__(self, *args, **kwargs):
89
     def __init__(self, *args, **kwargs):
54
     addSize = 100
119
     addSize = 100
55
     reloadOn = True
120
     reloadOn = True
56
 
121
 
57
-    def __init__(self, parent, name, icon, app, manager, printer, *args, **kwargs):
122
+    def __init__(self, parent, printer, *args, **kwargs):
58
         super(CamWindow, self).__init__(*args, **kwargs)
123
         super(CamWindow, self).__init__(*args, **kwargs)
59
-        self.app = app
60
-        self.manager = manager
124
+        self.app = parent.app
125
+        self.manager = parent.manager
61
         self.manager.finished.connect(self.handleResponse)
126
         self.manager.finished.connect(self.handleResponse)
62
         self.parent = parent
127
         self.parent = parent
63
         self.printer = printer
128
         self.printer = printer
64
         self.host = self.printer[0]
129
         self.host = self.printer[0]
65
         self.url = "http://" + self.host + ":8080/?action=snapshot"
130
         self.url = "http://" + self.host + ":8080/?action=snapshot"
66
 
131
 
67
-        self.setWindowTitle(name + " Webcam Stream")
68
-        self.setWindowIcon(icon)
132
+        self.setWindowTitle(parent.name + " Webcam Stream")
133
+        self.setWindowIcon(parent.icon)
69
 
134
 
70
         box = QVBoxLayout()
135
         box = QVBoxLayout()
71
         self.setLayout(box)
136
         self.setLayout(box)
173
     iconPath = "/usr/share/pixmaps/"
238
     iconPath = "/usr/share/pixmaps/"
174
     iconName = "octotray_icon.png"
239
     iconName = "octotray_icon.png"
175
 
240
 
176
-    # 0=host, 1=key
177
-    # (2=system-commands, 3=menu, 4...=actions)
178
-    printers = [
179
-        [ "PRINTER_HOST_HERE", "PRINTER_API_KEY_HERE" ]
180
-    ]
241
+    networkTimeout = 2.0 # in s
242
+
243
+    # list of lists, inner lists contain printer data:
244
+    # 0=host 1=key (2=system-commands 3=menu 4+=actions)
245
+    printers = []
181
     
246
     
182
     statesWithWarning = [
247
     statesWithWarning = [
183
         "Printing", "Pausing", "Paused"
248
         "Printing", "Pausing", "Paused"
184
     ]
249
     ]
185
 
250
 
186
     camWindows = []
251
     camWindows = []
252
+    settingsWindow = None
187
 
253
 
188
-    def __init__(self):
189
-        self.app = QtWidgets.QApplication(sys.argv)
254
+    def __init__(self, app):
190
         QCoreApplication.setApplicationName(self.name)
255
         QCoreApplication.setApplicationName(self.name)
256
+        self.app = app
191
 
257
 
192
         if not QSystemTrayIcon.isSystemTrayAvailable():
258
         if not QSystemTrayIcon.isSystemTrayAvailable():
193
             self.showDialog("OctoTray Error", "System Tray is not available on this platform!", "", False, False, True)
259
             self.showDialog("OctoTray Error", "System Tray is not available on this platform!", "", False, False, True)
195
 
261
 
196
         self.manager = QtNetwork.QNetworkAccessManager()
262
         self.manager = QtNetwork.QNetworkAccessManager()
197
         self.menu = QMenu()
263
         self.menu = QMenu()
264
+        self.printers = self.readSettings()
198
 
265
 
199
         unknownCount = 0
266
         unknownCount = 0
200
         for p in self.printers:
267
         for p in self.printers:
243
             p.append(action)
310
             p.append(action)
244
             menu.addAction(action)
311
             menu.addAction(action)
245
 
312
 
246
-        if (len(self.printers) <= 0) or (unknownCount >= len(self.printers)):
247
-            self.showDialog("OctoTray Error", "No printers available!", "", False, False, True)
248
-            sys.exit(0)
313
+        self.settingsAction = QAction("&Settings")
314
+        self.settingsAction.triggered.connect(self.showSettingsAction)
315
+        self.menu.addAction(self.settingsAction)
249
 
316
 
250
         self.quitAction = QAction("&Quit")
317
         self.quitAction = QAction("&Quit")
251
         self.quitAction.triggered.connect(self.exit)
318
         self.quitAction.triggered.connect(self.exit)
252
         self.menu.addAction(self.quitAction)
319
         self.menu.addAction(self.quitAction)
253
 
320
 
254
-        iconPathName = ""
321
+        self.iconPathName = ""
255
         if os.path.isfile(self.iconName):
322
         if os.path.isfile(self.iconName):
256
-            iconPathName = self.iconName
323
+            self.iconPathName = self.iconName
257
         elif os.path.isfile(self.iconPath + self.iconName):
324
         elif os.path.isfile(self.iconPath + self.iconName):
258
-            iconPathName = self.iconPath + self.iconName
325
+            self.iconPathName = self.iconPath + self.iconName
259
         else:
326
         else:
260
             self.showDialog("OctoTray Error", "Icon file has not been found! found", "", False, False, True)
327
             self.showDialog("OctoTray Error", "Icon file has not been found! found", "", False, False, True)
261
             sys.exit(0)
328
             sys.exit(0)
262
 
329
 
263
         self.icon = QIcon()
330
         self.icon = QIcon()
264
-        pic = QPixmap(32, 32)
265
-        pic.load(iconPathName)
266
-        self.icon = QIcon(pic)
267
-
268
-        trayIcon = QSystemTrayIcon(self.icon)
269
-        trayIcon.setToolTip(self.name + " " + self.version)
270
-        trayIcon.setContextMenu(self.menu)
271
-        trayIcon.setVisible(True)
272
-
273
-        sys.exit(self.app.exec_())
331
+        self.pic = QPixmap(32, 32)
332
+        self.pic.load(self.iconPathName)
333
+        self.icon = QIcon(self.pic)
334
+
335
+        self.trayIcon = QSystemTrayIcon(self.icon)
336
+        self.trayIcon.setToolTip(self.name + " " + self.version)
337
+        self.trayIcon.setContextMenu(self.menu)
338
+        self.trayIcon.setVisible(True)
339
+
340
+    def readSettings(self):
341
+        settings = QSettings(self.vendor, self.name)
342
+        printers = []
343
+        l = settings.beginReadArray("printers")
344
+        for i in range(0, l):
345
+            settings.setArrayIndex(i)
346
+            p = []
347
+            p.append(settings.value("host"))
348
+            p.append(settings.value("key"))
349
+            printers.append(p)
350
+        settings.endArray()
351
+        return printers
352
+
353
+    def writeSettings(self, printers):
354
+        settings = QSettings(self.vendor, self.name)
355
+        settings.remove("printers")
356
+        settings.beginWriteArray("printers")
357
+        for i in range(0, len(printers)):
358
+            p = printers[i]
359
+            settings.setArrayIndex(i)
360
+            settings.setValue("host", p[0])
361
+            settings.setValue("key", p[1])
362
+        settings.endArray()
363
+        del settings
274
 
364
 
275
     def openBrowser(self, url):
365
     def openBrowser(self, url):
276
         QDesktopServices.openUrl(QUrl("http://" + url))
366
         QDesktopServices.openUrl(QUrl("http://" + url))
312
             data = content.encode('ascii')
402
             data = content.encode('ascii')
313
             request = urllib.request.Request(url, data, headers)
403
             request = urllib.request.Request(url, data, headers)
314
         try:
404
         try:
315
-            with urllib.request.urlopen(request, None, 1.0) as response:
405
+            with urllib.request.urlopen(request, None, self.networkTimeout) as response:
316
                 text = response.read()
406
                 text = response.read()
317
                 return text
407
                 return text
408
+        except urllib.error.URLError:
409
+            pass
318
         except urllib.error.HTTPError:
410
         except urllib.error.HTTPError:
319
             pass
411
             pass
320
         return ""
412
         return ""
508
                 cw.activateWindow()
600
                 cw.activateWindow()
509
                 return
601
                 return
510
 
602
 
511
-        window = CamWindow(self, self.name, self.icon, self.app, self.manager, item)
603
+        window = CamWindow(self, item)
512
         self.camWindows.append(window)
604
         self.camWindows.append(window)
513
 
605
 
514
-        screenGeometry = QDesktopWidget().screenGeometry()
515
-        width = screenGeometry.width()
516
-        height = screenGeometry.height()
517
-        x = (width - window.width()) / 2
518
-        y = (height - window.height()) / 2
519
-        window.setGeometry(int(x), int(y), int(window.width()), int(window.height()))
520
-
521
         window.show()
606
         window.show()
522
         window.activateWindow()
607
         window.activateWindow()
523
 
608
 
609
+        screenGeometry = QDesktopWidget().screenGeometry()
610
+        x = (screenGeometry.width() - window.width()) / 2
611
+        y = (screenGeometry.height() - window.height()) / 2
612
+        x += screenGeometry.x()
613
+        y += screenGeometry.y()
614
+        window.setGeometry(int(x), int(y), int(window.width()), int(window.height()))
615
+
524
     def removeWebcamWindow(self, window):
616
     def removeWebcamWindow(self, window):
525
         self.camWindows.remove(window)
617
         self.camWindows.remove(window)
526
 
618
 
619
+    def showSettingsAction(self):
620
+        if self.settingsWindow != None:
621
+            self.settingsWindow.show()
622
+            self.settingsWindow.activateWindow()
623
+            return
624
+
625
+        self.settingsWindow = SettingsWindow(self)
626
+        self.settingsWindow.show()
627
+        self.settingsWindow.activateWindow()
628
+
629
+        screenGeometry = QDesktopWidget().screenGeometry()
630
+        x = (screenGeometry.width() - self.settingsWindow.width()) / 2
631
+        y = (screenGeometry.height() - self.settingsWindow.height()) / 2
632
+        x += screenGeometry.x()
633
+        y += screenGeometry.y()
634
+        self.settingsWindow.setGeometry(int(x), int(y), int(self.settingsWindow.width()), int(self.settingsWindow.height()))
635
+
636
+    def removeSettingsWindow(self):
637
+        self.settingsWindow = None
638
+
639
+    def closeAll(self):
640
+        for cw in self.camWindows:
641
+            cw.close()
642
+
643
+        if self.settingsWindow != None:
644
+            self.settingsWindow.close()
645
+
646
+        self.trayIcon.setVisible(False)
647
+
527
 if __name__ == "__main__":
648
 if __name__ == "__main__":
528
-    tray = OctoTray()
649
+    app = QtWidgets.QApplication(sys.argv)
650
+
651
+    tray = OctoTray(app)
652
+    rc = app.exec_()
653
+
654
+    while rc == 42:
655
+        tray.closeAll()
656
+        tray = OctoTray(app)
657
+        rc = app.exec_()
658
+
659
+    sys.exit(rc)

Loading…
Cancel
Save