window.py
| 1 | import sys |
| 2 | from PyQt5.QtWidgets import * |
| 3 | from PyQt5.QtGui import * |
| 4 | from PyQt5.QtCore import * |
| 5 | |
| 6 | import json |
| 7 | import re |
| 8 | |
| 9 | from .manager import ProjectManager |
| 10 | from .spellcheckedit import SpellCheckEdit |
| 11 | |
| 12 | class ProjectTab(QTabWidget): |
| 13 | def __init__(self, parent = None): |
| 14 | super(ProjectTab, self).__init__(parent) |
| 15 | |
| 16 | class Interface: |
| 17 | def __init__(self): |
| 18 | self.value = None |
| 19 | |
| 20 | def ok(self): |
| 21 | self.value = self.qd.textValue() |
| 22 | |
| 23 | def askPassword(self): |
| 24 | self.qd = QInputDialog() |
| 25 | self.qd.setLabelText(self.qd.tr("Please enter your password:")) |
| 26 | self.qd.setTextEchoMode(QLineEdit.Password) |
| 27 | self.qd.accepted.connect(self.ok) |
| 28 | self.qd.exec_() |
| 29 | return self.value |
| 30 | |
| 31 | class ProjectView(QWidget): |
| 32 | def __init__(self, project, showTranslated = True, showUntranslated = True, showFuzzy = True, parent = None): |
| 33 | super(ProjectView, self).__init__(parent) |
| 34 | self.project = project |
| 35 | self.content = self.project.content() |
| 36 | self.currentContent = list(self.content.keys())[0] |
| 37 | self.showTranslated = showTranslated |
| 38 | self.showUntranslated = showUntranslated |
| 39 | self.showFuzzy = showFuzzy |
| 40 | self.initUI() |
| 41 | |
| 42 | def updateContent(self): |
| 43 | self.treeWidget.clear() |
| 44 | items = [] |
| 45 | for entry in self.content[self.currentContent]: |
| 46 | if entry.isObsolete(): |
| 47 | continue |
| 48 | cont = False |
| 49 | if self.showTranslated and entry.isTranslated(): |
| 50 | cont = True |
| 51 | if self.showUntranslated and not entry.isTranslated(): |
| 52 | cont = True |
| 53 | if self.showFuzzy and entry.isFuzzy(): |
| 54 | cont = True |
| 55 | if not cont: |
| 56 | continue |
| 57 | item = QTreeWidgetItem([entry.msgids[0], entry.msgstrs[0]]) |
| 58 | item.setData(0, Qt.UserRole, entry) |
| 59 | items.append(item) |
| 60 | self.treeWidget.insertTopLevelItems(0, items) |
| 61 | |
| 62 | def initUI(self): |
| 63 | vbox = QVBoxLayout() |
| 64 | self.setLayout(vbox) |
| 65 | model = QStandardItemModel() |
| 66 | self.treeWidget = QTreeWidget() |
| 67 | self.treeWidget.setColumnCount(2) |
| 68 | self.msgid = QTextEdit() |
| 69 | self.msgid.setReadOnly(True) |
| 70 | self.msgstr = QTextEdit() |
| 71 | self.filechooser = QComboBox() |
| 72 | for project in list(self.content.keys()): |
| 73 | self.filechooser.addItem(project) |
| 74 | self.filechooser.currentIndexChanged.connect(self.changefile) |
| 75 | |
| 76 | if self.filechooser.count() > 1: |
| 77 | vbox.addWidget(self.filechooser) |
| 78 | |
| 79 | self.updateContent() |
| 80 | vbox.addWidget(self.treeWidget, 4) |
| 81 | self.hbox = QHBoxLayout() |
| 82 | self.hbox.addWidget(self.msgid) |
| 83 | self.hbox.addWidget(self.msgstr) |
| 84 | vbox.addLayout(self.hbox, 1) |
| 85 | size = self.treeWidget.size() |
| 86 | self.treeWidget.setColumnWidth(0, size.width()/2) |
| 87 | self.treeWidget.currentItemChanged.connect(self.selectItem) |
| 88 | |
| 89 | def changefile(self): |
| 90 | self.currentContent = list(self.content.keys())[self.filechooser.currentIndex()] |
| 91 | self.updateContent() |
| 92 | |
| 93 | def selectItem(self, current, old): |
| 94 | if current == None: |
| 95 | return |
| 96 | data = current.data(0, Qt.UserRole) |
| 97 | self.hbox.removeWidget(self.msgid) |
| 98 | self.hbox.removeWidget(self.msgstr) |
| 99 | self.msgid.deleteLater() |
| 100 | self.msgstr.deleteLater() |
| 101 | |
| 102 | if len(data.msgstrs) > 1: |
| 103 | self.msgid = QTabWidget(); |
| 104 | self.msgstr = QTabWidget(); |
| 105 | singular = QTextEdit() |
| 106 | singular.setReadOnly(True) |
| 107 | singular.setText(data.msgids[0]) |
| 108 | plural = QTextEdit() |
| 109 | plural.setReadOnly(True) |
| 110 | plural.setText(data.msgids[1]) |
| 111 | self.msgid.addTab(singular, self.tr("Singular")) |
| 112 | self.msgid.addTab(plural, self.tr("Plural")) |
| 113 | i = 0 |
| 114 | for msgstr in data.msgstrs: |
| 115 | form = SpellCheckEdit(self.project.lang) |
| 116 | form.setText(msgstr) |
| 117 | form.textChanged.connect(self.modify) |
| 118 | self.msgstr.addTab(form, str(i)) |
| 119 | i=i+1 |
| 120 | else: |
| 121 | self.msgid = QTextEdit() |
| 122 | self.msgid.setReadOnly(True) |
| 123 | self.msgstr = SpellCheckEdit(self.project.lang) |
| 124 | self.msgid.setText(data.msgids[0]) |
| 125 | self.msgstr.setText(data.msgstrs[0]) |
| 126 | self.msgstr.textChanged.connect(self.modify) |
| 127 | self.hbox.addWidget(self.msgid) |
| 128 | self.hbox.addWidget(self.msgstr) |
| 129 | |
| 130 | def modify(self): |
| 131 | item = self.treeWidget.currentItem() |
| 132 | data = item.data(0, Qt.UserRole) |
| 133 | if self.msgstr.__class__.__name__ == "SpellCheckEdit": |
| 134 | msgstr = self.msgstr.toPlainText() |
| 135 | data.update(0, msgstr) |
| 136 | item.setText(1, msgstr) |
| 137 | else: |
| 138 | i = 0 |
| 139 | for msgstr in data.msgstrs: |
| 140 | data.update(i, self.msgstr.widget(i).toPlainText()) |
| 141 | i=i+1 |
| 142 | item.setText(1, data.msgstr_plural[0]) |
| 143 | |
| 144 | def save(self): |
| 145 | self.project.save() |
| 146 | |
| 147 | def send(self): |
| 148 | self.project.save() |
| 149 | self.project.send(Interface()) |
| 150 | |
| 151 | def askmerge(self, msgid, oldstr, newstr): |
| 152 | # TODO: Actually do something more intelligent |
| 153 | return newstr |
| 154 | |
| 155 | def update(self): |
| 156 | self.project.save() |
| 157 | self.project.update(self.askmerge) |
| 158 | self.content = self.project.content() |
| 159 | self.updateContent() |
| 160 | |
| 161 | def filter(self, showTranslated, showUntranslated, showFuzzy): |
| 162 | self.showTranslated = showTranslated |
| 163 | self.showUntranslated = showUntranslated |
| 164 | self.showFuzzy = showFuzzy |
| 165 | self.updateContent() |
| 166 | |
| 167 | class NewWindow(QDialog): |
| 168 | def __init__(self, manager, parent = None): |
| 169 | super().__init__(parent) |
| 170 | self.name = "" |
| 171 | self.lang = "" |
| 172 | self.system = 0 |
| 173 | self.manager = manager |
| 174 | self.askNew = False |
| 175 | self.initUI() |
| 176 | |
| 177 | def initUI(self): |
| 178 | hbox = QHBoxLayout() |
| 179 | predefinedbox = QVBoxLayout() |
| 180 | self.searchfield = QLineEdit() |
| 181 | predefinedbox.addWidget(self.searchfield) |
| 182 | self.predefinedprojects = QListWidget() |
| 183 | with open('offlate/data.json') as f: |
| 184 | self.projectdata = json.load(f) |
| 185 | for d in self.projectdata: |
| 186 | item = QListWidgetItem(d['name']) |
| 187 | item.setData(Qt.UserRole, d) |
| 188 | self.predefinedprojects.addItem(item) |
| 189 | predefinedbox.addWidget(self.predefinedprojects) |
| 190 | |
| 191 | contentbox = QVBoxLayout() |
| 192 | formbox = QGroupBox(self.tr("Project information")) |
| 193 | self.formLayout = QFormLayout() |
| 194 | formbox.setLayout(self.formLayout) |
| 195 | |
| 196 | self.nameWidget = QLineEdit() |
| 197 | self.langWidget = QLineEdit() |
| 198 | self.formLayout.addRow(QLabel(self.tr("Name:")), self.nameWidget) |
| 199 | self.formLayout.addRow(QLabel(self.tr("Target Language:")), self.langWidget) |
| 200 | self.combo = QComboBox() |
| 201 | self.combo.addItem(self.tr("The Translation Project")) |
| 202 | self.combo.addItem(self.tr("Transifex")) |
| 203 | self.formLayout.addRow(self.combo) |
| 204 | |
| 205 | self.nameWidget.textChanged.connect(self.modify) |
| 206 | self.langWidget.textChanged.connect(self.modify) |
| 207 | |
| 208 | hhbox = QHBoxLayout() |
| 209 | cancel = QPushButton(self.tr("Cancel")) |
| 210 | self.okbutton = QPushButton(self.tr("OK")) |
| 211 | self.okbutton.setEnabled(False) |
| 212 | hhbox.addWidget(cancel) |
| 213 | hhbox.addWidget(self.okbutton) |
| 214 | contentbox.addWidget(formbox) |
| 215 | contentbox.addLayout(hhbox) |
| 216 | hbox.addLayout(predefinedbox) |
| 217 | hbox.addLayout(contentbox) |
| 218 | |
| 219 | self.additionalFields = [] |
| 220 | self.additionalFields.append([]) |
| 221 | self.additionalFields.append([]) |
| 222 | self.transifexOrganisation = QLineEdit() |
| 223 | self.transifexOrganisation.textChanged.connect(self.modify) |
| 224 | transifexOrganisationLabel = QLabel(self.tr("Organization")) |
| 225 | self.additionalFields[1].append({'label': transifexOrganisationLabel, |
| 226 | 'widget': self.transifexOrganisation}) |
| 227 | |
| 228 | self.setLayout(hbox) |
| 229 | |
| 230 | self.predefinedprojects.currentItemChanged.connect(self.fill) |
| 231 | cancel.clicked.connect(self.close) |
| 232 | self.okbutton.clicked.connect(self.ok) |
| 233 | self.searchfield.textChanged.connect(self.filter) |
| 234 | self.combo.currentIndexChanged.connect(self.othersystem) |
| 235 | |
| 236 | def ok(self): |
| 237 | self.askNew = True |
| 238 | self.close() |
| 239 | |
| 240 | def fill(self): |
| 241 | item = self.predefinedprojects.currentItem() |
| 242 | data = item.data(Qt.UserRole) |
| 243 | self.nameWidget.setText(data['name']) |
| 244 | self.combo.setCurrentIndex(int(data['system'])) |
| 245 | if data['system'] == 1: |
| 246 | self.transifexOrganisation.setText(data['organisation']) |
| 247 | |
| 248 | def filter(self): |
| 249 | search = self.searchfield.text() |
| 250 | self.predefinedprojects.clear() |
| 251 | regexp = re.compile(".*"+search) |
| 252 | for d in self.projectdata: |
| 253 | if regexp.match(d['name']): |
| 254 | item = QListWidgetItem(d['name']) |
| 255 | item.setData(Qt.UserRole, d) |
| 256 | self.predefinedprojects.addItem(item) |
| 257 | |
| 258 | def modify(self): |
| 259 | enable = False |
| 260 | if self.nameWidget.text() != '' and self.langWidget.text() != '': |
| 261 | enable = True |
| 262 | for widget in self.additionalFields[self.combo.currentIndex()]: |
| 263 | if widget['widget'].text() == '': |
| 264 | enable = False |
| 265 | break |
| 266 | self.okbutton.setEnabled(enable) |
| 267 | |
| 268 | def wantNew(self): |
| 269 | return self.askNew |
| 270 | |
| 271 | def getProjectName(self): |
| 272 | return self.nameWidget.text() |
| 273 | |
| 274 | def getProjectLang(self): |
| 275 | return self.langWidget.text() |
| 276 | |
| 277 | def getProjectSystem(self): |
| 278 | return self.combo.currentIndex() |
| 279 | |
| 280 | def getProjectInfo(self): |
| 281 | if self.getProjectSystem() == 0: |
| 282 | return {} |
| 283 | if self.getProjectSystem() == 1: |
| 284 | return {'organization': self.additionalFields[1][0]['widget'].text()} |
| 285 | return {} |
| 286 | |
| 287 | def othersystem(self): |
| 288 | for system in self.additionalFields: |
| 289 | for widget in system: |
| 290 | self.formLayout.takeRow(widget['widget']) |
| 291 | widget['widget'].hide() |
| 292 | widget['label'].hide() |
| 293 | self.formLayout.invalidate() |
| 294 | for widget in self.additionalFields[self.combo.currentIndex()]: |
| 295 | self.formLayout.addRow(widget['label'], widget['widget']) |
| 296 | widget['widget'].show() |
| 297 | widget['label'].show() |
| 298 | self.modify() |
| 299 | |
| 300 | class SettingsWindow(QDialog): |
| 301 | def __init__(self, preferences, parent = None): |
| 302 | super().__init__(parent) |
| 303 | self.data = preferences |
| 304 | self.done = False |
| 305 | self.initUI() |
| 306 | |
| 307 | def initUI(self): |
| 308 | vbox = QVBoxLayout() |
| 309 | |
| 310 | tab = QTabWidget() |
| 311 | self.addTPTab(tab) |
| 312 | self.addTransifexTab(tab) |
| 313 | |
| 314 | buttonbox = QHBoxLayout() |
| 315 | cancel = QPushButton(self.tr("Cancel")) |
| 316 | ok = QPushButton(self.tr("OK")) |
| 317 | buttonbox.addWidget(cancel) |
| 318 | buttonbox.addWidget(ok) |
| 319 | |
| 320 | vbox.addWidget(tab) |
| 321 | vbox.addLayout(buttonbox) |
| 322 | self.setLayout(vbox) |
| 323 | cancel.clicked.connect(self.close) |
| 324 | ok.clicked.connect(self.ok) |
| 325 | |
| 326 | def addTransifexTab(self, tab): |
| 327 | formBox = QGroupBox(self.tr("Transifex")) |
| 328 | formLayout = QFormLayout() |
| 329 | self.TransifexToken = QLineEdit() |
| 330 | |
| 331 | if not "Transifex" in self.data: |
| 332 | self.data["Transifex"] = {} |
| 333 | try: |
| 334 | self.TransifexToken.setText(self.data["Transifex"]["token"]) |
| 335 | except Exception: |
| 336 | pass |
| 337 | |
| 338 | self.TransifexToken.textChanged.connect(self.updateTransifex) |
| 339 | label = QLabel(self.tr("You can get a token from <a href=\"#\">https://www.transifex.com/user/settings/api/</a>")) |
| 340 | label.linkActivated.connect(self.openTransifex) |
| 341 | |
| 342 | formLayout.addRow(QLabel(self.tr("Token:")), self.TransifexToken) |
| 343 | formLayout.addRow(label) |
| 344 | |
| 345 | formBox.setLayout(formLayout) |
| 346 | tab.addTab(formBox, "Transifex") |
| 347 | |
| 348 | def openTransifex(self): |
| 349 | QDesktopServices().openUrl(QUrl("https://www.transifex.com/user/settings/api/")); |
| 350 | |
| 351 | def updateTransifex(self): |
| 352 | self.data["Transifex"] = {} |
| 353 | self.data["Transifex"]["token"] = self.TransifexToken.text() |
| 354 | |
| 355 | def addTPTab(self, tab): |
| 356 | formBox = QGroupBox(self.tr("Translation Project")) |
| 357 | formLayout = QFormLayout() |
| 358 | |
| 359 | self.TPemail = QLineEdit() |
| 360 | self.TPuser = QLineEdit() |
| 361 | self.TPserver = QLineEdit() |
| 362 | self.TPfullname = QLineEdit() |
| 363 | |
| 364 | if not "TP" in self.data: |
| 365 | self.data["TP"] = {} |
| 366 | |
| 367 | if 'email' in self.data['TP']: |
| 368 | self.TPemail.setText(self.data["TP"]["email"]) |
| 369 | if 'user' in self.data['TP']: |
| 370 | self.TPuser.setText(self.data["TP"]["user"]) |
| 371 | if 'server' in self.data['TP']: |
| 372 | self.TPserver.setText(self.data["TP"]["server"]) |
| 373 | if 'fullname' in self.data['TP']: |
| 374 | self.TPfullname.setText(self.data["TP"]["fullname"]) |
| 375 | |
| 376 | self.TPemail.textChanged.connect(self.updateTP) |
| 377 | self.TPuser.textChanged.connect(self.updateTP) |
| 378 | self.TPserver.textChanged.connect(self.updateTP) |
| 379 | self.TPfullname.textChanged.connect(self.updateTP) |
| 380 | |
| 381 | formLayout.addRow(QLabel(self.tr("Email:")), self.TPemail) |
| 382 | formLayout.addRow(QLabel(self.tr("Server:")), self.TPserver) |
| 383 | formLayout.addRow(QLabel(self.tr("User Name:")), self.TPuser) |
| 384 | formLayout.addRow(QLabel(self.tr("Full Name (John Doe <john@doe.me>):")), self.TPfullname) |
| 385 | |
| 386 | formBox.setLayout(formLayout) |
| 387 | tab.addTab(formBox, "TP") |
| 388 | |
| 389 | def updateTP(self): |
| 390 | self.data["TP"] = {} |
| 391 | self.data["TP"]["email"] = self.TPemail.text() |
| 392 | self.data["TP"]["user"] = self.TPuser.text() |
| 393 | self.data["TP"]["server"] = self.TPserver.text() |
| 394 | self.data["TP"]["fullname"] = self.TPfullname.text() |
| 395 | |
| 396 | def ok(self): |
| 397 | self.done = True |
| 398 | self.close() |
| 399 | |
| 400 | class Window(QMainWindow): |
| 401 | def __init__(self): |
| 402 | super().__init__() |
| 403 | self.manager = ProjectManager() |
| 404 | self.initUI() |
| 405 | |
| 406 | def initOpenProjects(self, menu): |
| 407 | l = self.manager.listProjects() |
| 408 | for p in l: |
| 409 | name = p['name'] |
| 410 | act = QAction(name, self) |
| 411 | act.triggered.connect((lambda name: (lambda : self.open(name)))(name)) |
| 412 | menu.addAction(act) |
| 413 | |
| 414 | def open(self, name): |
| 415 | project = self.manager.getProject(name) |
| 416 | self.tabs.addTab(ProjectView(project), name) |
| 417 | |
| 418 | def save(self): |
| 419 | self.tabs.currentWidget().save() |
| 420 | |
| 421 | def new(self): |
| 422 | w = NewWindow(self.manager) |
| 423 | w.exec_() |
| 424 | if not w.wantNew(): |
| 425 | return |
| 426 | self.manager.createProject(w.getProjectName(), w.getProjectLang(), |
| 427 | w.getProjectSystem(), w.getProjectInfo()) |
| 428 | self.open(w.getProjectName()) |
| 429 | |
| 430 | def send(self): |
| 431 | self.tabs.currentWidget().send() |
| 432 | |
| 433 | def update(self): |
| 434 | self.tabs.currentWidget().update() |
| 435 | |
| 436 | def closeProject(self): |
| 437 | self.tabs.removeTab(self.tabs.currentIndex()) |
| 438 | |
| 439 | def settings(self): |
| 440 | w = SettingsWindow(self.manager.getConf()) |
| 441 | w.exec_() |
| 442 | if w.done: |
| 443 | self.manager.updateSettings(w.data) |
| 444 | |
| 445 | def filter(self): |
| 446 | for i in range(0, self.tabs.count()): |
| 447 | self.tabs.widget(i).filter( |
| 448 | self.showTranslatedAct.isChecked(), |
| 449 | self.showUntranslatedAct.isChecked(), |
| 450 | self.showFuzzyAct.isChecked()) |
| 451 | |
| 452 | def initUI(self): |
| 453 | # Build menu |
| 454 | exitAct = QAction(QIcon('exit.png'), self.tr('Exit'), self) |
| 455 | exitAct.setShortcut('Ctrl+Q') |
| 456 | exitAct.setStatusTip(self.tr('Exit application')) |
| 457 | exitAct.triggered.connect(qApp.quit) |
| 458 | |
| 459 | saveAct = QAction(QIcon('save.png'), self.tr('Save'), self) |
| 460 | saveAct.setShortcut('Ctrl+S') |
| 461 | saveAct.setStatusTip(self.tr('Save current project')) |
| 462 | saveAct.triggered.connect(self.save) |
| 463 | |
| 464 | newAct = QAction(QIcon('new.png'), self.tr('New'), self) |
| 465 | newAct.setShortcut('Ctrl+N') |
| 466 | newAct.setStatusTip(self.tr('New project')) |
| 467 | newAct.triggered.connect(self.new) |
| 468 | |
| 469 | updateAct = QAction(QIcon('download.png'), self.tr('Update'), self) |
| 470 | updateAct.setShortcut('Ctrl+U') |
| 471 | updateAct.setStatusTip(self.tr('Get modifications from upstream')) |
| 472 | updateAct.triggered.connect(self.update) |
| 473 | |
| 474 | sendAct = QAction(QIcon('close.png'), self.tr('Close'), self) |
| 475 | sendAct.setStatusTip(self.tr('Close current project')) |
| 476 | sendAct.triggered.connect(self.closeProject) |
| 477 | |
| 478 | closeAct = QAction(QIcon('upload.png'), self.tr('Send'), self) |
| 479 | closeAct.setShortcut('Ctrl+E') |
| 480 | closeAct.setStatusTip(self.tr('Send modifications upstream')) |
| 481 | closeAct.triggered.connect(self.send) |
| 482 | |
| 483 | settingsAct = QAction(QIcon('settings.png'), self.tr('Settings'), self) |
| 484 | settingsAct.setShortcut('Ctrl+P') |
| 485 | settingsAct.setStatusTip(self.tr('Set parameters')) |
| 486 | settingsAct.triggered.connect(self.settings) |
| 487 | |
| 488 | self.showTranslatedAct = QAction(self.tr('Show Translated'), self, checkable=True) |
| 489 | self.showTranslatedAct.setChecked(True) |
| 490 | self.showTranslatedAct.triggered.connect(self.filter) |
| 491 | self.showFuzzyAct = QAction(self.tr('Show Fuzzy'), self, checkable=True) |
| 492 | self.showFuzzyAct.setChecked(True) |
| 493 | self.showFuzzyAct.triggered.connect(self.filter) |
| 494 | self.showUntranslatedAct = QAction(self.tr('Show Empty Translation'), self, checkable=True) |
| 495 | self.showUntranslatedAct.setChecked(True) |
| 496 | self.showUntranslatedAct.triggered.connect(self.filter) |
| 497 | |
| 498 | self.statusBar() |
| 499 | |
| 500 | openMenu = QMenu(self.tr('Open'), self) |
| 501 | self.initOpenProjects(openMenu) |
| 502 | |
| 503 | menubar = self.menuBar() |
| 504 | fileMenu = menubar.addMenu(self.tr('&File')) |
| 505 | fileMenu.addAction(newAct) |
| 506 | fileMenu.addMenu(openMenu) |
| 507 | fileMenu.addSeparator() |
| 508 | fileMenu.addAction(exitAct) |
| 509 | |
| 510 | projectMenu = menubar.addMenu(self.tr('&Project')) |
| 511 | projectMenu.addAction(updateAct) |
| 512 | projectMenu.addAction(saveAct) |
| 513 | projectMenu.addAction(sendAct) |
| 514 | projectMenu.addSeparator() |
| 515 | projectMenu.addAction(closeAct) |
| 516 | |
| 517 | editMenu = menubar.addMenu(self.tr('&Edit')) |
| 518 | editMenu.addAction(settingsAct) |
| 519 | |
| 520 | viewMenu = menubar.addMenu(self.tr('&View')) |
| 521 | viewMenu.addAction(self.showTranslatedAct) |
| 522 | viewMenu.addAction(self.showUntranslatedAct) |
| 523 | viewMenu.addAction(self.showFuzzyAct) |
| 524 | |
| 525 | self.tabs = ProjectTab() |
| 526 | |
| 527 | self.setCentralWidget(self.tabs) |
| 528 | |
| 529 | self.setGeometry(0, 0, 800, 600) |
| 530 | self.setWindowTitle('Offlate') |
| 531 | self.show() |
| 532 | |
| 533 | def main(): |
| 534 | app = QApplication(sys.argv) |
| 535 | translator = QTranslator() |
| 536 | if translator.load(QLocale(), "offlate", "_", "i18n"): |
| 537 | app.installTranslator(translator); |
| 538 | |
| 539 | w = Window() |
| 540 | |
| 541 | sys.exit(app.exec_()) |
| 542 | |
| 543 |