class FirstRunDialog(BaseDialog): def __init__(self, parent=None): BaseDialog.__init__(self, parent) self.setWindowTitle(_("First Run Dialog")) self.top_label = WarningLabel("FirstRun") self.wizard_widget = QtGui.QStackedWidget() page0 = PageZero(self) self.page1 = PageOne(self) self.page2 = PageTwo(self) self.page3 = PageThree(self) self.page4 = PageFour(self) self.page5 = PageFive(self) page6 = PageSix(self) self.page7 = PageSeven(self) # accept_page = AcceptPage(self) self.wizard_widget.addWidget(page0) self.wizard_widget.addWidget(self.page1) self.wizard_widget.addWidget(self.page2) self.wizard_widget.addWidget(self.page3) self.wizard_widget.addWidget(self.page4) self.wizard_widget.addWidget(self.page5) self.wizard_widget.addWidget(page6) self.wizard_widget.addWidget(self.page7) # self.wizard_widget.addWidget(accept_page) self.insertWidget(self.top_label) self.insertWidget(self.wizard_widget) self.next_but = self.button_box.addButton(_("Next"), self.button_box.ActionRole) self.back_but = self.button_box.addButton(_("Back"), self.button_box.ActionRole) self.apply_but.hide() self.back_but.hide() self.cancel_but.setText(_("Quit OpenMolar")) self.set_labels() def sizeHint(self): return QtCore.QSize(400, 400) def wait(self, waiting=True): if waiting: QtGui.QApplication.instance().setOverrideCursor( QtCore.Qt.WaitCursor) else: QtGui.QApplication.instance().restoreOverrideCursor() def set_labels(self): self.top_label.setText(self.current_page.header_text) self.cancel_but.setVisible(self.current_index == 0) self.back_but.setVisible(self.current_index != 0) if self.current_index == 5: self.next_but.setText(_("Create Database Now!")) elif self.current_index == 7: self.next_but.setText(_("Write Config File and Proceed")) else: self.next_but.setText(_("Next")) def next(self): ''' 0 = intro 1 = application password 2 = host and port 3 = database option (create new or use existing) 4 = database details (dbname, user and password) 5 = enter privileged user 6 = create database 7 = test connection, write config and exit. ''' i = self.wizard_widget.currentIndex() if not self.current_page.is_completed: QtGui.QMessageBox.warning(self, _("error"), self.current_page.error_message) new_i = i elif i == 4 and not self.page3.create_new: new_i = i + 3 elif i == 7: self.finish() return else: new_i = i + 1 self.wizard_widget.setCurrentIndex(new_i) self.set_labels() def back(self): i = self.wizard_widget.currentIndex() if i == 0: new_i = 0 elif i == 7: # shouldn't happen? new_i = 0 # don't create a database by hitting "back" else: new_i = i - 1 self.wizard_widget.setCurrentIndex(new_i) self.set_labels() def database_exists_already(self): self.wizard_widget.setCurrentIndex(4) self.set_labels() def finish(self): dom = minidom.parseString(XML_TEMPLATE) #-- hash the password and save it PSWORD = hashlib.md5( hashlib.sha1(str("diqug_ADD_SALT_3i2some" + self.sys_password)).hexdigest()).hexdigest() dom.getElementsByTagName( "system_password")[0].firstChild.replaceWholeText(PSWORD) #-- server settings xmlnode = dom.getElementsByTagName("server")[0] #-- host xmlnode.getElementsByTagName( "location")[0].firstChild.replaceWholeText(self.host) #--port xmlnode.getElementsByTagName("port")[0].firstChild.replaceWholeText( str(self.port)) #-- database settings xmlnode = dom.getElementsByTagName("database")[0] #--user xmlnode.getElementsByTagName("user")[0].firstChild.replaceWholeText( self.db_user) #--password xmlnode.getElementsByTagName( "password")[0].firstChild.replaceWholeText( base64.b64encode(self.db_pass)) #--db name xmlnode.getElementsByTagName("dbname")[0].firstChild.replaceWholeText( self.db_name) settings_dir = os.path.dirname(localsettings.global_cflocation) successful_save = False try: if not os.path.exists(settings_dir): LOGGER.info("creating settings directory '%s'", settings_dir) os.mkdir(settings_dir) LOGGER.info('writing settings to %s', localsettings.global_cflocation) f = open(localsettings.global_cflocation, "w") f.write(dom.toxml()) f.close() localsettings.cflocation = localsettings.global_cflocation successful_save = True except OSError: pass except IOError: pass if not successful_save: message = ( "unable to write to '%s' " "we need root privileges for that\n" "will resort to putting settings into a local file '%s'") LOGGER.warning(message, settings_dir, localsettings.cflocation) settings_dir = os.path.dirname(localsettings.cflocation) if not os.path.exists(settings_dir): os.mkdir(settings_dir) LOGGER.info("putting a local settings file in '%s'", settings_dir) f = open(localsettings.cflocation, "w") f.write(dom.toxml()) f.close() localsettings.cflocation = localsettings.cflocation conf_text = "[login]\nPASSWORD=\nUSER1=\nUSER2=" if self.page3.create_new: conf_text = conf_text.replace("USER1=", "USER1=USER") f = open(localsettings.LOGIN_CONF, "w") f.write(conf_text) f.close() self.accept() def _clicked(self, but): ''' "private" function called when button box is clicked ''' if but == self.next_but: self.next() elif but == self.back_but: self.back() else: BaseDialog._clicked(self, but) @property def current_index(self): return self.wizard_widget.currentIndex() @property def current_page(self): return self.wizard_widget.currentWidget() @property def sys_password(self): return str(self.page1.line_edit1.text().toAscii()) @property def host(self): return str(self.page2.line_edit1.text().toAscii()) @property def port(self): return int(str(self.page2.line_edit2.text().toAscii())) @property def db_name(self): return str(self.page4.line_edit1.text().toAscii()) @property def db_user(self): return str(self.page4.line_edit2.text().toAscii()) @property def db_pass(self): return str(self.page4.line_edit3.text().toAscii()) @property def privileged_user(self): return str(self.page5.line_edit1.text().toAscii()) @property def privileged_user_pass(self): return str(self.page5.line_edit2.text().toAscii())
class CheckVersionDialog(ExtendableDialog, Options): ''' A dialog which informs the user of any updates to the openmolar application There are 2 ways of calling this dialog. exec_() = show the dialog before polling the wesbite for releases background_exec() = only show the result if there is a new version. ''' result = None _new_version = None _next_check_date = None polling = False def __init__(self, parent=None): LOGGER.debug("initiating CheckVersionDialog") ExtendableDialog.__init__(self, parent) self.data_fetcher = DataFetcher(parent) self.config = MyConfigParser() def add_widgets(self): self.header_label = WarningLabel( _("Checking for updates.... please wait.")) self.result_label = QtWidgets.QLabel("") self.result_label.setAlignment(QtCore.Qt.AlignCenter) self.result_label.setOpenExternalLinks(True) self.insertWidget(self.header_label) self.insertWidget(self.result_label) self.cancel_but.hide() self.apply_but.setText(_("OK")) self.enableApply() self.options_widget = OptionsWidget(self) self.options_widget.set_chosen_option(self.config.update_option) self.set_advanced_but_text(_("Options")) self.add_advanced_widget(self.options_widget) def show_result(self): LOGGER.debug("CheckVersionDialog show result") self.result = self.data_fetcher.result() if self.result is None: self.result_label.setText( "%s<br /><a href='%s'>%s</a>" % (_("Unable to connect to"), INFORMATION_URL, INFORMATION_URL)) return if self.update_available: header_text = _("A newer version of OpenMolar is available") self.header_label.label.setStyleSheet("color: red") else: header_text = _("You are running the latest version - thankyou") self.header_label.setText(header_text) self.result_label.setText(MESSAGE % (self.new_version)) def lookup_due(self): ''' check the config file for user preferences on update check ''' LOGGER.debug("checking user preferences for application update check") if self.config.update_option == self.NEVER: return False if self.config.update_option == self.MONTHLY: delta = timedelta(days=30) elif self.config.update_option == self.WEEKLY: delta = timedelta(days=7) elif self.config.update_option == self.DAILY: delta = timedelta(days=1) else: delta = timedelta(days=0) if self.config.last_check_date + delta > date.today(): LOGGER.debug("update check not due yet") return False return True def hit_website(self): if not self.polling: LOGGER.info("polling website for latest release") self.polling = True self.data_fetcher.get_webdata() @property def update_available(self): ''' a boolean to lookup whether a new version is available. ''' LOGGER.debug("getting property update_available") try: if self.new_version[0] > localsettings.VERSION: LOGGER.info("There is a newer version available upstream") return True else: LOGGER.info("You are running the latest version - thankyou") return False except: LOGGER.exception("unknown error getting update available " "perhaps the website returned garbage???") return False @property def new_version(self): if self._new_version is None: scp = configparser.ConfigParser() scp.read_string(self.result) version, release_date, message = "", None, "" try: try: version = scp.get("RELEASE", "VERSION") except configparser.NoOptionError: pass try: release_date_string = scp.get("RELEASE", "DATE") m = re.match(r"(\d+),(\d+),(\d+)", release_date_string) if m: release_date = date(int(m.groups()[0]), int(m.groups()[1]), int(m.groups()[2])) self.checked_today = True else: LOGGER.warning("release date not in form 2016,03,09") except configparser.NoOptionError: pass except ValueError: # this will fire if a bad date is passed. logging.exception("error parsing date field") try: message = scp.get("RELEASE", "MESSAGE") except configparser.NoOptionError: pass except configparser.NoSectionError: LOGGER.warning("unable to parse result of version checking") except configparser.MissingSectionHeaderError: pass self._new_version = (version, localsettings.formatDate(release_date), message.replace("\n", "<br />")) return self._new_version def background_exec(self): if self.lookup_due(): self.data_fetcher.finished_signal.connect(self.exec_) self.hit_website() def exec_(self): LOGGER.debug("exec_ called by %s", self.sender()) self.add_widgets() if self.sender() == self.data_fetcher: self.show_result() # lookup has been performed discreetly, only bother the user if # there is an update available if not self.update_available: return False else: self.data_fetcher.finished_signal.connect(self.show_result) QtCore.QTimer.singleShot(5000, self.hit_website) if ExtendableDialog.exec_(self): self.config.user_chosen_option = self.options_widget.chosen_option self.config.checked_today = self.checked_today self.config.write_config()
class FirstRunDialog(BaseDialog): def __init__(self, parent=None): BaseDialog.__init__(self, parent) self.setWindowTitle(_("First Run Dialog")) self.top_label = WarningLabel("FirstRun") self.wizard_widget = QtWidgets.QStackedWidget() page0 = PageZero(self) self.page1 = PageOne(self) self.page2 = PageTwo(self) self.page3 = PageThree(self) self.page4 = PageFour(self) self.page5 = PageFive(self) page6 = PageSix(self) self.page7 = PageSeven(self) # accept_page = AcceptPage(self) self.wizard_widget.addWidget(page0) self.wizard_widget.addWidget(self.page1) self.wizard_widget.addWidget(self.page2) self.wizard_widget.addWidget(self.page3) self.wizard_widget.addWidget(self.page4) self.wizard_widget.addWidget(self.page5) self.wizard_widget.addWidget(page6) self.wizard_widget.addWidget(self.page7) # self.wizard_widget.addWidget(accept_page) self.insertWidget(self.top_label) self.insertWidget(self.wizard_widget) self.next_but = self.button_box.addButton( _("Next"), self.button_box.ActionRole) self.back_but = self.button_box.addButton( _("Back"), self.button_box.ActionRole) self.apply_but.hide() self.back_but.hide() self.cancel_but.setText(_("Quit OpenMolar")) self.set_labels() def sizeHint(self): return QtCore.QSize(400, 400) def wait(self, waiting=True): if waiting: QtWidgets.QApplication.instance().setOverrideCursor( QtCore.Qt.WaitCursor) else: QtWidgets.QApplication.instance().restoreOverrideCursor() def set_labels(self): self.top_label.setText(self.current_page.header_text) self.cancel_but.setVisible(self.current_index == 0) self.back_but.setVisible(self.current_index != 0) if self.current_index == 5: self.next_but.setText(_("Create Database Now!")) elif self.current_index == 7: self.next_but.setText(_("Write Config File and Proceed")) else: self.next_but.setText(_("Next")) def __next__(self): ''' 0 = intro 1 = application password 2 = host and port 3 = database option (create new or use existing) 4 = database details (dbname, user and password) 5 = enter privileged user 6 = create database 7 = test connection, write config and exit. ''' i = self.wizard_widget.currentIndex() if not self.current_page.is_completed: QtWidgets.QMessageBox.warning(self, _("error"), self.current_page.error_message) new_i = i elif i == 4 and not self.page3.create_new: new_i = i + 3 elif i == 7: self.finish() return else: new_i = i + 1 self.wizard_widget.setCurrentIndex(new_i) self.set_labels() def back(self): i = self.wizard_widget.currentIndex() if i == 0: new_i = 0 elif i == 7: # shouldn't happen? new_i = 0 # don't create a database by hitting "back" else: new_i = i - 1 self.wizard_widget.setCurrentIndex(new_i) self.set_labels() def database_exists_already(self): self.wizard_widget.setCurrentIndex(4) self.set_labels() def finish(self): dom = minidom.parseString(XML_TEMPLATE) # hash the password (twice) and save it sha1 = hashlib.sha1(("diqug_ADD_SALT_3i2some%s" % self.sys_password).encode("utf8")).hexdigest() PSWORD = hashlib.md5(sha1.encode("utf8")).hexdigest() dom.getElementsByTagName( "system_password")[0].firstChild.replaceWholeText(PSWORD) # server settings xmlnode = dom.getElementsByTagName("server")[0] # host xmlnode.getElementsByTagName( "location")[0].firstChild.replaceWholeText(self.host) # port xmlnode.getElementsByTagName( "port")[0].firstChild.replaceWholeText(str(self.port)) # database settings xmlnode = dom.getElementsByTagName("database")[0] # user xmlnode.getElementsByTagName( "user")[0].firstChild.replaceWholeText(self.db_user) # password xmlnode.getElementsByTagName( "password")[0].firstChild.replaceWholeText( base64.b64encode(self.db_pass.encode("utf8")).decode("utf8")) # db name xmlnode.getElementsByTagName( "dbname")[0].firstChild.replaceWholeText(self.db_name) settings_dir = os.path.dirname(localsettings.global_cflocation) successful_save = False try: if not os.path.exists(settings_dir): LOGGER.info("creating settings directory '%s'", settings_dir) os.mkdir(settings_dir) LOGGER.info( 'writing settings to %s', localsettings.global_cflocation) f = open(localsettings.global_cflocation, "w") f.write(dom.toxml()) f.close() localsettings.cflocation = localsettings.global_cflocation successful_save = True except OSError: pass except IOError: pass if not successful_save: message = ( "unable to write to '%s' " "we need root privileges for that\n" "will resort to putting settings into a local file '%s'") LOGGER.warning(message, settings_dir, localsettings.cflocation) settings_dir = os.path.dirname(localsettings.cflocation) if not os.path.exists(settings_dir): os.mkdir(settings_dir) LOGGER.info("putting a local settings file in '%s'", settings_dir) f = open(localsettings.cflocation, "w") f.write(dom.toxml()) f.close() localsettings.cflocation = localsettings.cflocation conf_text = "[login]\nPASSWORD=\nUSER1=\nUSER2=" if self.page3.create_new: conf_text = conf_text.replace("USER1=", "USER1=USER") f = open(localsettings.LOGIN_CONF, "w") f.write(conf_text) f.close() self.accept() def _clicked(self, but): ''' "private" function called when button box is clicked ''' if but == self.next_but: next(self) elif but == self.back_but: self.back() else: BaseDialog._clicked(self, but) @property def current_index(self): return self.wizard_widget.currentIndex() @property def current_page(self): return self.wizard_widget.currentWidget() @property def sys_password(self): return str(self.page1.line_edit1.text()) @property def host(self): return str(self.page2.line_edit1.text()) @property def port(self): return int(str(self.page2.line_edit2.text())) @property def db_name(self): return str(self.page4.line_edit1.text()) @property def db_user(self): return str(self.page4.line_edit2.text()) @property def db_pass(self): return str(self.page4.line_edit3.text()) @property def privileged_user(self): return str(self.page5.line_edit1.text()) @property def privileged_user_pass(self): return str(self.page5.line_edit2.text())
class EditTreatmentDialog(ExtendableDialog): def __init__(self, serialno, courseno, parent=None): ExtendableDialog.__init__(self, parent, remove_stretch=True) self.setWindowTitle(_("Edit Treatment Dialog")) self.serialno = serialno self.courseno = courseno self._treatment_course = None self.widgets = {} self.orig_values = {} frame = QtWidgets.QFrame() form_layout = QtWidgets.QFormLayout(frame) self.header_label = WarningLabel("") tooth_atts = [] for att in treatment_course.CURRTRT_ROOT_ATTS: widg = UpperCaseLineEdit() self.widgets[att] = widg if re.match("[ul][lr][1-8]", att): tooth_atts.append(att) else: form_layout.addRow(att, widg) for att in sorted(tooth_atts): form_layout.addRow(att.upper(), self.widgets[att]) scroll_area = QtWidgets.QScrollArea() scroll_area.setWidget(frame) scroll_area.setWidgetResizable(True) self.insertWidget(self.header_label) self.insertWidget(scroll_area) self.add_advanced_widget(QtWidgets.QLabel(_("No Advanced Options"))) QtCore.QTimer.singleShot(100, self.load_values) @property def treatment_course(self): if self._treatment_course is None: self._treatment_course = treatment_course.TreatmentCourse( self.serialno, self.courseno) return self._treatment_course def load_values(self): mb = QtWidgets.QMessageBox(self) mb.setWindowTitle(_("Option")) mb.setIcon(mb.Question) mb.setStandardButtons(mb.Yes | mb.No) mb.setText("%s<hr /><em>%s</em>" % ( _("Edit Completed items?"), _("Choosing 'NO' will offer edit of planned items"))) self.rejected.connect(mb.accept) # for Unittests mb.exec_() if mb.result() == mb.No: self.header_label.setText(_("Planned Items")) suffix = "pl" else: self.header_label.setText(_("Completed Items")) suffix = "cmp" for att in treatment_course.CURRTRT_ROOT_ATTS: val = self.treatment_course.__dict__[att + suffix] widg = self.widgets[att] self.orig_values[att] = val widg.setText(val) widg.editingFinished.connect(self.check_appliable) def new_value(self, att): return str(self.widgets[att].text()).strip(" ") + " " def check_appliable(self): for att in treatment_course.CURRTRT_ROOT_ATTS: if self.new_value(att) != self.orig_values[att]: self.enableApply() return self.enableApply(False) def sizeHint(self): return QtCore.QSize(350, 600) def update_db(self): changes = "" values = [] for att in treatment_course.CURRTRT_ROOT_ATTS: if self.new_value(att) != self.orig_values[att]: changes += "%s%s=%%s ," % (att, self.suffix) values.append(self.new_value(att)) treatment_course.update_course( changes.rstrip(","), values, self.serialno, self.courseno)