Beispiel #1
0
def ensureLocalDirectoryExists():
    """
    create the local dir if it doesn't already exist, and populate it
    with files from local_default.
    """
    if os.path.isfile(FIRST_TIME_INSTALL_FLAG):
        CONFIG.first_time_install = True
        os.remove(FIRST_TIME_INSTALL_FLAG)

    issue = ""
    if not os.path.isdir("local"):
        # TODO Build this list by seeing what subfolders are in local_default
        org_list = ["Generic", "NCSSAR", "RRSAR"]
        index = 0
        if CONFIG.first_time_install:
            index = ask_user_to_choose(
                "Which is your organization? Choose 'Generic' if you are not sure.",
                org_list)
            # index will be 0 if the user escaped, otherwise a 1-based index into the given list
            if index == 0:
                raise RadioLogConfigError(
                    "User quit out of first-time install.")
        else:
            issue = "Not a first-time install, yet 'local' directory not found; copying 'local_default/generic' to 'local'; you will want to edit local/radiolog.cfg -- or restore local from a backup."
            LOG.error(issue)
            inform_user_about_issue(issue,
                                    icon=ICON_ERROR,
                                    title="Missing Configuration Folder")
        shutil.copytree(f"local_default\\{org_list[index-1]}", "local")
    elif not os.path.isfile("local/radiolog.cfg"):
        issue = "'local' directory was found but did not contain radiolog.cfg; copying from local_default"
        LOG.error(issue)
        shutil.copyfile("local_default/radiolog.cfg", "local/radiolog.cfg")
    return issue
    def accept(self):
        location = self.locationField.text()
        condition = self.conditionField.toPlainText()
        resources = self.resourcesField.toPlainText()
        other = self.otherField.toPlainText()
        team = self.callsignField.text()
        subjDate = self.dateField.text()
        subjTime = self.timeField.text()
        radioLoc = self.radioLocField.toPlainText()

        # validation: description, location, instructions fields must all be non-blank
        vText = ""
        if location == "":
            vText += "\n'Location' cannot be blank."
        if condition == "":
            vText += "\n'Condition' cannot be blank."
        if resources == "":
            vText += "\n'Resources Needed' cannot be blank."
        LOG.debug("vText:" + vText)
        if vText:
            inform_user_about_issue(
                "Please complete the form and try again:\n" + vText,
                parent=self)
            return

        textToAdd = ""
        existingText = self.parent.messageField.text()
        if existingText != "":
            textToAdd = "; "
        textToAdd += "SUBJECT LOCATED: LOCATION: " + location + "; CONDITION: " + condition + "; RESOURCES NEEDED: " + resources
        if other != "":
            textToAdd += "; " + other
        self.parent.messageField.setText(existingText + textToAdd)
        self.closeEvent(QEvent(QEvent.Close), True)
        super(subjectLocatedDialog, self).accept()
