A gui application used for interactive upgrade reminders on Debian. I no longer use it and will not push changes.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 

163 líneas
5.2 KiB

  1. #!/usr/bin/python3
  2. from PySide2.QtWidgets import (QApplication, QLabel,
  3. QPushButton, QSlider,
  4. QLineEdit, QWidget, QVBoxLayout, QHBoxLayout,
  5. QDialog, QGroupBox, QTabWidget, QErrorMessage,
  6. QListWidgetItem, QGridLayout, QTextEdit,
  7. QComboBox, QToolBar, QInputDialog, QAction,
  8. QStackedWidget, QTextBrowser)
  9. from PySide2.QtCore import (Qt, QThread, Signal, QDir, QProcess,
  10. QCoreApplication)
  11. from PySide2.QtGui import (QIcon, QMovie)
  12. import sys, subprocess, trio
  13. class UpdatePrompt(QDialog):
  14. def __init__(self):
  15. super().__init__()
  16. self.makeView()
  17. return
  18. def makeView(self):
  19. layout = QVBoxLayout()
  20. btnLayout = QHBoxLayout()
  21. self.centStack = QStackedWidget()
  22. self.updateButton = QPushButton('Update')
  23. self.cancelButton = QPushButton('Cancel')
  24. notifyLabel = QLabel('There are upgrades scheduled')
  25. self.inputBox = QLineEdit()
  26. self.outputBox = QTextBrowser()
  27. #refreshIcon = QIcon.fromTheme('process-working')
  28. self.refreshIcon = QMovie('assets/spin3.gif')
  29. refreshAnimation = QLabel()
  30. layout.addWidget(notifyLabel)
  31. layout.addWidget(self.centStack)
  32. layout.addWidget(self.inputBox)
  33. layout.addLayout(btnLayout)
  34. btnLayout.addWidget(self.cancelButton)
  35. btnLayout.addWidget(self.updateButton)
  36. self.centStack.addWidget(refreshAnimation)
  37. self.centStack.addWidget(self.outputBox)
  38. refreshAnimation.setMovie(self.refreshIcon)
  39. refreshAnimation.setAlignment(Qt.AlignCenter)
  40. self.refreshIcon.start()
  41. self.inputBox.setEchoMode(QLineEdit.Password)
  42. self.inputBox.setFocus()
  43. self.inputBox.returnPressed.connect(self.pkgUpdates)
  44. self.updateButton.clicked.connect(self.pkgUpdates)
  45. self.cancelButton.clicked.connect(self.cancelUpdates)
  46. self.updateButton.setDefault(True)
  47. self.centStack.setCurrentIndex(1)
  48. notifyLabel.setAlignment(Qt.AlignTop)
  49. self.outputBox.setReadOnly(True)
  50. #self.outputBox.setAlignment(Qt.AlignTop)
  51. self.setWindowTitle('Package Upgrades')
  52. self.setLayout(layout)
  53. self.resize(450, 250)
  54. return
  55. async def asetup(self, password):
  56. async with trio.open_nursery() as nursery:
  57. finishedState = trio.Event()
  58. nursery.start_soon(self.upProc, password, 'update', finishedState)
  59. #nursery.start_soon(self.KEAlive, finishedState)
  60. return
  61. async def upProc(self, password, cmd, finishedState):
  62. proc = await trio.open_process(['sudo', '-S', 'apt-get', cmd, '-y'],
  63. stdin=subprocess.PIPE, stdout=subprocess.PIPE,
  64. stderr=subprocess.STDOUT)
  65. await proc.stdin.send_all((password + '\n').encode())
  66. while (proc.poll() == None):
  67. QCoreApplication.processEvents()
  68. await trio.sleep(0.1)
  69. result = ''
  70. result = await self.pullOutput(proc)
  71. self.appendToOutput(result)
  72. proc.terminate()
  73. if (cmd == 'update'):
  74. await self.upProc(password, 'upgrade', finishedState)
  75. finishedState.set()
  76. return
  77. async def pullOutput(self, proc):
  78. x = await proc.stdout.receive_some()
  79. x = x.decode()
  80. result = ''
  81. while (x != ''):
  82. QCoreApplication.processEvents()
  83. result = result + x
  84. x = await proc.stdout.receive_some()
  85. x = x.decode()
  86. return result
  87. async def KEAlive(self, finishedState):
  88. while finishedState.is_set():
  89. QCoreApplication.processEvents()
  90. trio.sleep(0.1)
  91. return
  92. return
  93. def appendToOutput(self, add):
  94. currentText = self.outputBox.toPlainText()
  95. self.outputBox.setText(currentText + 'Running updates\n' + add + '\n')
  96. print (add)
  97. return
  98. def pkgUpdates(self):
  99. self.centStack.setCurrentIndex(0)
  100. self.refreshIcon.start()
  101. QCoreApplication.processEvents()
  102. password = self.inputBox.text()
  103. if (password == ''):
  104. self.passError('The password field cannot be empty')
  105. return
  106. self.inputBox.clear()
  107. self.inputBox.setDisabled(True)
  108. self.updateButton.setDisabled(True)
  109. trio.run(self.asetup, password)
  110. self.centStack.setCurrentIndex(1)
  111. self.refreshIcon.stop()
  112. self.updateButton.setDisabled(False)
  113. self.inputBox.setDisabled(False)
  114. return
  115. def passError(self, s):
  116. passError = QDialog(self)
  117. msg = QLabel(s)
  118. layout = QVBoxLayout()
  119. layout.addWidget(msg)
  120. passError.setLayout(layout)
  121. okBtn = QPushButton('OK')
  122. okBtn.clicked.connect(passError.reject)
  123. layout.addWidget(okBtn)
  124. passError.exec_()
  125. return
  126. def cancelUpdates(self):
  127. #Needs way of closing subprocess during async run
  128. self.reject()
  129. return
  130. if __name__ == '__main__':
  131. app = QApplication([])
  132. view = UpdatePrompt()
  133. view.show()
  134. sys.exit(app.exec_())