개정판 26b3fef2
issue #1396: 자동 업데이트 기능 추가
Change-Id: I2ad6dde79152bc08301ef82336df271d2c2bbafb
App.spec | ||
---|---|---|
1 | 1 |
# -*- mode: python -*- |
2 | 2 |
|
3 |
winsparkle = '.venv\\Lib\\site-packages\\pywinsparkle\\libs\\x64\\WinSparkle.dll' |
|
3 | 4 |
block_cipher = None |
4 | 5 |
|
5 | 6 |
a = Analysis(['.\\DTI_PID\\DTI_PID\\App.py','.\\DTI_PID\\DTI_PID\\TrainingImageListDialog.py'], |
... | ... | |
7 | 8 |
binaries=[('.\\DTI_PID\\DTI_PID\\bin64\\*.exe', 'bin64'), |
8 | 9 |
('.\\DTI_PID\\DTI_PID\\bin64\\*.dll', 'bin64'), |
9 | 10 |
('.\\DTI_PID\\DTI_PID\\potrace.exe', '.'), |
11 |
(winsparkle, '.') |
|
10 | 12 |
], |
11 | 13 |
datas=[('.\\DTI_PID\\DTI_PID\\*.qss', '.'), |
12 | 14 |
('.\\DTI_PID\\DTI_PID\\*.pdf', '.'), |
DTI_PID/DTI_PID/App.py | ||
---|---|---|
2 | 2 |
""" This is application module """ |
3 | 3 |
import sys |
4 | 4 |
import os |
5 |
from pywinsparkle import pywinsparkle |
|
5 | 6 |
|
6 | 7 |
if hasattr(sys, 'frozen'): |
7 | 8 |
os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH'] |
... | ... | |
110 | 111 |
return None |
111 | 112 |
|
112 | 113 |
|
114 |
def no_update_found(): |
|
115 |
""" when no update has been found, close the updater""" |
|
116 |
print("No update found") |
|
117 |
print("Setting flag to shutdown PassagesUpdater") |
|
118 |
|
|
119 |
|
|
120 |
def found_update(): |
|
121 |
""" log that an update was found """ |
|
122 |
print("New Update Available") |
|
123 |
|
|
124 |
|
|
125 |
def encountered_error(): |
|
126 |
print("An error occurred") |
|
127 |
|
|
128 |
|
|
129 |
def update_cancelled(): |
|
130 |
""" when the update was cancelled, close the updater""" |
|
131 |
print("Update was cancelled") |
|
132 |
print("Setting flag to shutdown PassagesUpdater") |
|
133 |
|
|
134 |
|
|
135 |
def shutdown(): |
|
136 |
""" The installer is being launched signal the updater to shutdown """ |
|
137 |
|
|
138 |
# actually shutdown the app here |
|
139 |
sys.exit(0) |
|
140 |
|
|
141 |
|
|
142 |
def auto_update(update_url: str): |
|
143 |
"""auto update PAP""" |
|
144 |
import time |
|
145 |
|
|
146 |
# register callbacks |
|
147 |
pywinsparkle.win_sparkle_set_did_find_update_callback(found_update) |
|
148 |
pywinsparkle.win_sparkle_set_error_callback(encountered_error) |
|
149 |
pywinsparkle.win_sparkle_set_update_cancelled_callback(update_cancelled) |
|
150 |
pywinsparkle.win_sparkle_set_did_not_find_update_callback(no_update_found) |
|
151 |
pywinsparkle.win_sparkle_set_shutdown_request_callback(shutdown) |
|
152 |
|
|
153 |
# set application details |
|
154 |
version = QCoreApplication.applicationVersion() |
|
155 |
pywinsparkle.win_sparkle_set_appcast_url(update_url) |
|
156 |
pywinsparkle.win_sparkle_set_app_details(App.COMPANY, App.NAME, version) |
|
157 |
|
|
158 |
""" DSA 공개키 설정 |
|
159 |
if os.path.isfile('dsa_pub.pem'): |
|
160 |
with open('dsa_pub.pem', 'r') as file: |
|
161 |
pub_key = file.read() |
|
162 |
pywinsparkle.win_sparkle_set_dsa_pub_pem(pub_key) |
|
163 |
""" |
|
164 |
|
|
165 |
# initialize |
|
166 |
pywinsparkle.win_sparkle_init() |
|
167 |
|
|
168 |
# check for updates |
|
169 |
pywinsparkle.win_sparkle_check_update_with_ui() |
|
170 |
|
|
171 |
|
|
113 | 172 |
''' |
114 | 173 |
@history 18.04.23 Jeongwoo Change method to execute ProjectDialog(dlg.exec_()→dlg.showDialog()) |
115 | 174 |
''' |
... | ... | |
120 | 179 |
from MainWindow import MainWindow |
121 | 180 |
from ExceptionHandler import QExceptionHandler |
122 | 181 |
|
182 |
app_doc_data = AppDocData.instance() |
|
183 |
configs = app_doc_data.getAppConfigs('app', 'update_url') |
|
184 |
|
|
123 | 185 |
app = App(sys.argv) |
186 |
if configs and configs[0].value: |
|
187 |
auto_update(configs[0].value) |
|
124 | 188 |
|
125 | 189 |
""" log for unhandled exception """ |
126 | 190 |
app.exception_handler = QExceptionHandler() |
DTI_PID/DTI_PID/ProjectDialog.py | ||
---|---|---|
36 | 36 |
self.ui.comboBoxProjectUnit.setHidden(True) |
37 | 37 |
self.ui.label_3.setHidden(True) |
38 | 38 |
|
39 |
app_doc_data = AppDocData.instance() |
|
40 |
configs = app_doc_data.getAppConfigs('app', 'update_url') |
|
41 |
if configs and configs[0].value: |
|
42 |
self.ui.lineEditUpdateURL.setText(configs[0].value) |
|
43 |
|
|
39 | 44 |
def initComboBox(self): |
40 | 45 |
from AppDocData import AppDocData |
41 | 46 |
|
... | ... | |
66 | 71 |
|
67 | 72 |
def accept(self): |
68 | 73 |
""" accept project """ |
74 |
from AppDocData import Config |
|
75 |
|
|
76 |
app_doc_data = AppDocData.instance() |
|
77 |
|
|
69 | 78 |
index = self.ui.comboBox.currentIndex() |
70 | 79 |
project = self.ui.comboBox.itemData(index) |
71 | 80 |
prj_desc = self.ui.lineEditProjectDesc.text() |
... | ... | |
85 | 94 |
project.database.password = None |
86 | 95 |
project.database.file_path = os.path.join(project.getDbFilePath(), Project.DATABASE) |
87 | 96 |
|
88 |
AppDocData.instance().updateProjectUpdatedDate(project) |
|
97 |
app_doc_data.updateProjectUpdatedDate(project) |
|
98 |
|
|
99 |
configs = [Config('app', 'update_url', self.ui.lineEditUpdateURL.text())] |
|
100 |
app_doc_data.saveAppConfigs(configs) |
|
89 | 101 |
|
90 | 102 |
QDialog.accept(self) |
91 | 103 |
|
DTI_PID/DTI_PID/Project_UI.py | ||
---|---|---|
2 | 2 |
|
3 | 3 |
# Form implementation generated from reading ui file '.\UI\Project.ui' |
4 | 4 |
# |
5 |
# Created by: PyQt5 UI code generator 5.13.0
|
|
5 |
# Created by: PyQt5 UI code generator 5.15.4
|
|
6 | 6 |
# |
7 |
# WARNING! All changes made in this file will be lost! |
|
7 |
# WARNING: Any manual changes made to this file will be lost when pyuic5 is |
|
8 |
# run again. Do not edit this file unless you know what you are doing. |
|
8 | 9 |
|
9 | 10 |
|
10 | 11 |
from PyQt5 import QtCore, QtGui, QtWidgets |
... | ... | |
34 | 35 |
self.buttonBox.setFont(font) |
35 | 36 |
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) |
36 | 37 |
self.buttonBox.setObjectName("buttonBox") |
37 |
self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 1)
|
|
38 |
self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 1)
|
|
38 | 39 |
self.groupBoxDBType = QtWidgets.QGroupBox(ProjectDialog) |
39 | 40 |
self.groupBoxDBType.setObjectName("groupBoxDBType") |
40 | 41 |
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBoxDBType) |
... | ... | |
143 | 144 |
self.label_3.setObjectName("label_3") |
144 | 145 |
self.gridLayout_4.addWidget(self.label_3, 2, 0, 1, 1) |
145 | 146 |
self.gridLayout.addLayout(self.gridLayout_4, 0, 0, 1, 1) |
147 |
self.gridLayout_5 = QtWidgets.QGridLayout() |
|
148 |
self.gridLayout_5.setObjectName("gridLayout_5") |
|
149 |
self.label_4 = QtWidgets.QLabel(ProjectDialog) |
|
150 |
self.label_4.setObjectName("label_4") |
|
151 |
self.gridLayout_5.addWidget(self.label_4, 0, 0, 1, 1) |
|
152 |
self.lineEditUpdateURL = QtWidgets.QLineEdit(ProjectDialog) |
|
153 |
self.lineEditUpdateURL.setObjectName("lineEditUpdateURL") |
|
154 |
self.gridLayout_5.addWidget(self.lineEditUpdateURL, 0, 1, 1, 1) |
|
155 |
self.gridLayout.addLayout(self.gridLayout_5, 2, 0, 1, 1) |
|
146 | 156 |
|
147 | 157 |
self.retranslateUi(ProjectDialog) |
148 | 158 |
self.buttonBox.rejected.connect(ProjectDialog.reject) |
... | ... | |
172 | 182 |
self.label.setText(_translate("ProjectDialog", "Project Name")) |
173 | 183 |
self.label_2.setText(_translate("ProjectDialog", "Project Desc")) |
174 | 184 |
self.label_3.setText(_translate("ProjectDialog", "Project Unit")) |
185 |
self.label_4.setText(_translate("ProjectDialog", "Update URL : ")) |
|
175 | 186 |
import MainWindow_rc |
DTI_PID/DTI_PID/UI/Project.ui | ||
---|---|---|
37 | 37 |
<normaloff>:/newPrefix/project.png</normaloff>:/newPrefix/project.png</iconset> |
38 | 38 |
</property> |
39 | 39 |
<layout class="QGridLayout" name="gridLayout"> |
40 |
<item row="2" column="0">
|
|
40 |
<item row="3" column="0">
|
|
41 | 41 |
<widget class="QDialogButtonBox" name="buttonBox"> |
42 | 42 |
<property name="font"> |
43 | 43 |
<font> |
... | ... | |
239 | 239 |
</item> |
240 | 240 |
</layout> |
241 | 241 |
</item> |
242 |
<item row="2" column="0"> |
|
243 |
<layout class="QGridLayout" name="gridLayout_5"> |
|
244 |
<item row="0" column="0"> |
|
245 |
<widget class="QLabel" name="label_4"> |
|
246 |
<property name="text"> |
|
247 |
<string>Update URL : </string> |
|
248 |
</property> |
|
249 |
</widget> |
|
250 |
</item> |
|
251 |
<item row="0" column="1"> |
|
252 |
<widget class="QLineEdit" name="lineEditUpdateURL"/> |
|
253 |
</item> |
|
254 |
</layout> |
|
255 |
</item> |
|
242 | 256 |
</layout> |
243 | 257 |
</widget> |
244 | 258 |
<tabstops> |
DTI_PID/DTI_PID/requirements.txt | ||
---|---|---|
13 | 13 |
pytesseract==0.3.7 |
14 | 14 |
requests==2.25.1 |
15 | 15 |
Shapely==1.7.1 |
16 |
xlrd==1.2.0 |
|
16 |
xlrd==1.2.0 |
|
17 |
pywinsparkle==1.6.0 |
ID2.wxs | ||
---|---|---|
460 | 460 |
<Component Id="cmp876506411AF655401C5D9AD8E5F52EA6" Directory="INSTALLFOLDER" Guid="5E9F69D2-218E-4245-8C6E-78F29040E9F9" Win64="yes"> |
461 | 461 |
<File Id="fil21DE3060A3015F241292520DDA49CBB4" KeyPath="yes" Source=".\dist\App\_tkinter.pyd" /> |
462 | 462 |
</Component> |
463 |
|
|
464 |
<Component Id="cmp0523305FE9974D6F97EA71C8088909F7" Directory="INSTALLFOLDER" Guid="7810AA9F-65AF-4E37-AB35-98225176B378" Win64="yes"> |
|
465 |
<File Id="fil48ADB7DBD1764E3D98DD5C89E42BA084" KeyPath="yes" Source=".\dist\App\WinSparkle.dll" /> |
|
466 |
</Component> |
|
467 |
|
|
463 | 468 |
<Component Id="cmp4FA159BD48EFB80CD91D1617C562A2A0" Directory="dir59F9E3CEE744262828A1C345D9F97BD7" Guid="1579CFBB-9774-49DE-A00B-3BF3ACA189F6" Win64="yes"> |
464 | 469 |
<File Id="filBFCFFFB1D57447308C4D28C64B320987" KeyPath="yes" Source=".\dist\App\certifi\cacert.pem" /> |
465 | 470 |
</Component> |
appcast.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="utf-8"?> |
|
2 |
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle"> |
|
3 |
<channel> |
|
4 |
<title>HYTOS updates</title> |
|
5 |
<link>http://www.devdoftech.co.kr:8081/artifactory/ID2/appcast.xml</link> |
|
6 |
<description>Appcast for ID2 updates.</description> |
|
7 |
<language>en</language> |
|
8 |
<item> |
|
9 |
<title>Version 1.5.4</title> |
|
10 |
<sparkle:releaseNotesLink>http://devdoftech.co.kr:82/redmine/projects/id2/roadmap</sparkle:releaseNotesLink> |
|
11 |
<pubDate>Tue, 15 Sep 2012 18:11:12 +0200</pubDate> |
|
12 |
<enclosure url="http://www.devdoftech.co.kr:8081/artifactory/PAP/Setup/ID2-1.1.99.0.msi" |
|
13 |
sparkle:version="1.1.99" |
|
14 |
sparkle:dsaSignature="NEUCIB4lzlZTA5/rzWk7IWhw8I1vQPeFCHKLWZiZil4rm/fxAiEAtft5Aq79mhIZskVxvrFRQIjPaSnNsxNx+/kdFdS6mmM=" |
|
15 |
type="application/octet-stream"/> |
|
16 |
</item> |
|
17 |
</channel> |
|
18 |
</rss> |
내보내기 Unified diff