Beispiel #3
0
    def accept(self):
        ##		self.parent.timer.start(newEntryDialogTimeoutSeconds*1000) # reset the timeout
        number = self.clueNumberField.text()
        description = self.descriptionField.toPlainText()
        location = self.locationField.text()
        instructions = self.instructionsField.text()
        team = self.callsignField.text()
        clueDate = self.dateField.text()
        clueTime = self.timeField.text()
        radioLoc = self.radioLocField.toPlainText()

        # validation: description, location, instructions fields must all be non-blank
        vText = ""
        if description == "":
            vText += "\n'Description' cannot be blank."
        if location == "":
            vText += "\n'Location' cannot be blank."
        if instructions == "":
            vText += "\n'Instructions' cannot be blank."
        LOG.debug("vText:" + vText)
        if vText:
            inform_user_about_issue(
                "Please complete the form and try again:\n" + vText,
                parent=self)
            return

        self.parent.clueLogNeedsPrint = True
        textToAdd = ""
        existingText = self.parent.messageField.text()
        if existingText != "":
            textToAdd = "; "
        textToAdd += "CLUE#" + number + ": " + description + "; LOCATION: " + location + "; INSTRUCTIONS: " + instructions
        self.parent.messageField.setText(existingText + textToAdd)
        # previously, lastClueNumber was saved here - on accept; we need to save it on init instead, so that
        #  multiple concurrent clueDialogs will not have the same clue number!
        # header_labels=['CLUE#','DESCRIPTION','TEAM','TIME','DATE','OP','LOCATION','INSTRUCTIONS','RADIO LOC.']
        clueData = [
            number, description, team, clueTime, clueDate,
            self.parent.parent.opPeriod, location, instructions, radioLoc
        ]
        self.parent.parent.clueLog.append(clueData)
        if self.clueReportPrintCheckBox.isChecked():
            self.parent.parent.printClueReport(clueData)
        LOG.trace("accepted - calling close")
        self.parent.parent.clueLogDialog.tableView.model().layoutChanged.emit()
        self.closeEvent(QEvent(QEvent.Close), True)
        ##		pixmap=QPixmap(":/radiolog_ui/print_icon.png")
        ##		self.parent.parent.clueLogDialog.tableView.model().setHeaderData(0,Qt.Vertical,pixmap,Qt.DecorationRole)
        ##		self.parent.parent.clueLogDialog.tableView.model().setHeaderData(1,Qt.Vertical,pixmap,Qt.DecorationRole)
        ##		self.parent.parent.clueLogDialog.tableView.model().headerDataChanged.emit(Qt.Vertical,0,1)
        ##		# don't try self.close() here - it can cause the dialog to never close!  Instead use super().accept()
        super(clueDialog, self).accept()
Beispiel #4
0
 def printClueLogCB(self):
     self.parent.opsWithClues = sorted(
         list(
             set([
                 str(clue[5]) for clue in self.parent.clueLog
                 if str(clue[5]) != ""
             ])))
     if len(self.parent.opsWithClues) == 0:
         inform_user_about_issue("There are no clues to print.",
                                 title="No Clues to Print",
                                 parent=self)
     else:
         self.parent.printClueLogDialog.show()
 def accept(self):
     opPeriod = self.opPeriodComboBox.currentText()
     LOG.trace("Open printClueLogDialog.accept")
     if opPeriod == "--":
         inform_user_about_issue("There are no clues to print.",
                                 title="No Clues to Print",
                                 parent=self)
         self.reject()
     else:
         printClueLog(opPeriod, self.parent.getPrintParams())
         self.parent.clueLogNeedsPrint = False
         LOG.trace("Called parent printClueLogDialog.accept")
         super(printClueLogDialog, self).accept()
         LOG.trace("Called super printClueLogDialog.accept")
