def __init__(self): db = Database('database') if db .root is None: root = Persistent() root.list_of_users = [] db.elect (root) transaction.commit() checkout(db.root) self.list_of_users = db.root.list_of_users # Creating a user default to make easy the development user = User('Fulano', '*****@*****.**', 'pwd', "uid") document = Document("My document", ".txt", "I think to myself... what a wonderful world!", "uid", user.folder.id) document.id = "did" user.folder.id = "fid" user.add_document(user.folder.id, document) db.root.list_of_users.append(user) db.root.list_of_users = self.list_of_users transaction.commit() checkout(db .root) self.list_of_users = db .root.list_of_users else: self.list_of_users = db.root.list_of_users super(UserRepository, self).__init__()
def create(self): try: category = self.params.get("category") doc = Document(name=self.params["name"], category_id=category, document_id=self.params.get("document_id")) doc.put() self.redirect("/site/document/") except Exception, ex: self.render(text="Exception: %s" % ex)
def __init__(self, fileName): self._fN=fileName self._doc=Document() self._numStaples=0 self._scaffoldLength=0 decode(self._doc,file(self._fN).read()) self.getModelInfo() self.printModelInfo() self.vhLoop() self.numberScaffold()
def read_articles(path): articles = [] cnt = 0 for filename in os.listdir(path): with open(path + '/' + filename) as file: doc = Document(cnt, file.read()) doc.words, doc.sentences = process_document(doc.raw_text) count_tfidf(doc.sentences, doc.words) doc.graph = create_graph(doc.sentences, doc.words) cnt = cnt + 1 articles.append(doc) return articles
def new(self): query = db.GqlQuery("SELECT * FROM Page ORDER BY order DESC") self.page_num = 1 if query.count() > 0: page = query.get() self.page_num = page.order + 1 self.document = Document.get(self.params.get('id'))
def delete(self): key = self.params.get("key") res = {"status": "success", "msg": "削除しました"} document = Document.get(key) if document: document.delete() else: res = {"status": "error", "msg": "削除に失敗しました"} self.render(json=self.to_json(res))
def create_document(): if 'project' in request.json: project = request.json['project'] else: response = {'message': "Missing project"} response = make_response(response) return response, 400 if 'content' in request.json: content = request.json['content'] else: response = {'message': "Missing content"} response = make_response(response) return response, 400 doc = Document(content, [], []) doc.data = content doc.upload(project) return '', 204
def load_collection(self): documents = [] for doc in la('docs/'): lines = open('docs/' + doc, 'r').readlines() bow = [] for line in lines: bow += self.lineToarray(line) d = Document(doc, bow) documents.append(d) return documents
def searchDocuments(self): QApplication.instance().doclist.show() result = self.search.text() QApplication.instance().currentWord = result self.clearResults() documents = [] if result == "": for filepath in self.indexer.data['FILES']: QApplication.instance().doclist.addItem(Document(filepath, os.path.basename(filepath))) self.parent.leftDock.show() else: try: documentSet = parseResult(result) for filepath in documentSet: documents.append(Document(filepath, os.path.basename(filepath), result)) documents.sort(key=lambda x: x.rank, reverse=True) for doc in documents: QApplication.instance().doclist.addItem(doc) self.parent.leftDock.show() except ValueError: pass
def _create_item(self, metadata, parent): if metadata["Type"] == "CollectionType": new_object = Collection(metadata, parent) elif metadata["Type"] == "DocumentType": new_object = Document(metadata, parent) else: raise Exception("Unknown type %s" % metadata["Type"]) parent.add_child(new_object) return new_object
def create(self): #try: document = Document.get(self.params.get('document')) page = Page( name=self.params.get('name'), document=document, content=self.params.get('content'), order=int(self.params.get('order')) ) # データの保存 page.put() # URL '/page/' にリダイレクト self.redirect('/document/edit/'+self.params.get('document') )
def create_document(project_name): id_token = request.args.get('id_token') if id_token is None or id_token == "": response = { 'message': "ID Token is not included with the request uri in args" } response = make_response(response) return response, 400 requestor_email = get_email(id_token) if requestor_email is None: response = {'message': "ID Token has expired or is invalid"} response = make_response(response) return response, 400 users_col = get_col(project_name, "users") requestor = users_col.find_one({ 'email': requestor_email, 'isContributor': True }) if requestor is None: response = {'message': "You are not authorised to perform this action"} response = make_response(response) return response, 403 if 'content' in request.json: content = request.json['content'] else: response = {'message': "Missing content"} response = make_response(response) return response, 400 doc = Document(content, [], []) doc.data = content doc.upload(project_name) return '', 204
def upload(): dico = {} dico['metadata'] = {} output_dir = os.path.join(os.path.join(os.getcwd(), 'app'), 'output_dir/') if request.method == 'POST': file = request.files['file'] f_name = request.files["file"].filename doc = Document(file, f_name) _data = doc.refersTo() if 'error' not in list(_data.keys()): content = "" for key, value in _data.items(): if key != "content": dico['metadata'][key] = value else: dico[key] = value dico['metadata']['mime_type'] = request.files["file"].content_type else: resp = jsonify({'message': _data['error']}) resp.status_code = 400 return resp try: with open( os.path.join(output_dir, f_name.split('.')[0]) + '.json', 'w+') as outfile: json.dump(dico, outfile) except: print("Can't write json") return jsonify(dico) else: resp = jsonify( {'message': 'Cette méthode ne peut être exécuté que par un POST'}) resp.status_code = 405 return resp
def upload_file(): if request.method == 'POST': if 'projectName' in request.form: project_name = str(request.form['projectName']) if 'inputFile' not in request.files: response = {'status_code': 400, 'message': 'No file selected'} response = make_response(response) return response file = request.files['inputFile'] if file.filename == '': response = {'status_code': 400, 'message': 'No file selected'} response = make_response(response) return response if file: filename = secure_filename(file.filename) filelocation = os.path.join(uploads_dir, filename) file.save(filelocation) with open(filelocation) as csv_file: csv_reader = csv.reader(csv_file, delimiter=",") is_first_line = True for row in csv_reader: if is_first_line: is_first_line = False else: document = Document(ObjectId(row[0]), [], row[1]) # Find project database and populate document collection project = Project(project_name, [], []) project.add_document(document) # Delete file when done os.remove(filelocation) response = { 'status_code': 200, 'message': 'Documents imported successfully' } return make_response(response) else: response = { 'status_code': 400, 'message': 'No project id provided' } response = make_response(response) return response
def __init__(self): """docstring for __init__""" # initialize variables self._document = Document() self._document.setController(self) self._activePart = None self._filename = None self._fileOpenPath = None # will be set in _readSettings self._hasNoAssociatedFile = True self._pathViewInstance = None self._sliceViewInstance = None self._undoStack = None self.win = None self.fileopendialog = None self.filesavedialog = None self.settings = QSettings() self._readSettings() # call other init methods self._initWindow() if app().isInMaya(): self._initMaya() app().documentControllers.add(self)
def __init__(self, doc=None, fname=None): """docstring for __init__""" # initialize variables self._document = Document() if not doc else doc self._filename = fname self.win = None self._undoStack = None self._hasNoAssociatedFile = None self._sliceViewInstance = None self._pathViewInstance = None self._solidView = None self._activePart = None # call other init methods self.initWindow() self.initMaya() app().documentControllers.add(self)
def main(): logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) file_stream = FileStream( r"D:\Eigene Dateien\git\pandaLight-HDL" r"\pandaLight-tests\complete LED test\PANDA_LIGHT.vhd") lexer = VhdlLexer(file_stream) token_stream = CommonTokenStream(lexer) parser = VhdlParser(token_stream) listener = VhdlListener() tree = parser.design_file() walker = ParseTreeWalker() walker.walk(listener, tree) print(Document.from_tree(tree).tree_string())
def update(self): doc = Document.get(self.params.get("key")) published = self.params.get("published") if published != None and published == "True": doc.published = True else: doc.published = False doc.name = self.params.get("name") doc.categoey_id = self.params.get("category_id") c = db.GqlQuery("SELECT * FROM Category WHERE category_id = :1", doc.category_id).get() doc.category_name = c.name doc.content = self.params.get("content") doc.document_id = self.params.get("document_id") doc.put() self.redirect("/document/edit/" + self.params.get("key"))
def to_documents(lines): documents = [] for l in lines: a = l.strip().split(' ') num_terms = int(a[0]) # number of unique terms terms = [] counts = [] num_words = 0 # Add word to doc for t in a[1:]: b = t.split(':') w = int(b[0]) # term n_w = int(b[1]) # number of occurrence terms.append(w) counts.append(n_w) num_words += n_w # Add doc to corpus doc = Document(num_terms, num_words, terms, counts) documents.append(doc) return documents
def __init__(self, firstuse): app().documentControllers.add(self) self.doc = Document() self.idbank = IdBank() self.undoStack = QUndoStack() app().undoGroup.addStack(self.undoStack) self.win = DocumentWindow(docCtrlr=self) self.win.show() self.stdwin = StdWindow() self.webwin = WebWindow() self._filename = "untitled.cadnano" self.treeController = TreeController(self.win.treeview) self.createConnections() self.recentButton = None self.win.sliceGraphicsView.mouseMoveEvent = self.sliceViewMouseMove if firstuse == True: self.win.helplabel.setText(QString("It appears as though this is your first time using CaDNAno 2, would you like to view a tutorial?")) else: self.win.ignoreButton.hide() self.win.showHelpButton.hide() self.win.helplabel.hide()
class analysisHelpers(object): def __init__(self, fileName): self._fN=fileName self._doc=Document() self._numStaples=0 self._scaffoldLength=0 decode(self._doc,file(self._fN).read()) self.getModelInfo() self.printModelInfo() self.vhLoop() self.numberScaffold() ##Initialization Functions def vhLoop(self): for vh in self._vhList: vh._renumber=-1 vh._neighbors=self._part.getVirtualHelixNeighbors(vh) def getModelInfo(self): self._part=self._doc.selectedPart() self._vhList=self._part.getVirtualHelices() self._oligos=list(self._part.oligos()) def printModelInfo(self): self._numVH=len(self._vhList) self._numOligos=len(self._oligos) print "Design with %s virtual helices and %s oligos loaded" %(self._numVH,self._numOligos) #Sequence Application Functions def readSeqFile(self,sequenceFile): sqFile=file(sequenceFile) self._fullSeq=sqFile.read().strip() self._fullSeqLength=len(self._fullSeq) print "Sequence length %s" %(self._fullSeqLength) def applySequenceToScaffold(self, sequenceFile): self.readSeqFile(sequenceFile) #Find scaffold self.findScaffold() self._scaffold.applySequence(self._fullSeq) print "Applied sequence with %s length\n" %(len(self._scaffold.sequence())) self._scaffoldLength=len(self._scaffold.sequence()) def findScaffold(self): for x in self._oligos: scaf=x.isStaple() if scaf==False: self._scaffold=x #print "scaffold found" def getCircleMapData(self): self.numberScaffold() self.numberStaples() self.printCircleData() def numberScaffold(self): #Get start info self.findScaffold() count=1 first=0 for strand in self._scaffold.strand5p().generator3pStrand(): sLowIdx, sHighIdx = strand._baseIdxLow, strand._baseIdxHigh subn=strand.insertionLengthBetweenIdxs(sLowIdx, sHighIdx) difference=strand.length()+subn vh=strand.virtualHelix() if vh._renumber==-1: #print "Renumbering helix %s as %s\n" %(vh.number(), first) vh._renumber=first first=first+1 #print "length is %s" %difference count+=(difference) idx5p=strand.idx5Prime() idx3p=strand.idx3Prime() #if strand.isDrawn5to3 strand.num5Prime=count-difference strand.num3Prime=count-1 if not self._scaffoldLength: self._scaffoldLength=strand.num3Prime #scaffvh=self._scaffold._strand5p.virtualHelix() def numberStaples(self): for x in self._oligos: if x.isStaple()==True: self._numStaples+=1 for strand in x.strand5p().generator3pStrand(): strand.num5Prime=[] strand.num3Prime=[] #print "Staple part\n" scafComp=strand.getComplementStrands() if len(scafComp)>0: for p in range(0,len(scafComp)): dir1=scafComp[p].isDrawn5to3() diff53p=np.abs(scafComp[p].idx5Prime()-strand.idx3Prime()) diff35p=np.abs(scafComp[p].idx3Prime()-strand.idx5Prime()) strand.num5Prime.append(scafComp[p].num3Prime-diff35p) strand.num3Prime.append(scafComp[p].num5Prime+diff53p) def printCircleData(self): fileString="CD_" fileString+=self._fN fileString+=".csv" self._circleFileName=fileString self._circleFile=open(fileString,'w') self._circleFile.write("Staple locations on scaffold 5'->3'\n") for x in self._oligos: if x.isStaple()==True: stapleString="" count=0 for strand in x.strand5p().generator3pStrand(): if count>0: stapleString+="," scafComp=strand.getComplementStrands() if len(scafComp)>0: n=len(strand.num5Prime) for p in range(0,n): if p!=0: stapleString+="," stapleString+=("%s, %s") %(strand.num5Prime[p],strand.num3Prime[p]) count+=1 if stapleString: stapleString+="\n" #print stapleString self._circleFile.write(stapleString) self._circleFile.close() def getVirtualHelixSequences(self): for vh in self._vhList: seq='' first=1 minLoc=0 maxLoc=0 for scaffStr in vh.scaffoldStrandSet(): scaffStr._minMax=[] seq+=scaffStr.sequence() if minLoc==0 and maxLoc==0: minLoc=scaffStr.idx5Prime() maxLoc=scaffStr.idx3Prime() if scaffStr.isDrawn5to3(): if scaffStr.idx5Prime()<minLoc: minLoc=scaffStr.idx5Prime() if scaffStr.idx3Prime()>maxLoc: maxLoc=scaffStr.idx3Prime() else: if scaffStr.idx3Prime()<minLoc: minLoc=scaffStr.idx3Prime() if scaffStr.idx5Prime()>maxLoc: maxLoc=scaffStr.idx5Prime() scaffStr._minMax.append([minLoc,maxLoc]) vh._minMax=[minLoc,maxLoc] vh._sequence=seq def printScaffoldLength(self): return self._scaffoldLength def printCircleFileName(self): return self._circleFileName def setScaffoldLength(self,sfL): self._scaffoldLength=sfL def getVirtualHelixList(self): return self._vhList def getScaffoldStrand(self): return self._scaffold
from operator import attrgetter from model.document import Document from model.inverted_index import InvertedIndex if __name__ == "__main__": document = [] document.append(Document( "1", "Candi Prambanan merupakan salah satu candi yang ada di Indonesia")) document.append( Document("2", "Indonesia Merupakan Negara Yang Mempunyai Banyak Candi")) document.append(Document("3", "Liburan di Negara Berkembang")) # iterate doc doc = Document() for doc in document: print(doc.docId + " -> " + doc.content) # menampilkan konten dokumen # end iterate print("=======") print("Terms : ") print() iIndex = InvertedIndex.toInvertedIndex(document) print(iIndex)
def parse(self, file_path): """It parses the content of file_path and extracts relevant information from a TempEval-3 annotated file. Those information are packed in a Document object, which is our internal representation. """ assert os.path.isfile(file_path), 'File path does not exist!' logging.info('Document {}: parsing...'.format( os.path.relpath(file_path))) xml = etree.parse(file_path) text_node = xml.findall(".//TEXT")[0] text_string = etree.tostring(text_node, method='text', encoding='utf8') text_xml = etree.tostring(text_node, method='xml', encoding='utf8') text_string = unicode(text_string, 'UTF-8') text_xml = unicode(text_xml, 'UTF-8') right_chars = len(text_xml.split('</TEXT>')[1]) text_string = text_string[:-right_chars] text_xml = etree.tostring(text_node) # StanfordParser strips internally the text :( left_chars = len(text_string) - len(text_string.lstrip()) with Mute_stderr(): stanford_tree = CORENLP.parse(text_string) document = Document(file_path) document.text_offset = left_chars document.file_path = os.path.abspath(file_path) document.doc_id = os.path.basename(file_path) document.sec_times = self.get_dct(file_path) document.dct = document.sec_times.admission_date document.dct_text = document.dct.replace('-', '') document.title = os.path.basename(file_path) document.text = text_string document._coref = stanford_tree.get('coref', []) for num_sen, stanford_sentence in\ enumerate(stanford_tree['sentences']): collp_deps = stanford_sentence.get('collapsed_dependencies', None) basic_deps = stanford_sentence.get('basic_dependencies', None) parsetree = stanford_sentence.get('parsetree', u'') sentence_text = stanford_sentence.get('text', u'') sentence = Sentence(id_sentence=num_sen, basic_dependencies=basic_deps, collapsed_dependencies=collp_deps, parsetree=parsetree, text=sentence_text) for num_word, (word_form, attr) in\ enumerate(stanford_sentence['words']): offset_begin = int(attr['CharacterOffsetBegin']) - left_chars offset_end = int(attr['CharacterOffsetEnd']) - left_chars word = Word(word_form=word_form, char_offset_begin=offset_begin, char_offset_end=offset_end, lemma=attr['Lemma'], named_entity_tag=attr['NamedEntityTag'], part_of_speech=attr['PartOfSpeech'], id_token=num_word, id_sentence=num_sen) sentence.words.append(word) document.sentences.append(sentence) document.gold_annotations = self._get_annotations( xml, document) document.store_gold_annotations() document.complete_structure() logging.info('Document {}: parsed.'.format(os.path.relpath(file_path))) return document
def save_document(document): d = Document(document['name'], jwt.current_user.id) db.session.add(d) db.session.commit() return d
def upload_file(): id_token = request.args.get('id_token') if id_token is None or id_token == "": response = { 'message': "ID Token is not included with the request uri in args" } response = make_response(response) return response, 400 requestor_email = get_email(id_token) if requestor_email is None: response = {'message': "ID Token has expired or is invalid"} response = make_response(response) return response, 400 if request.method == 'POST': if 'projectName' in request.form: project_name = str(request.form['projectName']) else: response = {'message': 'No project id provided'} response = make_response(response) return response, 400 users_col = get_col(project_name, "users") requestor = users_col.find_one({ 'email': requestor_email, 'isContributor': True }) if requestor is None: response = { 'message': "You are not authorised to perform this action" } response = make_response(response) return response, 403 if 'inputFile' not in request.files: response = {'message': 'No file selected'} response = make_response(response) return response, 400 file = request.files['inputFile'] if file.filename == '': response = {'message': 'No file selected'} response = make_response(response) return response, 400 if file: filename = secure_filename(file.filename) filelocation = os.path.join(uploads_dir, filename) file.save(filelocation) with open(filelocation) as csv_file: csv_reader = csv.reader(csv_file, delimiter=",") is_first_line = True for row in csv_reader: if is_first_line: is_first_line = False else: document = Document(row[1], [], []) # Find project database and populate document collection project = Project(project_name, [], []) project.add_document(document) # Delete file when done os.remove(filelocation) response = {'message': 'Documents imported successfully'} response = make_response(response) return response, 200
def test_setup_document(): my_document = Document("data", [], []) assert (my_document.data == "data")
def _load_brush_icon_for_rawimage(self, brush): buf, w, h, stride = Document.load_image(brush.icon, 'RGB') brush.icon_preview = buf data = rawimage.mkRawimageData(w, h, buf, rawimage.RAWIMAGE_FORMAT_RAW_RGB_ID) return data
from model.document import Document from utils.DBUtils import get_db_session, array_to_bytes from utils.InitializeUtils import initialize if __name__ == '__main__': session = get_db_session() print("Initializing...") docs_df = initialize() print("Initialization completed!\n") print("Inserting documents into db...") for index, row in docs_df.iterrows(): doc = Document(id=row['id'], path=row['path'], filename=row['filename'], text=array_to_bytes(row['text'])) print("Inserting obj:", doc) session.add(doc) session.commit() print("Done!")
def parse(self, file_path): """It parses the content of file_path and extracts relevant information from a TempEval-3 annotated file. Those information are packed in a Document object, which is our internal representation. """ assert os.path.isfile(file_path), 'File path does not exist!' logging.info('Document {}: parsing...'.format( os.path.relpath(file_path))) xml = etree.parse(file_path) text_node = xml.findall(".//TEXT")[0] text_string = etree.tostring(text_node, method='text', encoding='utf8') text_xml = etree.tostring(text_node, method='xml', encoding='utf8') text_string = unicode(text_string, 'UTF-8') text_xml = unicode(text_xml, 'UTF-8') right_chars = len(text_xml.split('</TEXT>')[1]) text_string = text_string[:-right_chars] text_xml = etree.tostring(text_node) # StanfordParser strips internally the text :( left_chars = len(text_string) - len(text_string.lstrip()) with Mute_stderr(): stanford_tree = CORENLP.parse(text_string) document = Document(file_path) document.text_offset = left_chars document.file_path = os.path.abspath(file_path) document.doc_id = os.path.basename(file_path) document.sec_times = self.get_dct(file_path) document.dct = document.sec_times.admission_date document.dct_text = document.dct.replace('-', '') document.title = os.path.basename(file_path) document.text = text_string document._coref = stanford_tree.get('coref', []) for num_sen, stanford_sentence in\ enumerate(stanford_tree['sentences']): collp_deps = stanford_sentence.get('collapsed_dependencies', None) basic_deps = stanford_sentence.get('basic_dependencies', None) parsetree = stanford_sentence.get('parsetree', u'') sentence_text = stanford_sentence.get('text', u'') sentence = Sentence(id_sentence=num_sen, basic_dependencies=basic_deps, collapsed_dependencies=collp_deps, parsetree=parsetree, text=sentence_text) for num_word, (word_form, attr) in\ enumerate(stanford_sentence['words']): offset_begin = int(attr['CharacterOffsetBegin']) - left_chars offset_end = int(attr['CharacterOffsetEnd']) - left_chars word = Word(word_form=word_form, char_offset_begin=offset_begin, char_offset_end=offset_end, lemma=attr['Lemma'], named_entity_tag=attr['NamedEntityTag'], part_of_speech=attr['PartOfSpeech'], id_token=num_word, id_sentence=num_sen) sentence.words.append(word) document.sentences.append(sentence) document.gold_annotations = self._get_annotations(xml, document) document.store_gold_annotations() document.complete_structure() logging.info('Document {}: parsed.'.format(os.path.relpath(file_path))) return document
def edit(self): self.categories = Category.all().order("-post_at") self.rec = Document.get(self.params.get("id")) self.pages = db.GqlQuery("SELECT * FROM Page WHERE document = :1 ORDER BY order", db.Key(self.params.get("id")))
class DocumentController(): """ The document controller. Hooks high level (read file/write file, add submodel, etc) UI elements to their corresponding actions in the model """ def __init__(self, firstuse): app().documentControllers.add(self) self.doc = Document() self.idbank = IdBank() self.undoStack = QUndoStack() app().undoGroup.addStack(self.undoStack) self.win = DocumentWindow(docCtrlr=self) self.win.show() self.stdwin = StdWindow() self.webwin = WebWindow() self._filename = "untitled.cadnano" self.treeController = TreeController(self.win.treeview) self.createConnections() self.recentButton = None self.win.sliceGraphicsView.mouseMoveEvent = self.sliceViewMouseMove if firstuse == True: self.win.helplabel.setText(QString("It appears as though this is your first time using CaDNAno 2, would you like to view a tutorial?")) else: self.win.ignoreButton.hide() self.win.showHelpButton.hide() self.win.helplabel.hide() def sliceViewMouseMove(self, event): print "hello" """ Roger Additions """ """ def helpwindow(self): #file = open("usagetracker.txt", 'w') filename = "C:/Users/Roger Conturie/workspace/Final Cadnano/cadnano2/ui/usagetracker.txt" file = open(filename, 'r') timesopened = file.readline() file.close() if timesopened == '0': self.webwin.show() file = open(filename, 'w') file.write(str(int(timesopened) + 1)) file.close() """ def standardHelpClicked(self): self.stdwin.show() def networkHelpClicked(self): import os if os.system("ping google.com -n 1") == 1: print "no connection" else: self.webwin.show() def ignoreClicked(self): self.win.ignoreButton.hide() self.win.showHelpButton.hide() self.win.helplabel.hide() def showHelpClicked(self): self.stdwin.show() """ End Roger Additions """ def filename(self): return self._filename def setFilename(self, proposedFName): if self._filename == proposedFName: return True self._filename = proposedFName self.setDirty(True) return True def createConnections(self): """ Organizational method to collect signal/slot connectors. """ self.win.actionNewHoneycombPart.triggered.connect(self.hcombClicked) self.win.actionNewSquarePart.triggered.connect(self.squareClicked) self.win.actionNew.triggered.connect(app().newDocument) self.win.actionOpen.triggered.connect(self.openClicked) self.win.actionClose.triggered.connect(self.closeClicked) self.win.actionSave.triggered.connect(self.saveClicked) self.win.actionSVG.triggered.connect(self.svgClicked) self.win.actionStandard_Help.triggered.connect(self.standardHelpClicked) self.win.actionNetwork_Help.triggered.connect(self.networkHelpClicked) self.win.ignoreButton.pressed.connect(self.ignoreClicked) self.win.showHelpButton.pressed.connect(self.showHelpClicked) # self.win.actionSave_As.triggered.connect(self.saveAsClicked) # self.win.actionQuit.triggered.connect(self.closeClicked) # self.win.actionAdd.triggered.connect(self.addClicked) # self.win.actionDelete.triggered.connect(self.deleteClicked) # self.win.actionCut.triggered.connect(self.cutClicked) # self.win.actionPaste.triggered.connect(self.pasteClicked) # self.win.actionMoveUp.triggered.connect(self.moveUpClicked) # self.win.actionMoveDown.triggered.connect(self.moveDownClicked) # self.win.actionPromote.triggered.connect(self.promoteClicked) # self.win.actionDemote.triggered.connect(self.demoteClicked) # end def def setDirty(self, dirty=True): self.win.setWindowModified(dirty) #end def def newClicked(self): """docstring for newClicked""" print "new clicked" self.recentButton = "new" # end def def openClicked(self): """docstring for openClicked""" print "open clicked" self.recentButton = "open" # end def def closeClicked(self): """docstring for closeClicked""" print "close clicked" self.recentButton = "close" # end def def saveClicked(self): """docstring for saveClicked""" try: f = open(self.filename()) f.write(encode(self.doc)) f.close() except Exception: print "Save " return True self.recentButton = "save" def saveAsClicked(): filename = self.filename() if filename == None: directory = "." else: directory = QFileInfo(filename).path() filename = QFileDialog.getSaveFileName(self.win,\ "%s - Save As" % QApplication.applicationName(),\ directory,\ "%s (*.cadnano)" % QApplication.applicationName()) if filename.isEmpty(): return False if not filename.toLower().endswith(".cadnano"): filename += ".cadnano" self.setFilename(filename) self.recentButton = "saveAs" return self.saveClicked() def svgClicked(self): """docstring for svgClicked""" print "svg clicked" self.recentButton = "svg" # end def def hcombClicked(self): """docstring for hcombClicked""" print "+honeycomb clicked" self.addHoneycombHelixGroup() self.recentButton = "hcomb" # end def def squareClicked(self): """docstring for squareClicked""" print "+square clicked" self.recentButton = "square" # end def def addHoneycombHelixGroup(self, nrows=20, ncolumns=20): """docstring for addHoneycombHelixGroup""" # Create a new DNA part objId = self.idbank.get() instId = objId#self.idbank.get() dnaPartInst = self.doc.addDnaPart(objId, instId,\ crossSectionType='honeycomb') # Add the part to the Tree view name = "Part.%d" % objId self.treeController.addPartNode(name, dnaPartInst) # Create a Slice view of part shg = SliceHelixGroup(dnaPartInst, nrows, ncolumns,\ scene=self.win.slicescene,\ controller=self.win.sliceController) self.win.slicescene.addItem(shg) # Create a Path view of the part phg = PathHelixGroup(dnaPartInst, scene=self.win.pathscene,\ controller=self.win.pathController) self.win.pathscene.addItem(phg) # Connect the slice shg.helixAdded.connect(phg.handleHelixAdded) shg.sliceHelixClicked.connect(phg.handleSliceHelixClick) dnaPartInst.partselected.connect(shg.bringToFront) dnaPartInst.partselected.connect(phg.bringToFront) self.recentButton = "addHoneycombHelixGroup" # end def def deleteClicked(self): index = self.win.treeview.currentIndex() if not index.isValid(): return name = self.treemodel.data(index).toString() rows = self.treemodel.rowCount(index) if rows == 0: message = "<p>Delete '%s'" % name # end if elif rows == 1: message = "<p>Delete '%s' and its child (and " +\ "grandchildren etc.)" % name # end elif elif rows > 1: message = "<p>Delete '%s' and its %d children (and " +\ "grandchildren etc.)" % (name, rows) # end elif if not self.okToDelete(this, QString("Delete"), QString(message)): return self.treemodel.removeRow(index.row(), index.parent()) self.setDirty(True) self.updateUi() self.recentButton = "addHoneycombHelixGroup" # end def def okToDelete(self, parent, title, text, detailedText): """ """ messageBox = QMessageBox(parent) if parent: messageBox.setWindowModality(Qt.WindowModal) # end if messageBox.setIcon(QMessageBox.Question) messageBox.setWindowTitle(\ QString("%1 - %2").arg(QApplication.applicationName()).arg(title)) messageBox.setText(text) if not detailedText.isEmpty(): messageBox.setInformativeText(detailedText) # end if deleteButton = messageBox.addButton(QString("&Delete"),\ QMessageBox.AcceptRole) messageBox.addButton(QString("Do &Not Delete"),\ QMessageBox.RejectRole) messageBox.setDefaultButton(deleteButton) messageBox.exec_() return messageBox.clickedButton() == deleteButton # end def def okToClear(self, savedata, parent, title, text, detailedText): """ savedata is a function pointer """ assert savedata and parent messageBox = QMessageBox(parent) if parent: messageBox.setWindowModality(Qt.WindowModal) # end if messageBox.setIcon(QMessageBox.Question) messageBox.setWindowTitle(\ QString("%1 - %2").arg(QApplication.applicationName()).arg(title)) messageBox.setText(text) if not detailedText.isEmpty(): messageBox.setInformativeText(detailedText) # end if saveButton = messageBox.addButton(QMessageBox.Save) messageBox.addButton(QMessageBox.Save) messageBox.addButton(QMessageBox.Discard) messageBox.addButton(QMessageBox.Cancel) messageBox.setDefaultButton(saveButton) messageBox.exec_() if messageBox.clickedButton() == messageBox.button(QMessageBox.Cancel): return False if messageBox.clickedButton() == messageBox.button(QMessageBox.Save): return parent.savedata() # how to return the function (lambda?) return True # end def def createAction(self, icon, text, parent, shortcutkey): """ returns a QAction object """ action = QAction(QIcon(icon), text, parent) if not shorcutkey.isEmpty(): action.setShortcut(shortcutkey) # end if return action # end def def updateUi(self): """ """ #self.win.actionSave.setEnabled(self.win.isWindowModified()) rows = self.treemodel.rowCount() #self.win.actionSave_As.setEnabled(self.win.isWindowModified() or rows) #self.win.actionHideOrShowItems.setEnabled(rows) enable = self.win.treeview.currentIndex().isValid() # actions = [self.win.actionDelete,\ # self.win.actionMoveUp,\ # self.win.actionMoveDown,\ # self.win.actionCut,\ # self.win.actionPromote,\ # self.win.actionDemote] # for action in actions: # action.setEnabled(enable) # # end for # self.win.actionStartOrStop.setEnabled(rows); # self.win.actionPaste.setEnabled(self.treemodel.hasCutItem()) #end def def cutClicked(self): """""" self.win.actionPaste.setEnabled(self.treeController.cut()) # end def def pasteClicked(self): """""" self.treeController.paste() # end def def moveUpClicked(self): """""" self.treeController.moveUp() # end def def moveDownClicked(self): """""" self.treeController.moveDown() # end def def promoteClicked(self): """""" self.treeController.promote() #end def def demoteClicked(self): """""" self.treeController.demote() #end def def hideOrShowNode(self, hide, index): """""" self.treeController.hideOrShowNode()
def __init__(self, term="", posting=Posting(Document())): self.posting = posting self.term = term
def init(cls): cls._current_document = Document() log = vtk.vtkFileOutputWindow() #para guardar los mensajes de vtk log.SetFileName("logs/vtk.log") #fichero donde se guardan log.SetInstance(log) #usar este fichero
class DocumentController(): """ Connects UI buttons to their corresponding actions in the model. """ ### INIT METHODS ### def __init__(self): """docstring for __init__""" # initialize variables self._document = Document() self._document.setController(self) self._activePart = None self._filename = None self._fileOpenPath = None # will be set in _readSettings self._hasNoAssociatedFile = True self._pathViewInstance = None self._sliceViewInstance = None self._undoStack = None self.win = None self.fileopendialog = None self.filesavedialog = None self.settings = QSettings() self._readSettings() # call other init methods self._initWindow() if app().isInMaya(): self._initMaya() app().documentControllers.add(self) def _initWindow(self): """docstring for initWindow""" self.win = DocumentWindow(docCtrlr=self) self.win.setWindowIcon(QIcon('ui/mainwindow/images/cadnano2-app-icon.png')) app().documentWindowWasCreatedSignal.emit(self._document, self.win) self._connectWindowSignalsToSelf() self.win.show() def _initMaya(self): """ Initialize Maya-related state. Delete Maya nodes if there is an old document left over from the same session. Set up the Maya window. """ # There will only be one document if (app().activeDocument and app().activeDocument.win and not app().activeDocument.win.close()): return del app().activeDocument app().activeDocument = self import maya.OpenMayaUI as OpenMayaUI import sip ptr = OpenMayaUI.MQtUtil.mainWindow() mayaWin = sip.wrapinstance(long(ptr), QMainWindow) self.windock = QDockWidget("cadnano") self.windock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.windock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.windock.setWidget(self.win) mayaWin.addDockWidget(Qt.DockWidgetArea(Qt.LeftDockWidgetArea), self.windock) self.windock.setVisible(True) def _connectWindowSignalsToSelf(self): """This method serves to group all the signal & slot connections made by DocumentController""" self.win.actionNew.triggered.connect(self.actionNewSlot) self.win.actionOpen.triggered.connect(self.actionOpenSlot) self.win.actionClose.triggered.connect(self.actionCloseSlot) self.win.actionSave.triggered.connect(self.actionSaveSlot) self.win.actionSave_As.triggered.connect(self.actionSaveAsSlot) self.win.actionSVG.triggered.connect(self.actionSVGSlot) self.win.actionAutoStaple.triggered.connect(self.actionAutostapleSlot) self.win.actionExportStaples.triggered.connect(self.actionExportStaplesSlot) self.win.actionPreferences.triggered.connect(self.actionPrefsSlot) self.win.actionModify.triggered.connect(self.actionModifySlot) self.win.actionNewHoneycombPart.triggered.connect(\ self.actionAddHoneycombPartSlot) self.win.actionNewSquarePart.triggered.connect(\ self.actionAddSquarePartSlot) self.win.closeEvent = self.windowCloseEventHandler self.win.actionAbout.triggered.connect(self.actionAboutSlot) self.win.actionCadnanoWebsite.triggered.connect(self.actionCadnanoWebsiteSlot) self.win.actionFeedback.triggered.connect(self.actionFeedbackSlot) self.win.actionFilterHandle.triggered.connect(self.actionFilterHandleSlot) self.win.actionFilterEndpoint.triggered.connect(self.actionFilterEndpointSlot) self.win.actionFilterStrand.triggered.connect(self.actionFilterStrandSlot) self.win.actionFilterXover.triggered.connect(self.actionFilterXoverSlot) self.win.actionFilterScaf.triggered.connect(self.actionFilterScafSlot) self.win.actionFilterStap.triggered.connect(self.actionFilterStapSlot) self.win.actionRenumber.triggered.connect(self.actionRenumberSlot) ### SLOTS ### def undoStackCleanChangedSlot(self): """The title changes to include [*] on modification.""" self.win.setWindowModified(not self.undoStack().isClean()) self.win.setWindowTitle(self.documentTitle()) def actionAboutSlot(self): """Displays the about cadnano dialog.""" from ui.dialogs.ui_about import Ui_About dialog = QDialog() dialogAbout = Ui_About() # reusing this dialog, should rename dialog.setStyleSheet("QDialog { background-image: url(ui/dialogs/images/cadnano2-about.png); background-repeat: none; }") dialogAbout.setupUi(dialog) dialog.exec_() filterList = ["strand", "endpoint", "xover", "virtualHelix"] def actionFilterHandleSlot(self): """Disables all other selection filters when active.""" fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover fH.setChecked(True) if fE.isChecked(): fE.setChecked(False) if fS.isChecked(): fS.setChecked(False) if fX.isChecked(): fX.setChecked(False) self._document.documentSelectionFilterChangedSignal.emit(["virtualHelix"]) def actionFilterEndpointSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover if fH.isChecked(): fH.setChecked(False) if not fS.isChecked() and not fX.isChecked(): fE.setChecked(True) self._strandFilterUpdate() # end def def actionFilterStrandSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover if fH.isChecked(): fH.setChecked(False) if not fE.isChecked() and not fX.isChecked(): fS.setChecked(True) self._strandFilterUpdate() # end def def actionFilterXoverSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover if fH.isChecked(): fH.setChecked(False) if not fE.isChecked() and not fS.isChecked(): fX.setChecked(True) self._strandFilterUpdate() # end def def actionFilterScafSlot(self): """Remains checked if no other strand-type filter is active.""" fSc = self.win.actionFilterScaf fSt = self.win.actionFilterStap if not fSc.isChecked() and not fSt.isChecked(): fSc.setChecked(True) self._strandFilterUpdate() def actionFilterStapSlot(self): """Remains checked if no other strand-type filter is active.""" fSc = self.win.actionFilterScaf fSt = self.win.actionFilterStap if not fSc.isChecked() and not fSt.isChecked(): fSt.setChecked(True) self._strandFilterUpdate() # end def def _strandFilterUpdate(self): win = self.win filterList = [] if win.actionFilterEndpoint.isChecked(): filterList.append("endpoint") if win.actionFilterStrand.isChecked(): filterList.append("strand") if win.actionFilterXover.isChecked(): filterList.append("xover") if win.actionFilterScaf.isChecked(): filterList.append("scaffold") if win.actionFilterStap.isChecked(): filterList.append("staple") self._document.documentSelectionFilterChangedSignal.emit(filterList) # end def def actionNewSlot(self): """ 1. If document is has no parts, do nothing. 2. If document is dirty, call maybeSave and continue if it succeeds. 3. Create a new document and swap it into the existing ctrlr/window. """ # clear/reset the view! if len(self._document.parts()) == 0: return # no parts if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if self.filesavedialog != None: self.filesavedialog.finished.connect(self.newClickedCallback) else: # user did not save self.newClickedCallback() # finalize new def actionOpenSlot(self): """ 1. If document is untouched, proceed to open dialog. 2. If document is dirty, call maybesave and continue if it succeeds. Downstream, the file is selected in openAfterMaybeSave, and the selected file is actually opened in openAfterMaybeSaveCallback. """ if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if hasattr(self, "filesavedialog"): # user did save if self.filesavedialog != None: self.filesavedialog.finished.connect(self.openAfterMaybeSave) else: self.openAfterMaybeSave() # windows else: # user did not save self.openAfterMaybeSave() # finalize new def actionCloseSlot(self): """This will trigger a Window closeEvent.""" #print "closing" if util.isWindows(): #print "close win" self.win.close() if not app().isInMaya(): #print "exit app" import sys sys.exit(1) def actionSaveSlot(self): """SaveAs if necessary, otherwise overwrite existing file.""" if self._hasNoAssociatedFile: self.saveFileDialog() return self.writeDocumentToFile() def actionSaveAsSlot(self): """Open a save file dialog so user can choose a name.""" self.saveFileDialog() def actionSVGSlot(self): """docstring for actionSVGSlot""" fname = os.path.basename(str(self.filename())) if fname == None: directory = "." else: directory = QFileInfo(fname).path() fdialog = QFileDialog( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.svg)" % QApplication.applicationName()) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.svgsavedialog = fdialog self.svgsavedialog.filesSelected.connect(self.saveSVGDialogCallback) fdialog.open() class DummyChild(QGraphicsItem): def boundingRect(self): return QRect(200, 200) # self.parentObject().boundingRect() def paint(self, painter, option, widget=None): pass def saveSVGDialogCallback(self, selected): if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if fname.isEmpty() or os.path.isdir(fname): return False fname = str(fname) if not fname.lower().endswith(".svg"): fname += ".svg" if self.svgsavedialog != None: self.svgsavedialog.filesSelected.disconnect(self.saveSVGDialogCallback) del self.svgsavedialog # prevents hang self.svgsavedialog = None generator = QSvgGenerator() generator.setFileName(fname) generator.setSize(QSize(200, 200)) generator.setViewBox(QRect(0, 0, 2000, 2000)) painter = QPainter() # Render through scene # painter.begin(generator) # self.win.pathscene.render(painter) # painter.end() # Render item-by-item painter = QPainter() styleOption = QStyleOptionGraphicsItem() q = [self.win.pathroot] painter.begin(generator) while q: graphicsItem = q.pop() transform = graphicsItem.itemTransform(self.win.sliceroot)[0] painter.setTransform(transform) if graphicsItem.isVisible(): graphicsItem.paint(painter, styleOption, None) q.extend(graphicsItem.childItems()) painter.end() def actionExportStaplesSlot(self): """ Triggered by clicking Export Staples button. Opens a file dialog to determine where the staples should be saved. The callback is exportStaplesCallback which collects the staple sequences and exports the file. """ # Validate that no staple oligos are loops. part = self.activePart() stapLoopOlgs = part.getStapleLoopOligos() if stapLoopOlgs: from ui.dialogs.ui_warning import Ui_Warning dialog = QDialog() dialogWarning = Ui_Warning() # reusing this dialog, should rename dialog.setStyleSheet("QDialog { background-image: url(ui/dialogs/images/cadnano2-about.png); background-repeat: none; }") dialogWarning.setupUi(dialog) locs = ", ".join([o.locString() for o in stapLoopOlgs]) msg = "Part contains staple loop(s) at %s.\n\nUse the break tool to introduce 5' & 3' ends before exporting. Loops have been colored red; use undo to revert." % locs dialogWarning.title.setText("Staple validation failed") dialogWarning.message.setText(msg) for o in stapLoopOlgs: o.applyColor(styles.stapColors[0].name()) dialog.exec_() return # Proceed with staple export. fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") self.saveStaplesDialog = None self.exportStaplesCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.saveStaplesDialog = fdialog self.saveStaplesDialog.filesSelected.connect(self.exportStaplesCallback) fdialog.open() # end def def actionPrefsSlot(self): app().prefsClicked() def actionAutostapleSlot(self): part = self.activePart() if part: self.win.pathGraphicsView.setViewportUpdateOn(False) part.autoStaple() self.win.pathGraphicsView.setViewportUpdateOn(True) def actionModifySlot(self): """ Notifies that part root items that parts should respond to modifier selection signals. """ # uncomment for debugging # isChecked = self.win.actionModify.isChecked() # self.win.pathroot.setModifyState(isChecked) # self.win.sliceroot.setModifyState(isChecked) if app().isInMaya(): isChecked = self.win.actionModify.isChecked() self.win.pathroot.setModifyState(isChecked) self.win.sliceroot.setModifyState(isChecked) self.win.solidroot.setModifyState(isChecked) def actionAddHoneycombPartSlot(self): """docstring for actionAddHoneycombPartSlot""" part = self._document.addHoneycombPart() self.setActivePart(part) def actionAddSquarePartSlot(self): """docstring for actionAddSquarePartSlot""" part = self._document.addSquarePart() self.setActivePart(part) def actionRenumberSlot(self): coordList = self.win.pathroot.getSelectedPartOrderedVHList() part = self.activePart() part.renumber(coordList) # end def ### ACCESSORS ### def document(self): return self._document def window(self): return self.win def setDocument(self, doc): """ Sets the controller's document, and informs the document that this is its controller. """ self._document = doc doc.setController(self) def activePart(self): if self._activePart == None: self._activePart = self._document.selectedPart() return self._activePart def setActivePart(self, part): self._activePart = part def undoStack(self): return self._document.undoStack() ### PRIVATE SUPPORT METHODS ### def newDocument(self, doc=None, fname=None): """Creates a new Document, reusing the DocumentController.""" self._document.resetViews() self._document.removeAllParts() # clear out old parts self._document.undoStack().clear() # reset undostack self._filename = fname if fname else "untitled.json" self._hasNoAssociatedFile = fname == None self._activePart = None self.win.setWindowTitle(self.documentTitle() + '[*]') def saveFileDialog(self): fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.json)" % QApplication.applicationName()) self.writeDocumentToFile(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.json)" % QApplication.applicationName()) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.filesavedialog = fdialog self.filesavedialog.filesSelected.connect( self.saveFileDialogCallback) fdialog.open() # end def def _readSettings(self): """ Reads settings. Currenly this just loads the path of the last opened file, which is stored as self._fileOpenPath """ self.settings.beginGroup("FileSystem") self._fileOpenPath = self.settings.value("openpath", QDir().homePath()).toString() self.settings.endGroup() def _writeFileOpenPath(self, path): """ Makes sure to save/remember the *directory* path of the last opened file to settings. """ self._fileOpenPath = path self.settings.beginGroup("FileSystem") self.settings.setValue("openpath", path) self.settings.endGroup() ### SLOT CALLBACKS ### def actionNewSlotCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if self.filesavedialog != None: self.filesavedialog.finished.disconnect(self.actionNewSlotCallback) del self.filesavedialog # prevents hang (?) self.filesavedialog = None self.newDocument() def exportStaplesCallback(self, selected): """Export all staple sequences to selected CSV file.""" if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if fname.isEmpty() or os.path.isdir(fname): return False fname = str(fname) if not fname.lower().endswith(".csv"): fname += ".csv" if self.saveStaplesDialog != None: self.saveStaplesDialog.filesSelected.disconnect(self.exportStaplesCallback) # manual garbage collection to prevent hang (in osx) del self.saveStaplesDialog self.saveStaplesDialog = None # write the file output = self.activePart().getStapleSequences() with open(fname, 'w') as f: f.write(output) # end def def newClickedCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if self.filesavedialog != None: self.filesavedialog.finished.disconnect(self.newClickedCallback) del self.filesavedialog # prevents hang (?) self.filesavedialog = None self.newDocument() def openAfterMaybeSaveCallback(self, selected): """ Receives file selection info from the dialog created by openAfterMaybeSave, following user input. Extracts the file name and passes it to the decode method, which returns a new document doc, which is then set as the open document by newDocument. Calls finalizeImport and disconnects dialog signaling. """ if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if not fname or os.path.isdir(fname): return False fname = str(fname) self._writeFileOpenPath(os.path.dirname(fname)) self.newDocument(fname=fname) with open(fname) as fd: decode(self._document, fd.read()) if hasattr(self, "filesavedialog"): # user did save if self.fileopendialog != None: self.fileopendialog.filesSelected.disconnect(\ self.openAfterMaybeSaveCallback) # manual garbage collection to prevent hang (in osx) del self.fileopendialog self.fileopendialog = None def saveFileDialogCallback(self, selected): """If the user chose to save, write to that file.""" if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if fname.isEmpty() or os.path.isdir(fname): return False fname = str(fname) if not fname.lower().endswith(".json"): fname += ".json" if self.filesavedialog != None: self.filesavedialog.filesSelected.disconnect( self.saveFileDialogCallback) del self.filesavedialog # prevents hang self.filesavedialog = None self.writeDocumentToFile(fname) self._writeFileOpenPath(os.path.dirname(fname)) ### EVENT HANDLERS ### def windowCloseEventHandler(self, event): """Intercept close events when user attempts to close the window.""" if self.maybeSave(): event.accept() if app().isInMaya(): self.windock.setVisible(False) del self.windock self.windock = None app().documentControllers.remove(self) else: event.ignore() self.actionCloseSlot() ### FILE INPUT ## def documentTitle(self): fname = os.path.basename(str(self.filename())) if not self.undoStack().isClean(): fname += '[*]' return fname def filename(self): return self._filename def setFilename(self, proposedFName): if self._filename == proposedFName: return True self._filename = proposedFName self._hasNoAssociatedFile = False self.win.setWindowTitle(self.documentTitle()) return True def openAfterMaybeSave(self): """ This is the method that initiates file opening. It is called by actionOpenSlot to spawn a QFileDialog and connect it to a callback method. """ path = self._fileOpenPath if util.isWindows(): # required for native looking file window#"/", fname = QFileDialog.getOpenFileName( None, "Open Document", path, "cadnano1 / cadnano2 Files (*.nno *.json *.cadnano)") self.filesavedialog = None self.openAfterMaybeSaveCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "Open Document", path, "cadnano1 / cadnano2 Files (*.nno *.json *.cadnano)") fdialog.setAcceptMode(QFileDialog.AcceptOpen) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.fileopendialog = fdialog self.fileopendialog.filesSelected.connect(self.openAfterMaybeSaveCallback) fdialog.open() # end def ### FILE OUTPUT ### def maybeSave(self): """Save on quit, check if document changes have occured.""" if app().dontAskAndJustDiscardUnsavedChanges: return True if not self.undoStack().isClean(): # document dirty? savebox = QMessageBox(QMessageBox.Warning, "Application", "The document has been modified.\nDo you want to save your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self.win, Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet) savebox.setWindowModality(Qt.WindowModal) save = savebox.button(QMessageBox.Save) discard = savebox.button(QMessageBox.Discard) cancel = savebox.button(QMessageBox.Cancel) save.setShortcut("Ctrl+S") discard.setShortcut(QKeySequence("D,Ctrl+D")) cancel.setShortcut(QKeySequence("C,Ctrl+C,.,Ctrl+.")) ret = savebox.exec_() del savebox # manual garbage collection to prevent hang (in osx) if ret == QMessageBox.Save: return self.actionSaveAsSlot() elif ret == QMessageBox.Cancel: return False return True def writeDocumentToFile(self, filename=None): if filename == None: assert(not self._hasNoAssociatedFile) filename = self.filename() try: with open(filename, 'w') as f: helixOrderList = self.win.pathroot.getSelectedPartOrderedVHList() encode(self._document, helixOrderList, f) except IOError: flags = Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet errorbox = QMessageBox(QMessageBox.Critical, "cadnano", "Could not write to '%s'." % filename, QMessageBox.Ok, self.win, flags) errorbox.setWindowModality(Qt.WindowModal) errorbox.open() return False self.undoStack().setClean() self.setFilename(filename) return True def actionCadnanoWebsiteSlot(self): import webbrowser webbrowser.open("http://cadnano.org/") def actionFeedbackSlot(self): import webbrowser webbrowser.open("http://cadnano.org/feedback")
def test_setup_document(): my_document = Document(1, "data") assert(my_document.identifier == 1 and my_document.data == "data")
class DocumentController: """ Connects UI buttons to their corresponding actions in the model. """ ### INIT METHODS ### def __init__(self, doc=None, fname=None): """docstring for __init__""" # initialize variables self._document = Document() if not doc else doc self._filename = fname self.win = None self._undoStack = None self._hasNoAssociatedFile = None self._sliceViewInstance = None self._pathViewInstance = None self._solidView = None self._activePart = None # call other init methods self.initWindow() self.initMaya() app().documentControllers.add(self) def initWindow(self): """docstring for initWindow""" self.win = DocumentWindow(docCtrlr=self) self.connectWindowSignalsToSelf() self.win.show() def connectWindowSignalsToSelf(self): """This method serves to group all the signal & slot connections made by DocumentController""" self.win.actionNew.triggered.connect(self.actionNewSlot) self.win.actionOpen.triggered.connect(self.actionOpenSlot) self.win.actionClose.triggered.connect(self.actionCloseSlot) self.win.actionSave.triggered.connect(self.actionSaveSlot) self.win.actionSave_As.triggered.connect(self.actionSaveAsSlot) self.win.actionSVG.triggered.connect(self.actionSVGSlot) self.win.actionAutoStaple.triggered.connect(self.actionAutostapleSlot) self.win.actionExportStaples.triggered.connect(self.actionExportStaplesSlot) self.win.actionPreferences.triggered.connect(self.actionPrefsSlot) self.win.actionModify.triggered.connect(self.actionModifySlot) self.win.actionNewHoneycombPart.triggered.connect(self.actionAddHoneycombPartSlot) self.win.actionNewSquarePart.triggered.connect(self.actionAddSquarePartSlot) self.win.closeEvent = self.windowCloseEventHandler def initMaya(self): """docstring for initMaya""" if app().isInMaya(): # There will only be one document if app().activeDocument and app().activeDocument.win and not app().activeDocument.win.close(): return del app().activeDocument app().deleteAllMayaNodes() app().activeDocument = self ### SLOTS ### def undoStackCleanChangedSlot(self): """The title changes to include [*] on modification.""" self.win.setWindowModified(not self.undoStack().isClean()) self.win.setWindowTitle(self.documentTitle()) def actionNewSlot(self): """ 1. If document is has no parts, do nothing. 2. If document is dirty, call maybeSave and continue if it succeeds. 3. Create a new document and swap it into the existing ctrlr/window. """ if len(self._document.parts()) == 0: # print "no parts!" return # no parts if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if hasattr(self, "filesavedialog"): # user did save self.filesavedialog.finished.connect(self.newClickedCallback) else: # user did not save self.newClickedCallback() # finalize new def actionOpenSlot(self): """ 1. If document is untouched, proceed to open dialog. 2. If document is dirty, call maybesave and continue if it succeeds. Downstream, the file is selected in openAfterMaybeSave, and the selected file is actually opened in openAfterMaybeSaveCallback. """ if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if hasattr(self, "filesavedialog"): # user did save if self.filesavedialog != None: self.filesavedialog.finished.connect(self.openAfterMaybeSave) else: self.openAfterMaybeSave() # windows else: # user did not save self.openAfterMaybeSave() # finalize new def actionCloseSlot(self): """This will trigger a Window closeEvent.""" if util.isWindows(): self.win.close() def actionSaveSlot(self): """SaveAs if necessary, otherwise overwrite existing file.""" if self._hasNoAssociatedFile: self.saveFileDialog() return # if importedFromJson: # self.saveFileDialog() # return self.writeDocumentToFile() def actionSaveAsSlot(self): """Open a save file dialog so user can choose a name.""" self.saveFileDialog() def actionSVGSlot(self): """docstring for actionSVGSlot""" pass def actionExportStaplesSlot(self): """ Triggered by clicking Export Staples button. Opens a file dialog to determine where the staples should be saved. The callback is exportCSVCallback which collects the staple sequences and exports the file. """ fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)" ) self.saveCSVdialog = None self.exportFile(fname) else: # access through non-blocking callback fdialog = QFileDialog(self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) # fdialog.exec_() # or .show(), or .open() self.saveCSVdialog = fdialog self.saveCSVdialog.filesSelected.connect(self.exportCSVCallback) fdialog.open() # end def def actionPrefsSlot(self): """docstring for actionPrefsSlot""" app().prefsClicked def actionAutostapleSlot(self): """docstring for actionAutostapleSlot""" self.activePart().autoStaple() def actionModifySlot(self): """docstring for actionModifySlot""" pass def actionAddHoneycombPartSlot(self): """docstring for actionAddHoneycombPartSlot""" part = self._document.addDnaHoneycombPart() self.setActivePart(part) def actionAddSquarePartSlot(self): """docstring for actionAddSquarePartSlot""" part = self._document.addDnaSquarePart() self.setActivePart(part) ### METHODS ### def undoStack(self): return self._document.undoStack() def newDocument(self, doc=None, fname=None): """Creates a new Document, reusing the DocumentController.""" if app().isInMaya(): app().deleteAllMayaNodes() self._document.removeAllParts() # clear out old parts self._undoStack.clear() # reset undostack del self.sliceGraphicsItem del self.pathHelixGroup self.sliceGraphicsItem = None self.pathHelixGroup = None self.solidHelixGroup = None self._filename = fname if fname else "untitled.nno" self._hasNoAssociatedFile = fname == None self._activePart = None self.win.setWindowTitle(self.documentTitle() + "[*]") if doc != None and doc.parts(): part = doc.parts()[0] self._activePart = part self.setDocument(doc) part.needsFittingToView.emit() # must come after setDocument else: self.setDocument(Document()) def windowCloseEventHandler(self, event): """Intercept close events when user attempts to close the window.""" if self.maybeSave(): event.accept() if app().isInMaya(): self.windock.setVisible(False) del self.windock app().documentControllers.remove(self) else: event.ignore() ### slot callbacks ### def actionNewSlotCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if hasattr(self, "filesavedialog"): # user did save self.filesavedialog.finished.disconnect(self.actionNewSlotCallback) del self.filesavedialog # prevents hang (?) self.newDocument() def saveFileDialogCallback(self): """docstring for saveFileDialogCallback""" if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if fname.isEmpty() or os.path.isdir(fname): return False fname = str(fname) if not fname.lower().endswith(".nno"): fname += ".nno" if self.filesavedialog != None: self.filesavedialog.filesSelected.disconnect(self.saveFileDialogCallback) del self.filesavedialog # prevents hang self.writeDocumentToFile(fname) def openAfterMaybeSaveCallback(self): """docstring for openAfterMaybeSaveCallback""" if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if not fname or os.path.isdir(fname): return False fname = str(fname) doc = decode(file(fname).read()) self.newDocument(doc, fname) doc.finalizeImport() # updates staple highlighting if self.fileopendialog != None: self.fileopendialog.filesSelected.disconnect(self.openAfterMaybeSaveCallback) # manual garbage collection to prevent hang (in osx) del self.fileopendialog ### file input ## def documentTitle(self): fname = os.path.basename(str(self.filename())) if not self.undoStack().isClean(): fname += "[*]" return fname def filename(self): return self._filename def setFilename(self): if self._filename == proposedFName: return True self._filename = proposedFName self._hasNoAssociatedFile = False self.win.setWindowTitle(self.documentTitle()) return True def openAfterMaybeSave(self): """docstring for openAfterMaybeSave""" if util.isWindows(): # required for native looking file window fname = QFileDialog.getOpenFileName( None, "Open Document", "/", "CADnano1 / CADnano2 Files (*.nno *.json *.cadnano)" ) self.filesavedialog = None self.openAfterMaybeSaveCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog(self.win, "Open Document", "/", "CADnano1 / CADnano2 Files (*.nno *.json *.cadnano)") fdialog.setAcceptMode(QFileDialog.AcceptOpen) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) # fdialog.exec_() # or .show(), or .open() self.fileopendialog = fdialog self.fileopendialog.filesSelected.connect(self.openAfterMaybeSaveCallback) fdialog.open() # or .show(), or .open() def openAfterMaybeSaveCallback(self): if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if not fname or os.path.isdir(fname): return False fname = str(fname) doc = decode(file(fname).read()) # DocumentController(doc, fname) self.newDocument(doc, fname) doc.finalizeImport() # updates staple highlighting if self.fileopendialog != None: self.fileopendialog.filesSelected.disconnect(self.openAfterMaybeSaveCallback) # manual garbage collection to prevent hang (in osx) del self.fileopendialog ### file output ### def maybeSave(self): """Save on quit, check if document changes have occured.""" if app().dontAskAndJustDiscardUnsavedChanges: return True if not self.undoStack().isClean(): # document dirty? savebox = QMessageBox( QMessageBox.Warning, "Application", "The document has been modified.\nDo you want to save your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self.win, Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet, ) savebox.setWindowModality(Qt.WindowModal) save = savebox.button(QMessageBox.Save) discard = savebox.button(QMessageBox.Discard) cancel = savebox.button(QMessageBox.Cancel) save.setShortcut("Ctrl+S") discard.setShortcut(QKeySequence("D,Ctrl+D")) cancel.setShortcut(QKeySequence("C,Ctrl+C,.,Ctrl+.")) ret = savebox.exec_() del savebox # manual garbage collection to prevent hang (in osx) if ret == QMessageBox.Save: return self.saveAsClicked() elif ret == QMessageBox.Cancel: return False return True def writeDocumentToFile(self, filename=None): if filename == None: assert not self._hasNoAssociatedFile filename = self.filename() try: f = open(filename, "w") encode(self._document, f) f.close() except IOError: flags = Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet errorbox = QMessageBox( QMessageBox.Critical, "CaDNAno", "Could not write to '%s'." % filename, QMessageBox.Ok, self.win, flags ) errorbox.setWindowModality(Qt.WindowModal) errorbox.open() return False self.undoStack().setClean() self.setFilename(filename) return True def saveFileDialog(self): """Spawn a QFileDialog to allow user to choose a filename and path.""" fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.nno)" % QApplication.applicationName(), ) self.writeDocumentToFile(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.nno)" % QApplication.applicationName(), ) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) # fdialog.exec_() # or .show(), or .open() self.filesavedialog = fdialog self.filesavedialog.filesSelected.connect(self.saveFileDialogCallback) fdialog.open() def saveFileDialogCallback(self, selected): """If the user chose to save, write to that file.""" if isinstance(selected, QStringList) or isinstance(selected, list): fname = selected[0] else: fname = selected if fname.isEmpty() or os.path.isdir(fname): return False fname = str(fname) if not fname.lower().endswith(".nno"): fname += ".nno" if self.filesavedialog != None: self.filesavedialog.filesSelected.disconnect(self.saveFileDialogCallback) del self.filesavedialog # prevents hang self.writeDocumentToFile(fname) ### document related ### def document(self): """docstring for document""" return self._document def setDocument(self, doc): """docstring for setDocument""" print "in setDocument", doc self._document = doc ### part related ## def activePart(self): if self._activePart == None: self._activePart = self._document.selectedPart() return self._activePart def setActivePart(self, part): """docstring for setActivePart""" self._activePart = part
class DocumentController(): """ Connects UI buttons to their corresponding actions in the model. """ ### INIT METHODS ### def __init__(self): """docstring for __init__""" # initialize variables self._document = Document() self._document.setController(self) self._activePart = None self._filename = None self._fileOpenPath = None # will be set in _readSettings self._hasNoAssociatedFile = True self._pathViewInstance = None self._sliceViewInstance = None self._undoStack = None self.win = None self.fileopendialog = None self.filesavedialog = None self.settings = QSettings() self._readSettings() # call other init methods self._initWindow() if app().isInMaya(): self._initMaya() app().documentControllers.add(self) def _initWindow(self): """docstring for initWindow""" self.win = DocumentWindow(docCtrlr=self) self.win.setWindowIcon( QIcon('ui/mainwindow/images/cadnano2-app-icon.png')) app().documentWindowWasCreatedSignal.emit(self._document, self.win) self._connectWindowSignalsToSelf() self.win.show() def _initMaya(self): """ Initialize Maya-related state. Delete Maya nodes if there is an old document left over from the same session. Set up the Maya window. """ # There will only be one document if (app().activeDocument and app().activeDocument.win and not app().activeDocument.win.close()): return del app().activeDocument app().activeDocument = self import maya.OpenMayaUI as OpenMayaUI import sip ptr = OpenMayaUI.MQtUtil.mainWindow() mayaWin = sip.wrapinstance(int(ptr), QMainWindow) self.windock = QDockWidget("cadnano") self.windock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.windock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.windock.setWidget(self.win) mayaWin.addDockWidget(Qt.DockWidgetArea(Qt.LeftDockWidgetArea), self.windock) self.windock.setVisible(True) def destroyDC(self): self.disconnectSignalsToSelf() if self.win is not None: self.win.destroyWin() self.win = None # end def def disconnectSignalsToSelf(self): win = self.win if win is not None: win.actionNew.triggered.disconnect(self.actionNewSlot) win.actionOpen.triggered.disconnect(self.actionOpenSlot) win.actionClose.triggered.disconnect(self.actionCloseSlot) win.actionSave.triggered.disconnect(self.actionSaveSlot) win.actionSave_As.triggered.disconnect(self.actionSaveAsSlot) win.actionSVG.triggered.disconnect(self.actionSVGSlot) win.actionAutoStaple.triggered.disconnect( self.actionAutostapleSlot) win.actionExportStaples.triggered.disconnect( self.actionExportStaplesSlot) win.actionPreferences.triggered.disconnect(self.actionPrefsSlot) win.actionModify.triggered.disconnect(self.actionModifySlot) win.actionNewHoneycombPart.triggered.disconnect( self.actionAddHoneycombPartSlot) win.actionNewSquarePart.triggered.disconnect( self.actionAddSquarePartSlot) win.closeEvent = self.windowCloseEventHandler win.actionAbout.triggered.disconnect(self.actionAboutSlot) win.actionCadnanoWebsite.triggered.disconnect( self.actionCadnanoWebsiteSlot) win.actionFeedback.triggered.disconnect(self.actionFeedbackSlot) win.actionFilterHandle.triggered.disconnect( self.actionFilterHandleSlot) win.actionFilterEndpoint.triggered.disconnect( self.actionFilterEndpointSlot) win.actionFilterStrand.triggered.disconnect( self.actionFilterStrandSlot) win.actionFilterXover.triggered.disconnect( self.actionFilterXoverSlot) win.actionFilterScaf.triggered.disconnect( self.actionFilterScafSlot) win.actionFilterStap.triggered.disconnect( self.actionFilterStapSlot) win.actionRenumber.triggered.disconnect(self.actionRenumberSlot) # end def def _connectWindowSignalsToSelf(self): """This method serves to group all the signal & slot connections made by DocumentController""" self.win.actionNew.triggered.connect(self.actionNewSlot) self.win.actionOpen.triggered.connect(self.actionOpenSlot) self.win.actionClose.triggered.connect(self.actionCloseSlot) self.win.actionSave.triggered.connect(self.actionSaveSlot) self.win.actionSave_As.triggered.connect(self.actionSaveAsSlot) self.win.actionSVG.triggered.connect(self.actionSVGSlot) self.win.actionAutoStaple.triggered.connect(self.actionAutostapleSlot) self.win.actionExportStaples.triggered.connect( self.actionExportStaplesSlot) self.win.actionPreferences.triggered.connect(self.actionPrefsSlot) self.win.actionModify.triggered.connect(self.actionModifySlot) self.win.actionNewHoneycombPart.triggered.connect( self.actionAddHoneycombPartSlot) self.win.actionNewSquarePart.triggered.connect( self.actionAddSquarePartSlot) self.win.closeEvent = self.windowCloseEventHandler self.win.actionAbout.triggered.connect(self.actionAboutSlot) self.win.actionCadnanoWebsite.triggered.connect( self.actionCadnanoWebsiteSlot) self.win.actionFeedback.triggered.connect(self.actionFeedbackSlot) self.win.actionFilterHandle.triggered.connect( self.actionFilterHandleSlot) self.win.actionFilterEndpoint.triggered.connect( self.actionFilterEndpointSlot) self.win.actionFilterStrand.triggered.connect( self.actionFilterStrandSlot) self.win.actionFilterXover.triggered.connect( self.actionFilterXoverSlot) self.win.actionFilterScaf.triggered.connect(self.actionFilterScafSlot) self.win.actionFilterStap.triggered.connect(self.actionFilterStapSlot) self.win.actionRenumber.triggered.connect(self.actionRenumberSlot) ### SLOTS ### def undoStackCleanChangedSlot(self): """The title changes to include [*] on modification.""" self.win.setWindowModified(not self.undoStack().isClean()) self.win.setWindowTitle(self.documentTitle()) def actionAboutSlot(self): """Displays the about cadnano dialog.""" from ui.dialogs.ui_about import Ui_About dialog = QDialog() dialogAbout = Ui_About() # reusing this dialog, should rename dialog.setStyleSheet( "QDialog { background-image: url(ui/dialogs/images/cadnano2-about.png); background-repeat: none; }" ) dialogAbout.setupUi(dialog) dialog.exec_() filterList = ["strand", "endpoint", "xover", "virtualHelix"] def actionFilterHandleSlot(self): """Disables all other selection filters when active.""" fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover fH.setChecked(True) if fE.isChecked(): fE.setChecked(False) if fS.isChecked(): fS.setChecked(False) if fX.isChecked(): fX.setChecked(False) self._document.documentSelectionFilterChangedSignal.emit( ["virtualHelix"]) def actionFilterEndpointSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover if fH.isChecked(): fH.setChecked(False) if not fS.isChecked() and not fX.isChecked(): fE.setChecked(True) self._strandFilterUpdate() # end def def actionFilterStrandSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover if fH.isChecked(): fH.setChecked(False) if not fE.isChecked() and not fX.isChecked(): fS.setChecked(True) self._strandFilterUpdate() # end def def actionFilterXoverSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.actionFilterHandle fE = self.win.actionFilterEndpoint fS = self.win.actionFilterStrand fX = self.win.actionFilterXover if fH.isChecked(): fH.setChecked(False) if not fE.isChecked() and not fS.isChecked(): fX.setChecked(True) self._strandFilterUpdate() # end def def actionFilterScafSlot(self): """Remains checked if no other strand-type filter is active.""" fSc = self.win.actionFilterScaf fSt = self.win.actionFilterStap if not fSc.isChecked() and not fSt.isChecked(): fSc.setChecked(True) self._strandFilterUpdate() def actionFilterStapSlot(self): """Remains checked if no other strand-type filter is active.""" fSc = self.win.actionFilterScaf fSt = self.win.actionFilterStap if not fSc.isChecked() and not fSt.isChecked(): fSt.setChecked(True) self._strandFilterUpdate() # end def def _strandFilterUpdate(self): win = self.win filterList = [] if win.actionFilterEndpoint.isChecked(): filterList.append("endpoint") if win.actionFilterStrand.isChecked(): filterList.append("strand") if win.actionFilterXover.isChecked(): filterList.append("xover") if win.actionFilterScaf.isChecked(): filterList.append("scaffold") if win.actionFilterStap.isChecked(): filterList.append("staple") self._document.documentSelectionFilterChangedSignal.emit(filterList) # end def def actionNewSlot(self): """ 1. If document is has no parts, do nothing. 2. If document is dirty, call maybeSave and continue if it succeeds. 3. Create a new document and swap it into the existing ctrlr/window. """ # clear/reset the view! if len(self._document.parts()) == 0: return # no parts if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if self.filesavedialog != None: self.filesavedialog.finished.connect(self.newClickedCallback) else: # user did not save self.newClickedCallback() # finalize new def actionOpenSlot(self): """ 1. If document is untouched, proceed to open dialog. 2. If document is dirty, call maybesave and continue if it succeeds. Downstream, the file is selected in openAfterMaybeSave, and the selected file is actually opened in openAfterMaybeSaveCallback. """ if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if hasattr(self, "filesavedialog"): # user did save if self.filesavedialog != None: self.filesavedialog.finished.connect( self.openAfterMaybeSave) else: self.openAfterMaybeSave() # windows else: # user did not save self.openAfterMaybeSave() # finalize new def actionCloseSlot(self): """This will trigger a Window closeEvent.""" #print "closing" if util.isWindows(): #print "close win" if self.win is not None: self.win.close() if not app().isInMaya(): #print "exit app" import sys sys.exit(1) def actionSaveSlot(self): """SaveAs if necessary, otherwise overwrite existing file.""" if self._hasNoAssociatedFile: self.saveFileDialog() return self.writeDocumentToFile() def actionSaveAsSlot(self): """Open a save file dialog so user can choose a name.""" self.saveFileDialog() def actionSVGSlot(self): """docstring for actionSVGSlot""" fname = os.path.basename(str(self.filename())) if fname == None: directory = "." else: directory = QFileInfo(fname).path() fdialog = QFileDialog(self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.svg)" % QApplication.applicationName()) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.svgsavedialog = fdialog self.svgsavedialog.filesSelected.connect(self.saveSVGDialogCallback) fdialog.open() class DummyChild(QGraphicsItem): def boundingRect(self): return QRect(200, 200) # self.parentObject().boundingRect() def paint(self, painter, option, widget=None): pass def saveSVGDialogCallback(self, selected): if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected if not fname or fname is None or os.path.isdir(fname): return False fname = str(fname) if not fname.lower().endswith(".svg"): fname += ".svg" if self.svgsavedialog != None: self.svgsavedialog.filesSelected.disconnect( self.saveSVGDialogCallback) del self.svgsavedialog # prevents hang self.svgsavedialog = None generator = QSvgGenerator() generator.setFileName(fname) generator.setSize(QSize(200, 200)) generator.setViewBox(QRect(0, 0, 2000, 2000)) painter = QPainter() # Render through scene # painter.begin(generator) # self.win.pathscene.render(painter) # painter.end() # Render item-by-item painter = QPainter() styleOption = QStyleOptionGraphicsItem() q = [self.win.pathroot] painter.begin(generator) while q: graphicsItem = q.pop() transform = graphicsItem.itemTransform(self.win.sliceroot)[0] painter.setTransform(transform) if graphicsItem.isVisible(): graphicsItem.paint(painter, styleOption, None) q.extend(graphicsItem.childItems()) painter.end() def actionExportStaplesSlot(self): """ Triggered by clicking Export Staples button. Opens a file dialog to determine where the staples should be saved. The callback is exportStaplesCallback which collects the staple sequences and exports the file. """ # Validate that no staple oligos are loops. part = self.activePart() stapLoopOlgs = part.getStapleLoopOligos() if stapLoopOlgs: from ui.dialogs.ui_warning import Ui_Warning dialog = QDialog() dialogWarning = Ui_Warning() # reusing this dialog, should rename dialog.setStyleSheet( "QDialog { background-image: url(ui/dialogs/images/cadnano2-about.png); background-repeat: none; }" ) dialogWarning.setupUi(dialog) locs = ", ".join([o.locString() for o in stapLoopOlgs]) msg = "Part contains staple loop(s) at %s.\n\nUse the break tool to introduce 5' & 3' ends before exporting. Loops have been colored red; use undo to revert." % locs dialogWarning.title.setText("Staple validation failed") dialogWarning.message.setText(msg) for o in stapLoopOlgs: o.applyColor(styles.stapColors[0].name()) dialog.exec_() return # Proceed with staple export. fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") self.saveStaplesDialog = None self.exportStaplesCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.saveStaplesDialog = fdialog self.saveStaplesDialog.filesSelected.connect( self.exportStaplesCallback) fdialog.open() # end def def actionPrefsSlot(self): app().prefsClicked() def actionAutostapleSlot(self): part = self.activePart() if part: self.win.pathGraphicsView.setViewportUpdateOn(False) part.autoStaple() self.win.pathGraphicsView.setViewportUpdateOn(True) def actionModifySlot(self): """ Notifies that part root items that parts should respond to modifier selection signals. """ # uncomment for debugging # isChecked = self.win.actionModify.isChecked() # self.win.pathroot.setModifyState(isChecked) # self.win.sliceroot.setModifyState(isChecked) if app().isInMaya(): isChecked = self.win.actionModify.isChecked() self.win.pathroot.setModifyState(isChecked) self.win.sliceroot.setModifyState(isChecked) self.win.solidroot.setModifyState(isChecked) def actionAddHoneycombPartSlot(self): """docstring for actionAddHoneycombPartSlot""" part = self._document.addHoneycombPart() self.setActivePart(part) def actionAddSquarePartSlot(self): """docstring for actionAddSquarePartSlot""" part = self._document.addSquarePart() self.setActivePart(part) def actionRenumberSlot(self): coordList = self.win.pathroot.getSelectedPartOrderedVHList() part = self.activePart() part.renumber(coordList) # end def ### ACCESSORS ### def document(self): return self._document def window(self): return self.win def setDocument(self, doc): """ Sets the controller's document, and informs the document that this is its controller. """ self._document = doc doc.setController(self) def activePart(self): if self._activePart == None: self._activePart = self._document.selectedPart() return self._activePart def setActivePart(self, part): self._activePart = part def undoStack(self): return self._document.undoStack() ### PRIVATE SUPPORT METHODS ### def newDocument(self, doc=None, fname=None): """Creates a new Document, reusing the DocumentController.""" self._document.resetViews() self._document.removeAllParts() # clear out old parts self._document.undoStack().clear() # reset undostack self._filename = fname if fname else "untitled.json" self._hasNoAssociatedFile = fname == None self._activePart = None self.win.setWindowTitle(self.documentTitle() + '[*]') def saveFileDialog(self): fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.json)" % QApplication.applicationName()) self.writeDocumentToFile(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.json)" % QApplication.applicationName()) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.filesavedialog = fdialog self.filesavedialog.filesSelected.connect( self.saveFileDialogCallback) fdialog.open() # end def def _readSettings(self): self.settings.beginGroup("FileSystem") self._fileOpenPath = self.settings.value("openpath", QDir().homePath()) self.settings.endGroup() def _writeFileOpenPath(self, path): """docstring for _writePath""" self._fileOpenPath = path self.settings.beginGroup("FileSystem") self.settings.setValue("openpath", path) self.settings.endGroup() ### SLOT CALLBACKS ### def actionNewSlotCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if self.filesavedialog != None: self.filesavedialog.finished.disconnect(self.actionNewSlotCallback) del self.filesavedialog # prevents hang (?) self.filesavedialog = None self.newDocument() def exportStaplesCallback(self, selected): """Export all staple sequences to selected CSV file. Args: selected (Tuple, List or str): if a List or Tuple, the filename should be the first element """ if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected # Return if fname is '', None, or a directory path if not fname or fname is None or os.path.isdir(fname): return False if not fname.lower().endswith(".txt"): fname += ".txt" if self.saveStaplesDialog is not None: self.saveStaplesDialog.filesSelected.disconnect( self.exportStaplesCallback) # manual garbage collection to prevent hang (in osx) del self.saveStaplesDialog self.saveStaplesDialog = None # write the file ap = self.activePart() if ap is not None: output = ap.getStapleSequences() with open(fname, 'w') as f: f.write(output) # end def def newClickedCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if self.filesavedialog != None: self.filesavedialog.finished.disconnect(self.newClickedCallback) del self.filesavedialog # prevents hang (?) self.filesavedialog = None self.newDocument() def openAfterMaybeSaveCallback(self, selected): """ Receives file selection info from the dialog created by openAfterMaybeSave, following user input. Extracts the file name and passes it to the decode method, which returns a new document doc, which is then set as the open document by newDocument. Calls finalizeImport and disconnects dialog signaling. """ if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected if fname is None or fname == '' or os.path.isdir(fname): return False if not os.path.exists(fname): return False self._writeFileOpenPath(os.path.dirname(fname)) self.newDocument(fname=fname) with io.open(fname, 'r', encoding='utf-8') as fd: decode(self._document, fd.read()) if hasattr(self, "filesavedialog"): # user did save if self.fileopendialog is not None: self.fileopendialog.filesSelected.disconnect( self.openAfterMaybeSaveCallback) # manual garbage collection to prevent hang (in osx) del self.fileopendialog self.fileopendialog = None def saveFileDialogCallback(self, selected): """If the user chose to save, write to that file.""" if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected if fname is None or os.path.isdir(fname): return False if not fname.lower().endswith(".json"): fname += ".json" if self.filesavedialog is not None: self.filesavedialog.filesSelected.disconnect( self.saveFileDialogCallback) del self.filesavedialog # prevents hang self.filesavedialog = None self.writeDocumentToFile(fname) self._writeFileOpenPath(os.path.dirname(fname)) ### EVENT HANDLERS ### def windowCloseEventHandler(self, event): """Intercept close events when user attempts to close the window.""" if self.maybeSave(): event.accept() if app().isInMaya(): self.windock.setVisible(False) del self.windock self.windock = None the_app = app() self.destroyDC() if the_app.documentControllers: the_app.destroyApp() else: event.ignore() self.actionCloseSlot() ### FILE INPUT ## def documentTitle(self): fname = os.path.basename(str(self.filename())) if not self.undoStack().isClean(): fname += '[*]' return fname def filename(self): return self._filename def setFilename(self, proposedFName): if self._filename == proposedFName: return True self._filename = proposedFName self._hasNoAssociatedFile = False self.win.setWindowTitle(self.documentTitle()) return True def openAfterMaybeSave(self): """ This is the method that initiates file opening. It is called by actionOpenSlot to spawn a QFileDialog and connect it to a callback method. """ path = self._fileOpenPath if util.isWindows(): # required for native looking file window#"/", fname = QFileDialog.getOpenFileName( None, "Open Document", path, "cadnano1 / cadnano2 Files (*.nno *.json *.cadnano)") self.filesavedialog = None self.openAfterMaybeSaveCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "Open Document", path, "cadnano1 / cadnano2 Files (*.nno *.json *.cadnano)") fdialog.setAcceptMode(QFileDialog.AcceptOpen) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.fileopendialog = fdialog self.fileopendialog.filesSelected.connect( self.openAfterMaybeSaveCallback) fdialog.open() # end def ### FILE OUTPUT ### def maybeSave(self): """Save on quit, check if document changes have occured.""" if app().dontAskAndJustDiscardUnsavedChanges: return True if not self.undoStack().isClean(): # document dirty? savebox = QMessageBox( QMessageBox.Warning, "Application", "The document has been modified.\nDo you want to save your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self.win, Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet) savebox.setWindowModality(Qt.WindowModal) save = savebox.button(QMessageBox.Save) discard = savebox.button(QMessageBox.Discard) cancel = savebox.button(QMessageBox.Cancel) save.setShortcut("Ctrl+S") discard.setShortcut(QKeySequence("D,Ctrl+D")) cancel.setShortcut(QKeySequence("C,Ctrl+C,.,Ctrl+.")) ret = savebox.exec_() del savebox # manual garbage collection to prevent hang (in osx) if ret == QMessageBox.Save: return self.actionSaveAsSlot() elif ret == QMessageBox.Cancel: return False return True def writeDocumentToFile(self, filename=None): if filename == None: assert (not self._hasNoAssociatedFile) filename = self.filename() try: if util.isWindows(): filename = filename[0] with open(filename, 'w') as f: helixOrderList = self.win.pathroot.getSelectedPartOrderedVHList( ) encode(self._document, helixOrderList, f) except IOError: flags = Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet errorbox = QMessageBox(QMessageBox.Critical, "cadnano", "Could not write to '%s'." % filename, QMessageBox.Ok, self.win, flags) errorbox.setWindowModality(Qt.WindowModal) errorbox.open() return False self.undoStack().setClean() self.setFilename(filename) return True def actionCadnanoWebsiteSlot(self): import webbrowser webbrowser.open("http://cadnano.org/") def actionFeedbackSlot(self): import webbrowser webbrowser.open("http://cadnano.org/feedback")