示例#1
0
    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()
示例#2
0
 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_()
示例#3
0
	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_()
示例#4
0
	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
示例#5
0
    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_()
示例#6
0
 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()
示例#7
0
 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_())
示例#8
0
	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()
示例#9
0
    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_()
示例#10
0
	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()
示例#11
0
 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_()
示例#12
0
 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)
示例#13
0
 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_()
示例#14
0
    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
示例#15
0
    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)
示例#16
0
    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_()
示例#17
0
	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
			)
示例#18
0
	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_()
示例#19
0
    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
示例#20
0
	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
示例#21
0
	def _on_click_ok(self):
		"""Validate input."""
		if self.alias_num is not None:
			self.accept()
		else:
			ExceptionMessageBox(AliasNumberError()).exec_()
示例#22
0
	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
示例#23
0
	def _on_click_ok(self):
		"""Validate input."""
		if self.note is not None:
			self.accept()
		else:
			ExceptionMessageBox(ProjectNoteError()).exec_()