Beispiel #6
0
def printClueLog(opPeriod, printParams: argparse.Namespace):
    # header_labels=['#','DESCRIPTION','TEAM','TIME','DATE','O.P.','LOCATION','INSTRUCTIONS','RADIO LOC.']
    opPeriod = int(opPeriod)
    clueLogPdfFileName = CONFIG.firstWorkingDir + "\\" + printParams.pdfFileName.replace(
        ".pdf", "_clueLog_OP" + str(opPeriod) + ".pdf")
    LOG.trace("generating clue log pdf: " + clueLogPdfFileName)
    try:
        f = open(clueLogPdfFileName, "wb")
    except:
        inform_user_about_issue(
            f"PDF could not be generated: {clueLogPdfFileName}\n\nMaybe the file is currently being viewed by another program?  If so, please close that viewer and try again.  As a last resort, the auto-saved CSV file can be printed from Excel or as a plain text file.",
            timeout=10000,
        )
        return
    else:
        f.close()
    # note the topMargin is based on what looks good; you would think that a 0.6 table plus a 0.5 hard
    # margin (see t.drawOn above) would require a 1.1 margin here, but, not so.
    doc = SimpleDocTemplate(clueLogPdfFileName,
                            pagesize=landscape(letter),
                            leftMargin=0.5 * inch,
                            rightMargin=0.5 * inch,
                            topMargin=1.03 * inch,
                            bottomMargin=0.5 * inch)  # or pagesize=letter
    QCoreApplication.processEvents()
    elements = []
    styles = getSampleStyleSheet()
    clueLogPrint = []
    clueLogPrint.append(
        printParams.clue_log_header_labels[0:5] +
        printParams.clue_log_header_labels[6:8])  # omit operational period
    for row in printParams.clueLog:
        LOG.debug("clue: opPeriod=" + str(opPeriod) + "; row=" + str(row))
        if str(row[5]) == str(opPeriod) or row[1].startswith(
                "Operational Period " + str(opPeriod) +
                " Begins:") or (opPeriod == 1
                                and row[1].startswith("Radio Log Begins:")):
            clueLogPrint.append([
                row[0],
                Paragraph(row[1], styles["Normal"]), row[2], row[3], row[4],
                Paragraph(row[6], styles["Normal"]),
                Paragraph(row[7], styles["Normal"])
            ])
    clueLogPrint[1][5] = printParams.datum
    if len(clueLogPrint) > 2:
        ##			t=Table(clueLogPrint,repeatRows=1,colWidths=[x*inch for x in [0.6,3.75,.9,0.5,1.25,3]])
        t = Table(clueLogPrint,
                  repeatRows=1,
                  colWidths=[
                      x * inch for x in [0.3, 3.75, 0.9, 0.5, 0.8, 1.25, 2.5]
                  ])
        t.setStyle(
            TableStyle([
                ("F/generating clue llONT", (0, 0), (-1, -1), "Helvetica"),
                ("FONT", (0, 0), (-1, 1), "Helvetica-Bold"),
                ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
                ("BOX", (0, 0), (-1, -1), 2, colors.black),
                ("BOX", (0, 0), (6, 0), 2, colors.black),
            ]))
        elements.append(t)
        doc.build(elements,
                  onFirstPage=functools.partial(printClueLogHeaderFooter,
                                                printParams=printParams,
                                                opPeriod=opPeriod),
                  onLaterPages=functools.partial(printClueLogHeaderFooter,
                                                 printParams=printParams,
                                                 opPeriod=opPeriod))
        # 			self.clueLogMsgBox.setInformativeText("Finalizing and Printing...")
        if SWITCHES.devmode:
            view_pdf(clueLogPdfFileName)
        else:
            print_pdf(clueLogPdfFileName)
        make_backup_copy(clueLogPdfFileName)
