def _on_click_context(self, context): """Process context menu actions.""" context_action = str(self.view.table.sender().text()) # Attempt to acquire job ownership try: job_num = self._selected_job_num(self._selected_dwg_nums) job, lock = JobIO.job_and_lock(job_num) except (MultipleJobError, JobInUseError, JobNotFoundError, IOError, EOFError) as error: ExceptionMessageBox(error).exec_() return # Modify work order data if context_action == 'Delete': handler.delete(self._selected_dwg_nums, job.projects) elif context_action == 'Add Note': handler.note(self._selected_dwg_nums, job.projects, self._users.my_name) elif context == 'Due Dates': handler.due_date(self._selected_dwg_nums, job.projects, context_action) # Attempt to save changes try: JobIO.save(job_num, job) except IOError as error: ExceptionMessageBox(error).exec_() # Release ownership and update view lock.unlock() self._status.show_save_msg(job_num) self._on_click_refresh()
def on_click_help(self): """Open user guide.""" try: os.startfile(os.path.join(Path.DOCS, 'RotoWorks User Guide.pdf')) except OSError as error: logging.warning(error) ExceptionMessageBox(error).exec_()
def _on_click_ok(self): """Process request to add template files.""" try: # Check for errors vals = [ self.drawing_num, self._project_dir_ws.dir, self._add_files_ws.template ] errors = [ DrawingNumberError, ProjectStorageError, TemplateError ] for i in range(len(vals)): if vals[i] is None: raise errors[i]() if self._add_files_ws.template == 'None': raise TemplateError() # Create template files self._add_files_ws.create_files( self._add_files_ws.template, self._project_dir_ws.dir, self.drawing_num ) self.accept() except (DrawingNumberError, ProjectStorageError, TemplateError) as error: ExceptionMessageBox(error).exec_()
def make(job_num, logger): """Create a valid project workspace. Parameters ---------- job_num : str A 6-digit integer that is associated with a collection of work orders. logger : logging.getLogger Sends informative messages to user log file. Returns ------- workspace : str or None A validated project workspace directory. """ while True: workspace, ok = ProjectWorkspace.get_toplevel_workspace() if ok: if os.path.basename(workspace) == job_num: ProjectWorkspace.init_workspace(workspace) logger('set %s workspace' % job_num) return workspace else: ExceptionMessageBox(WorkspaceError()).exec_() else: return
def start(self): try: # Get measurement DataFrames rw_filepath = Template.get_reference_path() ref_path = os.path.dirname(rw_filepath) ref_job_num = os.path.basename(rw_filepath)[:6] ref_data = Template.data_formatted( os.path.join(ref_path, self._csv)) data = Template.data_formatted(self._data_csv) # Get merged comparison DataFrame comparison_data = Template.get_comparison(self._data.job_num, ref_job_num, data, ref_data) # Prompt user to save comparison as CSV save_path = str(QtGui.QFileDialog.getSaveFileName(caption='Save')) if len(os.path.basename(save_path)) != 0: comparison_data.to_csv('%s.csv' % save_path, index=False) except TypeError as error: # object of type 'NoneType' has no len(), user cancellelation pass except IOError as error: ExceptionMessageBox(error).exec_()
def on_click_upload(self): """Process request to load work center data.""" try: if self.is_admin(): self._intent = GetWorkCenterSource() except PasswordError as error: ExceptionMessageBox(error).exec_() self.on_click_upload() else: self.desk.refresh_home()
def start_app(self): """Call the appropriate user interface.""" try: # time.sleep(2) # Throttle process for visual effect. self.app_data = self._load_data() except StartUpError as error: self.close() ExceptionMessageBox(error).exec_() else: self.finish(Nucleus(self.app_data)) sys.exit(self.app.exec_())
def _save(self): """Write user input to CSV file and close view.""" input_data = self.view.get_input_data() try: with open(self._weight.OUTPUT_FILE, 'wb') as csvfile: csvwriter = csv.writer(csvfile) csvwriter.writerows(input_data) except IOError as error: logging.warning(error) ExceptionMessageBox(error).exec_() self.view.close()
def on_emit_exit(self, error): """End assignment process due to a given error and display reasoning to user. Parameters ---------- error : Exception subclass """ self.thread_cleanup() self.view.close() ExceptionMessageBox(error).exec_()
def _on_click_doc_btn(self): """Launch a documentation session.""" inspection = self.view.selection try: doc = self._doc_session_map[inspection](self._data) doc.start() except (CADOpenError, CADDocError, CADLayerError, AttributeError, IOError) as error: logging.warning(error) ExceptionMessageBox(error).exec_() self._on_click_listbox()
def open_path(path): """Open a file or directory via its parent process. Parameters ---------- path : str Absolute path to file or directory. """ try: Logic.open_path(path) except (OSError, TypeError) as error: ExceptionMessageBox(error).exec_()
def on_click_open(self): """Prompt user to open an existing project.""" history = HistoryController() if history.view.exec_(): if history.project is not None: try: data = get_data_source(history.project) except IOError as error: logging.warning(error) ExceptionMessageBox(error).exec_() else: self.enter_workscope(data)
def on_click_new(self): """Process a request to create a new ``Job``.""" job_num, ok = QtGui.QInputDialog.getInt(self, 'New', 'Job Number:') if ok: job_num = str(job_num) request = NewJobRequest(job_num, self.app_data.users.log) try: # An approved request initializes job files and directories. if request.approved(): self.load_job(job_num) except (JobNumberError, ExistingJobError, OSError, WorkspaceError, IOError, UnknownError) as error: ExceptionMessageBox(error).exec_()
def process_complete_job_request(self, job_num, job=None, lock=None): """Process a request to remove job files from ``Nucleus``. Parameters ---------- job_num : str The 6-digit job number. job : Job or None A collection of work orders requesting completion. lock : GateKeeper or None Controls read and write access to `job` applicaton files. Returns ------- True If `job` files were removed from ``Nucleus``. """ self.app_data.users.log('initiating a complete job request for %s' % job_num) request = CompleteJobRequest( job_num, self.app_data.users.supervisor_email_addresses, job, lock) try: if not request.approved(): self.app_data.users.log( '%s complete job request was not approved' % job_num) return except (JobInUseError, IOError, EOFError, ProjectsFolderRootError, DestinationError) as error: self.app_data.users.log(error) ExceptionMessageBox(error).exec_() else: self.status.showMessage('Updating your jobs...') self.desk.refresh_home() # Log data to user file self.app_data.users.log('%s completed, due by %s' % (job_num, JobIO.job_due_date(job))) self.app_data.users.log('%s drawing count: %d' % (job_num, request.dwg_count)) for project in request.projects: self.app_data.users.log('project:%s,%s' % (request.projects[project].alias_num, request.projects[project].owner)) self.status.showMessage('%s closed successfully.' % job_num) return True
def __init__(self, xlsx_path): # Verify access to workcenter spreadsheet try: self.df = pd.read_excel(xlsx_path) except IOError as error: ExceptionMessageBox(error).exec_() return # Setup GUI self.view = ProgressDialog('Assignment In Progress') self.view.ok_btn.clicked.connect(self.view.accept) self.view.update('Reviewing data...') self.view.show() # Begin processing workcenter data self.start_worker_thread(self.df)
def process_open_job_request(self, job_num): """Process a request to open an existing ``Job``. Parameters ---------- job_num : str The 6-digit job number. """ try: if len(job_num) != 6: raise JobNumberError() self.load_job(job_num) except (JobNumberError, OSError, JobNotFoundError, JobInUseError, IOError, EOFError) as error: ExceptionMessageBox(error).exec_()
def save(self): """Serialize ``Job`` data.""" folder = self.active_folder if folder != 'Home': try: self._folders[folder].save() except (IOError, SecurityError) as error: ExceptionMessageBox(error).exec_() else: self._app_data.users.log('saved job %s' % folder) self._status.show_save_msg(folder) else: self._status.showMessage( 'Cannot save a job in this context.', 2000 )
def _on_click_ok(self): """Process request to add new project. Notes ----- Only the template files are created here (if applicable), all other processes required to create a new project are completed separately. """ try: # Check for errors vals = [ self.alias_num, self.drawing_num, self._add_files_ws.template, self.note ] errors = [ AliasNumberError, DrawingNumberError, TemplateError, ProjectNoteError ] for i in range(len(vals)): if vals[i] is None: raise errors[i]() if self._add_files_ws.template == 'None': pass else: if self._project_dir_ws.dir is None: raise ProjectStorageError() else: # Create template files self._add_files_ws.create_files( self._add_files_ws.template, self._project_dir_ws.dir, self.drawing_num ) self.accept() except ( AliasNumberError, DrawingNumberError, ProjectStorageError, TemplateError, ProjectNoteError ) as error: ExceptionMessageBox(error).exec_()
def save(self): """Save updates to the project file. Returns ------- Data Instance data model. """ try: self._data.scope.update(self.table_map) self._data.save() except IOError as error: logging.warning(error) ExceptionMessageBox(error).exec_() else: return self._data
def create(self): """Setup filepaths and serialize data model. Returns ------- data : Data Project data model. """ # Get inputs from view job_num = self.view.job_num phase = self.view.phase machine_type = self.view.machine_type subtype = self.view.machine_sub_type is_curtis = self.view.is_curtis nickname = self.view.nickname try: # Setup filepath filepath = Project.filepath( job_num, phase, machine_type, subtype, nickname ) if os.path.exists(filepath): if ExistingProjectError.proceed(self.view) != QtGui.QMessageBox.Yes: return # Save data to file data = Project.init_data( job_num, phase, machine_type, is_curtis, filepath ) except (IOError, ProjectsFolderRootError, WindowsError) as error: logging.warning(error) ExceptionMessageBox(error).exec_() else: return data
def _on_click_ok(self): """Validate input.""" if self.alias_num is not None: self.accept() else: ExceptionMessageBox(AliasNumberError()).exec_()
def status(selected_dwg_nums, projects, status, workspace, log): """Modify a project's status attribute. Parameters ---------- selected_dwg_nums : list Drawing numbers associated with the ``Projects`` that are requesting modification. projects : dict ``Projects`` organized by drawing number. status : str The new status. workspace : str The toplevel project workspace directory. log : callable Interface to user log file. Notes ----- When `status` signifies the completion of a work order, an attempt is made to send the corresponding non-controlled drawing PDF to the issued prints folder. This PDF should be created through Autodesk Inventor per the local iLogic code, otherwise the resulting PDF name may not match the required convention. In this case, this method will not find the PDF and the user will be responsible to completing this action. """ if status == WorkOrderConstants.STATUS_LIST[-1]: job_num = selected_dwg_nums[0][:6] dwgs_nums = JobIO.drawing_nums_from_list(selected_dwg_nums) target_count = len(dwgs_nums) actual_count = 0 moved_dwg_nums = [] # Get the destination for non-controlled drawing PDFs. try: dst = Extract.issued_prints_folder(job_num) except (DestinationError, ProjectsFolderRootError) as error: ExceptionMessageBox(error).exec_() return pdfs = ContextHandler.workspace_pdfs(workspace) for pdf in pdfs: if actual_count < target_count: # Get the filename and drawing number from pdf. # The '_' separator is driven by Inventor iLogic code. # Non-controlled PDF files must conform to this convention. filename = os.path.basename(pdf) target_dwg_num = filename.split('_')[0] if target_dwg_num in selected_dwg_nums: dst_path = os.path.join(dst, filename) shutil.move(pdf, dst_path) actual_count += 1 moved_dwg_nums.append(target_dwg_num) # Check for PDFs that should exist, but don't. missing_pdfs = [i for i in dwgs_nums if i not in moved_dwg_nums] if len(missing_pdfs) != 0: log('%s PDF not moved, there may be others' % missing_pdfs[0]) MissingPDFError.show(missing_pdfs) for p in selected_dwg_nums: projects[p].status = status
def _on_click_ok(self): """Validate input.""" if self.note is not None: self.accept() else: ExceptionMessageBox(ProjectNoteError()).exec_()