Source code for Assign_GUP.email_mvc_view


# Copyright (c) 2009 - 2016, UChicago Argonne, LLC.
# See LICENSE file for details.

'''
MVC View for emails

:see: http://www.saltycrane.com/blog/2008/01/pyqt-43-simple-qabstractlistmodel/
:see: http://www.saltycrane.com/blog/2007/12/pyqt-43-qtableview-qabstracttablemodel/
'''

import os, sys, time
from PyQt4 import QtCore, QtGui

import email_template
import event_filters
import general_mvc_model
import history
import proposal
import qt_utils
import resources
import signals

UI_FILE = 'emailview.ui'
REVIEWERS_TEST_FILE = os.path.join('project', 'agup_project.xml')


[docs]class Email(object): '''data structure for sending email''' to = None cc = None subject = None body = None
[docs] def send(self): '''send the email content to the default email tool''' # FIXME: no email when len(msg)>~750 # FIXME: body text loses its formatting if self.to is None: raise RuntimeError('Must specify email recipient') msg = 'mailto:' + self.to more = [] if self.cc is not None: more.append('cc=' + self.cc) if self.subject is not None: more.append('subject=' + self.subject) if self.body is not None: more.append('body=' + self.body) if len(more) > 0: args = '&'.join([_ for _ in more]) msg += '?' + args url = QtCore.QUrl(msg) service = QtGui.QDesktopServices() service.openUrl(url)
[docs]class AGUP_Emails_View(QtGui.QWidget): ''' Show the email to be sent to each Reviewer :param obj parent: instance of main_window.AGUP_MainWindow or None :param obj agup: instance of agup_data.AGUP_Data :param obj settings: instance of settings.ApplicationQSettings ''' def __init__(self, parent=None, agup=None, settings=None, hide_email_button=True): self.parent = parent self.agup = agup self.settings = settings QtGui.QWidget.__init__(self) resources.loadUi(UI_FILE, self) self.restoreWindowGeometry() self.setWindowTitle('Assign_GUP - Email Letters') self.listview_gb.setTitle('Reviewers') self.details_gb.setTitle('Email Letter') self.email = Email() self.details_panel = QtGui.QPlainTextEdit(self) layout = self.details_gb.layout() layout.addWidget(self.details_panel) self.sort_name = None if self.agup.reviewers is not None: self.setModel(self.agup.reviewers) if len(self.agup.reviewers) > 0: self.sort_name = self.agup.reviewers.keyOrder()[0] self.showReviewerEmail() self.selectFirstListItem() self.listView.clicked.connect(self.on_item_clicked) self.listView.entered.connect(self.on_item_clicked) self.arrowKeysEventFilter = event_filters.ArrowKeysEventFilter() self.listView.installEventFilter(self.arrowKeysEventFilter) self.custom_signals = signals.CustomSignals() self.openButton.released.connect(self.doOpenEmail) # FIXME: Until the email part is fixed, do not show the button in the UI if hide_email_button: self.openButton.hide() def _init_topic_widgets(self, topics_obj): ''' ''' self.details_panel.addTopics(topics_obj.getTopicList())
[docs] def on_item_clicked(self, index): ''' called when changing the selected Reviewer in the list ''' if index == self.prior_selection_index: # clicked on the current item return False self.selectModelByIndex(index, self.prior_selection_index)
[docs] def selectModelByIndex(self, curr, prev): ''' select Reviewer for email display as referenced by QListView index :param index curr: sort_name string of current selected reviewer :param index prev: QListView index of previously selected reviewer ''' self.sort_name = self.index_to_ID(curr) if self.sort_name is None: return self.showReviewerEmail()
[docs] def selectFirstListItem(self): ''' ''' idx = self.listView.indexAt(QtCore.QPoint(0,0)) self.listView.setCurrentIndex(idx) return idx
[docs] def index_to_ID(self, index): '''convert QListView index to sort_name string''' obj = index.data().toPyObject() if obj is None: return obj return str(obj)
[docs] def setModel(self, model): ''' ''' self.reviewers = model self.reviewers_model = general_mvc_model.AGUP_MVC_Model(self.reviewers, parent=self) self.listView.setModel(self.reviewers_model)
[docs] def closeEvent(self, event): ''' ''' self.saveWindowGeometry() event.accept()
[docs] def saveWindowGeometry(self): ''' remember where the window was ''' if self.settings is not None: self.settings.saveWindowGeometry(self)
[docs] def restoreWindowGeometry(self): ''' put the window back where it was ''' if self.settings is not None: self.settings.restoreWindowGeometry(self)
[docs] def showReviewerEmail(self): ''' select Reviewer for email display as referenced by self.sort_name ''' def getAssignments(full_name, role): assignments = [] for prop in self.agup.proposals: if role == prop.eligible_reviewers.get(full_name, None): assignments.append(prop.getKey('proposal_id')) return assignments if self.sort_name is None: return panelist = self.reviewers.getReviewer(str(self.sort_name)) text = self.sort_name text += '\n' text += str(panelist) # TODO: show email letter instead et = email_template.EmailTemplate() keyword_dict = self._getEmailKeywords_(et) full_name = panelist.getFullName() primaries = getAssignments(full_name, proposal.PRIMARY_REVIEWER_ROLE) secondaries = getAssignments(full_name, proposal.SECONDARY_REVIEWER_ROLE) fields = dict( # to be filled with data from an instance of Reviewer FULL_NAME = full_name, EMAIL = panelist.getKey('email'), ASSIGNED_PRIMARY_PROPOSALS = ' '.join(primaries), ASSIGNED_SECONDARY_PROPOSALS = ' '.join(secondaries), ) fields.update(keyword_dict) title = 'email: ' + full_name self.email.body = et.mail_merge(**fields) self.details_panel.setPlainText(self.email.body) fmt = 'APS General User Proposal Review Assignments for %s Cycle' self.email.subject = fmt % fields['REVIEW_CYCLE'] if 'CC' not in fields: fields['CC'] = email_template.DEFAULT_TEMPLATE_FIELDS['CC'] self.email.cc = fields['CC'] self.email.to = '%s <%s>' % (full_name, fields['EMAIL']) # set reviewers self.prior_selection_index = self.listView.currentIndex() self.details_panel.modified = False history.addLog('selected reviewer: ' + str(self.sort_name))
def _getEmailKeywords_(self, et): ''' internal: get the dictionary of keywords for the mail merge ''' keyword_dict = {} if self.settings is not None: keyword_dict = self.settings.getEmailKeywords() if len(keyword_dict) == 0: keyword_dict = et.keyword_dict # self.settings.saveEmailKeywords(keyword_dict) return keyword_dict
[docs] def doOpenEmail(self): ''' open the email letter in the email tool (does not work too good now) ''' self.email.send()
def update(self): history.addLog(self.__class__.__name__ + '.update()', False) self.showReviewerEmail()
[docs]def main(): '''simple starter program to develop this code''' import sys import os import agup_data agup = agup_data.AGUP_Data() agup.openPrpFile('project/agup_project.xml') app = QtGui.QApplication(sys.argv) # TODO: developer use only: hide_email_button=False mw = AGUP_Emails_View(None, agup, hide_email_button=False) mw.show() _r = app.exec_() sys.exit(_r)
if __name__ == '__main__': main()