Beispiel #7
0
def printLog(opPeriod, printParams: argparse.Namespace, teams=False):
    """
    Optional argument 'teams': if True, generate one pdf of all individual team logs;
    so, this function should be called once to generate the overall log pdf, and
    again with teams=True to generate team logs pdf
    if 'teams' is an array of team names, just print those team log(s)
    """
    opPeriod = int(opPeriod)
    pdfName = CONFIG.firstWorkingDir + "\\" + printParams.pdfFileName
    teamFilterList = [""]  # by default, print print all entries; if teams=True, add a filter for each team
    msgAdder = ""
    if teams:
        if isinstance(teams, list):
            # recursively call this function for each team in list of teams
            for team in teams:
                printParams.printLog(opPeriod, team)
        elif isinstance(teams, str):
            pdfName = pdfName.replace(".pdf", "_" + teams.replace(" ", "_").replace(".", "_") + ".pdf")
            msgAdder = " for " + teams
            teamFilterList = [teams]
        else:
            pdfName = pdfName.replace(".pdf", "_teams.pdf")
            msgAdder = " for individual teams"
            teamFilterList = []
            for team in printParams.allTeamsList:
                if team != "dummy":
                    teamFilterList.append(team)
    LOG.debug("teamFilterList=" + str(teamFilterList))
    pdfName = pdfName.replace(".pdf", "_OP" + str(opPeriod) + ".pdf")
    LOG.debug("generating radio log pdf: " + pdfName)
    try:
        f = open(pdfName, "wb")
    except:
        inform_user_about_issue(
            f"PDF could not be generated:\n\n{pdfName}\n\nMaybe the file is currently being viewed by another program?  If so, please close that viewer and try again.  As a last resort, the auto-saved CSV file can be printed from Excel or as a plain text file."
        )
        return
    else:
        f.close()
    # note the topMargin is based on what looks good; you would think that a 0.6 table plus a 0.5 hard
    # margin (see t.drawOn above) would require a 1.1 margin here, but, not so.
    doc = SimpleDocTemplate(pdfName, pagesize=landscape(letter), leftMargin=0.5 * inch, rightMargin=0.5 * inch, topMargin=1.03 * inch, bottomMargin=0.5 * inch)  # or pagesize=letter
    # 		printParams.logMsgBox.show()
    # 		QTimer.singleShot(5000,printParams.logMsgBox.close)
    QCoreApplication.processEvents()
    elements = []
    for team in teamFilterList:
        extTeamNameLower = getExtTeamName(team).lower()
        radioLogPrint = []
        styles = getSampleStyleSheet()
        radioLogPrint.append(printParams.header_labels[0:6])
        entryOpPeriod = 1  # update this number when 'Operational Period <x> Begins' lines are found
        # hits=False # flag to indicate whether this team has any entries in the requested op period; if not, don't make a table for this team
        for row in printParams.radioLog:
            opStartRow = False
            # LOG.debug("message:"+row[3]+":"+str(row[3].split()))
            if row[3].startswith("Radio Log Begins:"):
                opStartRow = True
            if row[3].startswith("Operational Period") and row[3].split()[3] == "Begins:":
                opStartRow = True
                entryOpPeriod = int(row[3].split()[2])
            # LOG.debug("desired op period="+str(opPeriod)+"; this entry op period="+str(entryOpPeriod))
            if entryOpPeriod == opPeriod:
                if team == "" or extTeamNameLower == getExtTeamName(row[2]).lower() or opStartRow:  # filter by team name if argument was specified
                    radioLogPrint.append([row[0], row[1], row[2], Paragraph(row[3], styles["Normal"]), Paragraph(row[4], styles["Normal"]), Paragraph(row[5], styles["Normal"])])
        # hits=True
        if not teams:
            radioLogPrint[1][4] = printParams.datum
        LOG.debug("length:" + str(len(radioLogPrint)))
        if not teams or len(radioLogPrint) > 2:  # don't make a table for teams that have no entries during the requested op period
            t = Table(radioLogPrint, repeatRows=1, colWidths=[x * inch for x in [0.5, 0.6, 1.25, 5.5, 1.25, 0.9]])
            t.setStyle(
                TableStyle([("FONT", (0, 0), (-1, -1), "Helvetica"), ("FONT", (0, 0), (-1, 1), "Helvetica-Bold"), ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black), ("BOX", (0, 0), (-1, -1), 2, colors.black), ("BOX", (0, 0), (5, 0), 2, colors.black)])
            )
            elements.append(t)
            if teams and team != teamFilterList[-1]:  # don't add a spacer after the last team - it could cause another page!
                elements.append(Spacer(0, 0.25 * inch))
    doc.build(elements, onFirstPage=functools.partial(printLogHeaderFooter, opPeriod=opPeriod, printParams=printParams, teams=teams), onLaterPages=functools.partial(printLogHeaderFooter, opPeriod=opPeriod, printParams=printParams, teams=teams))
    if SWITCHES.devmode:
        view_pdf(pdfName)
    else:
        print_pdf(pdfName)
    printParams.radioLogNeedsPrint = False
    make_backup_copy(pdfName)